Use Caddy instead of NGINX as your reverse proxy

Here are some notes about how I got my test Discourse instance running with Caddy Server.

Cool stuff about Caddy:

Cons:

  • Not as battle tested as apache, nginx and cia.

How To

Preparing Discourse

First, you need to apply this changes to your app.yml:

templates:
  - "templates/postgres.template.yml"
  - "templates/redis.template.yml"
  - "templates/web.template.yml"
  - "templates/web.ratelimited.template.yml"
  - "templates/web.socketed.template.yml" # <<<----- THIS IS NEW

## Leave these two commented out
#  - "templates/web.ssl.template.yml"
#  - "templates/web.letsencrypt.ssl.template.yml"

## Leave these two commented out 
expose:
#  - "8080:80"   # http
#  - "443:443" # https

env:
  ## This should be commented out
  #LETSENCRYPT_ACCOUNT_EMAIL: mymail@gmail.com
  ## This is required to avoid mixed content warnings when behind a reverse proxy
  DISCOURSE_FORCE_HTTPS: true

Preparing Caddy

In the spirit of Discourse, let’s put Caddy in a Docker image too :whale2:

First prepare with:

mkdir -p /var/caddy/data /var/caddy/config
nano /var/caddy/Caddyfile

Add the following to the Caddyfile (using Caddy v2 syntax):

{
  email MYEMAILHERE@gmail.com
}

forum.example.com { # your domain here
  reverse_proxy unix//sock/nginx.http.sock
}

Save and exit.

Let’s test

Now you need to rebuild Discourse:

cd /var/discourse
./launcher rebuild app

And then run Caddy:

docker run -d \
    -v /var/caddy/Caddyfile:/etc/caddy/Caddyfile \
    -v /var/caddy/data:/data \
    -v /var/caddy/config:/config \
    -v /var/discourse/shared/standalone:/sock \
    -p 80:80 -p 443:443 \
    -p 443:443/udp \
    --restart=always \
    --name caddy \
    caddy:latest

After all, your forum should be avaliable at your domain, using SSL + HTTP2 + QUIC. You can’t more hipster than that.

Last edited by @pacharanero 2026-04-19T13:38:22Z

Check documentPerform check on document:
23개의 좋아요

I run Caddy’s Discourse forums with this Caddyfile and no container:

forum.caddyserver.com

timeouts off
proxy / localhost:8080 {
	transparent
}

I just set up Discourse (with one easy tweak) and ran Caddy on the host machine.

^ This setup has been tested, and I can confirm it has been running with no glitches for months.

12개의 좋아요

I like how you’ve proxied to the socket and left the ports unexposed.

Neat little guide that one can use as a guideline to easily incorporate their Discourse installation to an existing Caddy proxy, too. Cheers!

3개의 좋아요

But using nginx, as I can see now.

Well, I have more than 1 Discourse install with Caddy in the front, but I didn’t bother to replace the server header and it still shows nginx. Can be the same. Or they are just using the simple Discourse install and have no need to run a reverse proxy at all in the front.

1개의 좋아요

My Discourse sites behind Caddy show nginx as the server too. I guess that transparent setting might make Caddy, uh, transparent.

3개의 좋아요

That might be a bug from a recent change, it didn’t used to do that. :thinking:

2개의 좋아요

Dear @Falco

Thank you so much for your posting.

I would like to install discourse using caddy condition, but I was confused with your docker command.

I never heard about the caddy, so I follow the digital ocean document

My question is, in the current server situation, Should I change the path
from etc/Caddyfile to /etc/caddy/Caddyfile?

docker run -d \
    -v /var/caddy/Caddyfile:/etc/Caddyfile \
    -v /var/caddy:/root/.caddy \
    -v /var/discourse/shared/standalone:/sock \
    -p 80:80 -p 443:443 \
    -p 80:80/udp -p 443:443/udp \
    --restart=always \
    --name caddy \
    --entrypoint "/usr/local/bin/caddy" \
    abiosoft/caddy -quic -email MYEMAILHERE@gmail.com -agree --conf /etc/Caddyfile --log stdout

Sincerely

이것은 제 서버에서 작동하지 않았습니다. 저는 다음을 사용했습니다:

unix:/var/discourse/shared/standalone/nginx.http.sock

이것은 caddy v1용입니다. caddy v2의 경우, 다음을 사용하세요:

unix//var/discourse/shared/standalone/nginx.http.sock

단순히 ":"를 "/"로 교체하면 됩니다.

1개의 좋아요

OP의 가이드를 따르면서 Caddy를 Docker로 실행하고 볼륨을 지정된 대로 마운트한 경우, 해당 경로는 작동합니다. 가이드를 따르지 않는 경우, 경로는 다를 수 있습니다.

3개의 좋아요

그들의 포럼 도메인과 서브도메인은 이제 여기에 이름이 등록되어 있습니다.

1개의 좋아요

오래된 스레드를 건드려서 죄송합니다. Caddy를 Discourse와 함께 사용하려고 시도하고 있습니다. Caddy 설정에서 "proxy"를 사용했지만, 제가 사용했을 때 문법 오류가 발생하고 유효하지 않다고 표시됩니다. "proxy"가 이제 "reverse_proxy"로 변경된 것이 아닌가요?

