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:
22개의 좋아요

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

This not work on my server. For me, I used:

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

And this is for caddy v1. For caddy v2, please use:

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

Just replace “:” to “/”.

1개의 좋아요

That path works if you are following the guide in the OP and running Caddy in docker and mounting the volumes as specified. If you are not following the guide, there will be different paths, yes.

3개의 좋아요

Their forum domain and subdomain are now named under this.

1개의 좋아요

Sorry for bumping old threads, I’m trying to make Caddy work with Discourse. In your Caddy configuration, you use “proxy”, but when I use it, it says that there is a syntax error and that it’s not valid. Hasn’t “proxy” now been changed to “reverse_proxy”?

here’s my config:

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

I think so. Did you try it?

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_ALIASESDISCOURSE_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를 함께 사용 중이신 건가요?