Docker Linux Caddy 反向代理 Nginx HTTPS

用 Caddy 取代 Nginx 做反向代理:自動 HTTPS 讓憑證管理從此消失

Nginx 強大但設定繁瑣,Certbot 又是一層維護負擔。Caddy 內建自動 HTTPS、語法簡潔,對中小型部署來說是更實際的選擇。本文完整說明 Caddy 的核心概念、實際設定範例,以及與 Docker 整合的正確方式。

Nginx 是反向代理的預設答案已經超過十年,但它從來不是最省事的選擇。每次新增一個服務,你得寫 server block、跑 Certbot、確認 renewal cron 沒有失效、測試設定沒有 syntax error 才能 reload。這套流程沒有錯,只是在 Let’s Encrypt 普及、單機部署多服務已是常態的今天,顯得過於繁瑣。

Caddy 的核心設計目標就是讓這些摩擦消失。一個網域三行設定,HTTPS 自動申請、自動續期,HTTP redirect 也不用手動寫。本文不是要說 Nginx 不好——在高流量、需要細粒度調校的場景 Nginx 仍然是首選。但對於 VPS 上跑幾個服務的開發者和中小企業,Caddy 值得認真評估。

Caddy 的自動 HTTPS 到底做了什麼

Caddy 在啟動時,會自動對所有設定了公開網域名稱的站台:

  1. 向 Let’s Encrypt(或 ZeroSSL)申請 TLS 憑證
  2. 完成 ACME HTTP-01 挑戰(你需要確保 80 port 可以從外部連入)
  3. 把憑證存放在 ~/.local/share/caddy(或 Docker volume)
  4. 設定自動 renewal,憑證到期前 30 天自動更新
  5. 強制 HTTP 轉向 HTTPS,不需要任何額外設定

整個過程在 Caddy 第一次啟動時就完成,後續完全不需要管理。這不是魔法,背後用的就是每個人都在用的 Let’s Encrypt,只是 Caddy 把這層操作完全內化了。

Caddyfile 語法:真的只要這樣

反向代理到本機 3000 port,全站 HTTPS:

1
2
3
example.com {
reverse_proxy localhost:3000
}

就這樣。對比 Nginx 加 Certbot 的完整設定,這三行涵蓋了至少 40 行的工作量:HTTP → HTTPS redirect、憑證申請、TLS 設定、proxy header 轉發全部預設處理好。

多個網域代理到不同服務:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
api.example.com {
reverse_proxy localhost:8080
}

app.example.com {
reverse_proxy localhost:3000
}

admin.example.com {
reverse_proxy localhost:4000
basicauth {
admin JDJhJDE0JHBhc3N3b3JkX2hhc2g
}
}

每個網域各自申請獨立憑證,互不影響。basicauth 指令直接在 Caddyfile 裡設定,不需要另外建 htpasswd 檔。

需要加 header(例如讓後端應用知道原始 IP):

1
2
3
4
5
6
7
8
9
10
api.example.com {
reverse_proxy localhost:8080 {
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
}
header {
Strict-Transport-Security "max-age=31536000; includeSubDomains"
X-Content-Type-Options "nosniff"
}
}

AI 相關服務或其他需要長時間連線的場景,可以調整 timeout:

1
2
3
4
5
6
7
8
ai-api.example.com {
reverse_proxy localhost:11434 {
transport http {
read_timeout 5m
write_timeout 5m
}
}
}

在 VPS 上安裝 Caddy(不用 Docker)

1
2
3
4
5
6
7
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | \
sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | \
sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy

設定檔路徑是 /etc/caddy/Caddyfile,修改完後:

1
2
3
sudo caddy fmt --overwrite /etc/caddy/Caddyfile  # 格式化
sudo caddy validate --config /etc/caddy/Caddyfile # 語法檢查
sudo systemctl reload caddy # 熱重載,不中斷連線

不像 Nginx 需要 nginx -t 確認語法再 reload,Caddy 的 validate 指令會在套用前做完整驗證,reload 是真正的 zero-downtime reload。

與 Docker Compose 整合

這是最常見的使用場景:把 Caddy 放在 Docker Compose stack 裡,反代其他服務。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
services:
caddy:
image: caddy:2.11-alpine
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "443:443/udp" # HTTP/3 (QUIC)
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data # 存放憑證,必須 persist
- caddy_config:/config
networks: [proxy]
cap_drop: [ALL]
cap_add: [NET_BIND_SERVICE]

api:
image: myapp:v1.2.3
networks: [proxy]
# 注意:不需要 ports 設定,Caddy 透過 Docker network 直接連

volumes:
caddy_data:
caddy_config:

networks:
proxy:

對應的 Caddyfile(容器名稱直接作為 upstream hostname):

1
2
3
api.example.com {
reverse_proxy api:8080
}

caddy_data volume 一定要 persist。Caddy 把憑證存在這裡,如果用 docker compose down -v 刪掉它,下次啟動會重新申請憑證。Let’s Encrypt 有速率限制(每個 registered domain 每週 50 張),開發時頻繁重建 stack 很容易撞到。

443:443/udp 開啟 HTTP/3 支援,Caddy 2.7+ 預設啟用,讓支援 QUIC 的瀏覽器能使用更快的連線。

本機開發用 HTTPS

Caddy 可以替本機服務簽發由本機 CA 信任的憑證:

1
caddy trust  # 安裝 Caddy 的本機 CA 到系統信任清單
1
2
3
localhost {
reverse_proxy localhost:3000
}

這樣 https://localhost 就能有效的 HTTPS,不會出現憑證警告,測試 HSTS、Secure cookie 等只能在 HTTPS 環境跑的功能時特別有用。

Nginx 換到 Caddy 需要考慮的事

幾個 Nginx 能做但 Caddy 目前比較麻煩或不同的地方:

複雜的條件式路由:Nginx 可以用 ifmapgeo 模組做複雜的條件判斷。Caddy 有 @matcher 語法,但邏輯深的場景設定會比較冗長。

fine-grained 快取設定:Nginx 有成熟的 proxy cache 模組,Caddy 的快取功能是社群外掛,需要自行編譯。如果你現有 Nginx 有複雜的快取規則,遷移成本較高。

已有的 Certbot 憑證無法直接移轉:Caddy 和 Certbot 各自管理憑證,切換時 Caddy 會重新申請。要注意 Let’s Encrypt 速率限制,特別是子網域多的情況。

Lua/OpenResty:如果用到 OpenResty 的能力,Caddy 沒有對等方案。

以上這些對大多數 VPS 上的常規部署不構成問題。如果你的 Nginx 設定只是幾個 server block 加 SSL,遷移到 Caddy 大概花半小時。


NCSE Network 的 VPS 搭載 NVMe SSD,適合跑 Caddy 這類長期維運成本低的輕量服務。如果你正在規劃新的服務部署環境,歡迎參考 ncse.tw 的方案。

需要穩定的雲端主機?

NCSE Network 提供企業級 VPS,7 天免費試用,臺灣是方電訊機房,99% SLA 保證。

查看 VPS 方案 →