misOrz

IT Tech & Life

Caddy vs Nginx:自架服務該選哪一個?

Caddy vs Nginx: Which One Should You Pick for Self-Hosted Services?

If you have ever been woken up by an expired certificate, you already know what this comparison is really about. Caddy and Nginx do the same job: they sit in front of your services, terminate TLS, and route traffic. The difference is how much of that work they do for you.

What Is Caddy?

Caddy is an open-source web server written in Go, first released in 2015. It was the first web server to enable HTTPS automatically by default, and it now has over 75,000 stars on GitHub. Its headline feature is automatic HTTPS: write a domain name in the config file, and Caddy obtains a certificate from Let's Encrypt or ZeroSSL, renews it before expiry, and enables HTTP/2 and HTTP/3 — with no extra tooling.

What Is Nginx?

Nginx is an open-source web server written in C, first released in 2004. It is event-driven, famously light on memory, and remains one of the most widely deployed web servers and reverse proxies in the world. If you have used the internet, you have used Nginx. Its configuration is powerful and precise — and, frankly, more verbose.

Side-by-Side Comparison

Feature Caddy Nginx
Config difficulty Low, a few lines of Caddyfile Medium to high, detailed syntax
Automatic HTTPS Built in, zero setup No, needs Certbot or similar
Certificate renewal Automatic, handled internally Via Certbot cron / systemd timer
Config hot update Admin API, no reload needed nginx -s reload, graceful, keeps connections
HTTP/3 Enabled by default Experimental since 1.25, needs a build flag
Static file performance Fast, close behind Nginx Slightly ahead in raw benchmarks
Memory footprint Moderate (Go runtime) Very low
Modules / ecosystem Plugins via xcaddy (compile time) Huge ecosystem, dynamic modules
Config format Caddyfile, JSON, API nginx.conf
Enterprise adoption Growing Extremely high
Chinese learning resources Fewer Abundant

Certificates: The Question That Started This Article

Can Nginx renew certificates by itself? No. Nginx only reads certificate files from disk (ssl_certificate and ssl_certificate_key). It has no ACME client, so it cannot talk to Let's Encrypt at all.

The standard setup is Certbot plus a scheduled renewal:

certbot --nginx -d example.com
certbot renew --dry-run   # test that auto-renewal works

Certbot installs a systemd timer that checks twice a day and renews any certificate with less than 30 days left, then reloads Nginx. Let's Encrypt certificates last 90 days, so this automation is not optional — it is the whole point.

A lighter alternative is acme.sh, which also supports DNS API verification, useful when port 80 is not reachable from the internet.

Caddy, by contrast, does all of this internally. There is no Certbot, no cron job, and no renewal to forget. That is the core of its appeal.

Reverse Proxy: Three Lines vs a Server Block

Caddy — put api.example.com in front of a FastAPI app on port 8000:

api.example.com {
    reverse_proxy localhost:8000
}

Nginx — the same job:

server {
    listen 443 ssl;
    server_name api.example.com;
    ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;

    location / {
        proxy_pass http://localhost:8000;
    }
}

Both work. One of them also needed a certificate before it could start.

Docker

With Docker Compose, Caddy is one more service next to your app, with a named volume for its certificate store — that volume must persist, or every container rebuild will reissue certificates and hit rate limits:

services:
  api:
    build: .
    expose:
      - "8000"
  caddy:
    image: caddy:latest
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - caddy_data:/data
      - caddy_config:/config
volumes:
  caddy_data:
  caddy_config:

The equivalent Nginx setup needs the same compose file plus a Certbot container or a host-side renewal job.

Which One Should You Pick?

Pick Caddy if you self-host services (Vaultwarden, n8n, Nextcloud, a FastAPI backend), you want HTTPS without thinking about it, or you have been bitten by an expired certificate before. For a personal server, it is the faster path to a secure setup.

Pick Nginx if your team already knows it deeply, you need very fine-grained traffic control (complex rewrites, rate limiting, multi-layer caching), or you are running at a scale where its raw throughput and ecosystem matter more than convenience.

You do not have to choose once and forever. Caddy ships a config adapter that converts Nginx configuration to Caddy format, and the two can run side by side on different domains or ports while you migrate one service at a time.

Verdict

Nginx is the industry default for a reason, and it is not going anywhere. But for self-hosted services, Caddy removes the single most annoying chore in the whole stack — certificate management — and that alone is worth switching for. The moment your first certificate renews itself without you noticing, you will not want to go back.


Caddy vs Nginx:自架服務該選哪一個?