제 설정은 다음과 같습니다:

forum.example.com {
    reverse_proxy / unix//var/discourse/shared/standalone/nginx.http.sock {
        transparent
    }
}

그렇다고 생각합니다. 직접 시도해 보셨나요?

1개의 좋아요

맷, 감사합니다!
컨테이너 없이 설정해도 2025년에 여전히 잘 작동한다는 것을 확인했습니다 :smiley:

forum.website.com {
        reverse_proxy localhost:8080
}

"proxy"만 사용해서는 작동하지 않았습니다.

저에게도 잘 작동합니다!

다만, 해당 매우 간단한 설정을 따랐을 때 “Mixed Content” 경고가 발생했습니다:


이 문제를 해결하기 위해 설정 파일(app.yml 또는 web_only.yml)의 env 섹션에 추가 지시문을 넣어야 했습니다:

# FORCE SSL 
DISCOURSE_FORCE_HTTPS: true

참고로, Caddy를 리버스 프록시로 사용하는 비-도커(Docker) 기반 환경의 현재 단계는 다음과 같습니다:

1) Discourse 설정 파일 조정

  • 인증서 주석 처리
    templates:
    #  - "templates/web.ssl.template.yml"
    #  - "templates/web.letsencrypt.ssl.template.yml"
    
  • 포트 매핑 변경 및 443 매핑 비활성화
    expose:
    - "8080:80"   # http
    # - "443:443" # https
    
  • 정적 파일 서빙 시 HTTPS 강제
    env: 
    DISCOURSE_FORCE_HTTPS: true
    

2) Discourse 재빌드

./launcher rebuild app

3) Caddy 설정

  • Caddy 설치: 공식 기본값을 그대로 사용합니다: Install — Caddy Documentation

  • /etc/caddy/Caddyfile 조정

    forum.example.com {
          reverse_proxy localhost:8080
    }
    

    멀티사이트를 사용하는 경우, 도메인을 나열하면 됩니다:

    forum.example.com, forum2.example.com, forum3.example.com {
          reverse_proxy localhost:8080
    }
    

    기본 설정 파일 위치를 확인하려면 systemctl status caddy를 실행할 수도 있습니다.

4) Caddy 실행

systemctl start caddy

변경 사항 후 설정 재로드:

cd /etc/caddy
caddy reload
4개의 좋아요

안녕하세요, 튜토리얼 감사합니다.

멀티사이트 환경이 아닌 경우 Caddy를 사용하는 데 어떤 이점이 있나요? 성능이나 다른 장점이 있을까요?

그건 잘 모르겠어요. 이제 제 스테이징 서버에서는 이 설정을 사용하고 있어요. 인스턴스를 추가하거나 변경할 때 인증서 관련 문제에 부딪히지 않아서 정말 쉽거든요.

2개의 좋아요

멀티사이트 환경에서 SSL 설정을 간소화하기 위해 비슷한 작업을 해본 적이 있습니다…
… 단, Caddy v2로 업데이트하고 docker-compose를 멀티사이트 환경에 맞게 구성했습니다.

web.yml 파일에서는 다음과 같이 설정했습니다:

  • templates/web.socketed.template.yml만 사용하고 SSL 관련 yml 파일은 사용하지 않습니다.
  • 포트 "443:443", "80:80" 등을 주석 처리합니다.
  • DISCOURSE_HOSTNAME_ALIASES와 DISCOURSE_FORCE_HTTPS: true를 추가합니다.

이 구성은 최신 버전의 Caddy 2를 사용하므로, 이 주제에서 앞서 언급된 Caddy v1 설정들과는 외관이 다를 수 있습니다.

다음은 초기에 필요한 파일들을 생성하고 caddy를 시작하는 bash 스크립트입니다:

#!/usr/bin/env bash

# 필요한 디렉터리 생성
mkdir -p /var/caddy
mkdir -p /var/caddy/data
mkdir -p /var/caddy/config



# 단순화된 Caddyfile 생성
cat > /var/caddy/Caddyfile << 'EOF'
{
    email your-email-address-here@example.com
}

community1.example.com, community2.example.com, community3.example.com {
    reverse_proxy unix//sock/nginx.http.sock
}
EOF

# docker-compose.yml 생성
cat > /var/caddy/docker-compose.yml << 'EOF'
services:
  caddy:
    image: caddy:latest
    container_name: caddy-proxy
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
      - "443:443/udp"
    volumes:
      - /var/caddy/Caddyfile:/etc/caddy/Caddyfile
      - /var/caddy/data:/data
      - /var/caddy/config:/config
      - /var/discourse/shared/standalone:/sock
EOF

# caddy 디렉터리로 이동하고 시작
cd /var/caddy

# Caddy 시작
docker compose up -d
2개의 좋아요

감사합니다! Nginx에서 Caddy로 전환하고 싶습니다. 여전히 unix//sock/nginx.http.sock가 남아 있네요. Nginx와 Caddy를 함께 사용 중이신 건가요?