痛点
运维老手都知道 Nginx + Certbot 的经典组合:配反向代理、写 cron 续签证书、每次加站点就要改一堆配置。问题来了:
- 证书管理是负担 — certbot renew 偶尔失败、DNS 验证要额外配置、多域名续签容易漏
- 配置语法重 — 一个简单的反代要写 10+ 行,server_name / proxy_pass / proxy_set_header 一个不能少
- reload 有风险 — 配置写错一个分号,
nginx -t过了但上线后 502,线上排查浪费时间
Caddy 是一个用 Go 编写的现代 Web 服务器,核心卖点:自动 HTTPS(含证书申请 + 续签)、极简配置、热重载零停机。在中小规模反代场景(< 50 个站点),Caddy 可以直接替代 Nginx + Certbot,配置量减少 80%。
方案
用 Caddy 做反向代理 + 自动 HTTPS,替换原有的 Nginx + Certbot 方案。核心优势:
| 维度 | Nginx + Certbot | Caddy |
|---|---|---|
| HTTPS 证书 | 手动配 certbot + cron | 自动申请、续签、部署 |
| 配置行数(单站点) | 15-20 行 | 3-5 行 |
| 热重载 | nginx -s reload(需 -t 验证) |
caddy reload(原子性,失败自动回滚) |
| 默认安全 | 需手动配 HSTS/OCSP | 默认启用 HSTS、OCSP Stapling、TLS 1.2+ |
实操步骤
第 1 步:安装 Caddy
# Ubuntu/Debian
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
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 -y
# 验证
caddy version
# v2.8.x
第 2 步:编写 Caddyfile 反代配置
sudo vim /etc/caddy/Caddyfile
假设你要反代 3 个服务:
# API 服务 - 自动 HTTPS
api.example.com {
reverse_proxy localhost:8080
}
# 前端应用
app.example.com {
reverse_proxy localhost:3000
}
# 管理后台 - 限制 IP 访问
admin.example.com {
@blocked not remote_ip 10.0.0.0/8 192.168.0.0/16
respond @blocked 403
reverse_proxy localhost:9090
}
就这么简单。不需要写 ssl_certificate 路径、不需要配 certbot、不需要 proxy_set_header — Caddy 全部自动处理。
第 3 步:启动并验证
# 格式化配置(检查语法)
caddy fmt --overwrite /etc/caddy/Caddyfile
# 验证配置
caddy validate --config /etc/caddy/Caddyfile
# 启动 / 重启服务
sudo systemctl restart caddy
sudo systemctl enable caddy
# 验证证书(首次启动会自动从 Let's Encrypt 申请)
curl -vI https://api.example.com 2>&1 | grep -E "subject:|expire"
# 查看证书存储
ls /var/lib/caddy/.local/share/caddy/certificates/
新增站点热重载
后续加站点,只需编辑 Caddyfile 然后:
caddy reload --config /etc/caddy/Caddyfile
# 零停机,配置有误会自动回滚,不影响线上流量
避坑
坑 1:80/443 端口被占用
Caddy 需要同时监听 80(用于 ACME HTTP-01 验证)和 443。如果 Nginx 还在跑:
# 先停 Nginx
sudo systemctl stop nginx && sudo systemctl disable nginx
# 确认端口释放
ss -tulnp | grep -E ':80|:443'
注意:不要同时跑 Nginx 和 Caddy 监听相同端口,会直接启动失败。
坑 2:DNS 未解析就启动 Caddy
Caddy 启动时会立即尝试申请证书。如果域名 DNS 还没指向服务器 IP,ACME 验证会失败,短时间内重试过多会被 Let's Encrypt 限速(每小时 5 次失败)。
# 先确认 DNS 已生效
dig +short api.example.com
# 应返回你服务器的公网 IP
# 如果要测试,先用 HTTP 模式
api.example.com:80 {
reverse_proxy localhost:8080
}
坑 3:后端服务返回 502/503
Caddy 默认不设置 Host 头透传,某些后端(如 Grafana、GitLab)依赖 Host 头做路由:
grafana.example.com {
reverse_proxy localhost:3000 {
header_up Host {upstream_hostport}
# 或者透传原始 Host
# header_up Host {host}
}
}
同时检查后端是否只监听 127.0.0.1:
ss -tlnp | grep 3000
# 确认是 0.0.0.0:3000 或 127.0.0.1:3000
总结
| 场景 | 推荐方案 |
|---|---|
| 中小规模反代(< 50 站点) | ✅ Caddy — 配置简洁、证书全自动 |
| 高并发/复杂路由(OpenResty 插件) | ⚠️ 仍用 Nginx — 生态成熟、性能极致 |
| 需要精细缓存策略 | ⚠️ Nginx 或专用 CDN |
核心结论:对于 90% 的反向代理 + HTTPS 场景,Caddy 的「零配置自动证书 + 3 行反代」体验完胜 Nginx + Certbot。运维成本从「写配置 + 管证书 + 排错」降到「写域名 + 指后端」,省下的时间去做更有价值的事。
迁移建议:先在测试环境跑一周验证稳定性,再逐步迁移生产站点。Caddy 的 JSON API 也支持动态配置,适合和 CI/CD 流水线集成实现站点自动发布。