如果你曾經因為憑證過期半夜被叫起來,你就知道這篇比較真正在比的是什麼。Caddy 和 Nginx 做的是同一份工作:擋在你的服務前面,處理 TLS、轉發流量。差別在於,它們幫你做了多少。

什麼是 Caddy?

Caddy 是用 Go 寫的開源網頁伺服器,2015 年首次發佈,是史上第一個預設就自動啟用 HTTPS 的網頁伺服器,GitHub 上已有超過 75,000 顆星。它的最大賣點就是自動 HTTPS:設定檔寫上網域名稱,它就自動向 Let's Encrypt 或 ZeroSSL 申請憑證、到期前自動續期、自動啟用 HTTP/2 與 HTTP/3,不需要另外裝任何工具。

什麼是 Nginx?

Nginx 是用 C 寫的開源網頁伺服器,2004 年首次發佈,事件驅動、記憶體佔用極低,至今仍是全球最普及的網頁伺服器與反向代理之一。你用過網路,就用過 Nginx。它的設定功能強大精細,相對也比較囉嗦。

並排比較

比較項目 Caddy Nginx
設定難度 低,Caddyfile 幾行搞定 中高,語法細碎
自動 HTTPS 內建,零設定 沒有,需搭配 Certbot
憑證續期 內部自動處理 靠 Certbot cron/systemd timer
設定熱更新 管理 API 推送,免重啟 nginx -s reload,優雅重載、不斷連線
HTTP/3 預設支援 1.25 起實驗性支援,需編譯參數
靜態檔案效能 快,略遜於 Nginx 原始效能測試略勝一籌
記憶體佔用 中等(Go runtime) 極低
模組/生態系 外掛需 xcaddy 編譯期加入 生態系龐大,支援動態模組
設定格式 Caddyfile、JSON、API nginx.conf
企業普及度 持續成長中 極高
中文學習資源 較少 極多

憑證:這篇文章的起點

Nginx 能自己續憑證嗎?不行。Nginx 只會讀取磁碟上的憑證檔案(ssl_certificate 與 ssl_certificate_key),它本身沒有 ACME 客戶端,完全不會去跟 Let's Encrypt 打交道。

標準做法是 Certbot 加上排程續期:

certbot --nginx -d example.com
certbot renew --dry-run   # 測試自動續期是否正常

Certbot 會裝一個 systemd timer,每天檢查兩次,憑證剩下不到 30 天就自動續期,然後重載 Nginx。Let's Encrypt 憑證效期只有 90 天,所以自動化不是加分,是必要。

比較輕量的替代方案是 acme.sh,還支援 DNS API 驗證,80 埠不對外開放也能簽憑證。

Caddy 則是把這整件事都內建了。沒有 Certbot、沒有 cron、沒有會忘記的續期。這就是它最大的吸引力。

反向代理:三行 vs 一個 server 區塊

Caddy——把 api.example.com 轉給本機 8000 埠的 FastAPI:

api.example.com {
    reverse_proxy localhost:8000
}

Nginx——同樣的工作:

server {
    listen 443 ssl;
    server_name api.example.com;
    ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;

    location / {
        proxy_pass http://localhost:8000;
    }
}

兩個都能用,但其中一個在啟動之前,還得先有一張憑證。

Docker

用 Docker Compose 時,Caddy 就是你 App 旁邊多一個服務,憑證儲存一定要用具名 volume 持久化,否則每次重建容器都要重新簽發憑證,會撞上簽發速率限制:

services:
  api:
    build: .
    expose:
      - "8000"
  caddy:
    image: caddy:latest
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - caddy_data:/data
      - caddy_config:/config
volumes:
  caddy_data:
  caddy_config:

同樣的架構換成 Nginx,除了 Compose 檔,還得再加一個 Certbot 容器或主機上的續期排程。

該選哪一個?

選 Caddy,如果你自架服務(Vaultwarden、n8n、Nextcloud、FastAPI 後端都算),想要 HTTPS 但不想管憑證,或你曾經被過期憑證搞過。對個人伺服器來說,它是更快抵達安全上線的路。

選 Nginx,如果團隊對它已經很熟,需要非常細緻的流量控制(複雜 rewrite、限流、多層 cache),或規模大到原始吞吐量與生態系比方便性更重要。

不用一次定生死。Caddy 內建 config adapter,可以把 Nginx 設定轉成 Caddy 格式,兩個也可以先在不同網域或 port 上並存,一個服務一個服務慢慢搬。

結論

Nginx 是業界預設選擇,有它的道理,也不會消失。但對自架服務來說,Caddy 拿掉了整個架構裡最煩的一件事——憑證管理,光是這一點就值得換。等你第一次發現憑證自己續好了、你完全沒注意到,那一刻你就回不去了。