Caddy:一行配置搞定自动 HTTPS 的反向代理
反向代理解决三个问题:把多个服务收拢到 80/443、统一加 HTTPS、以及隔离内网服务与公网。
一、最常见的一套配置
example.com {
encode gzip zstd
reverse_proxy 127.0.0.1:8080
}
jellyfin.example.com {
reverse_proxy 127.0.0.1:8096
}
api.example.com {
reverse_proxy /v1/* 127.0.0.1:3000
reverse_proxy 127.0.0.1:3001
}
就这么几行,它自动做完这些事:申请 Let's Encrypt 证书、配置自动续期、把 HTTP 请求 301 到 HTTPS、开启 HTTP/2、压缩响应。域名解析指向这台机器,证书当天就能下来。
二、它比传统方案省掉的四件事
- 证书申请与续期:不需要另装客户端、不需要定时任务;
- 跳转规则:不用手写 80 端口的 server 块;
- 配置语法:一个站点一个块,不需要记 location 匹配优先级;
- HTTP/3:UDP 443 放行后自动启用。
三、WebSocket 与长连接
很多自建服务(消息推送、终端、监控面板)依赖 WebSocket。传统方案要手动加 Upgrade 头,这在 Caddy 里是自动的——reverse_proxy 会透传升级请求。
但要配超时,否则长连接会被断:
reverse_proxy 127.0.0.1:8080 {
transport http {
read_timeout 1h
write_timeout 1h
}
}
四、几个容易踩的点
1. 证书申请失败
八成是这三个原因:域名没解析到本机、80 端口被占用或没放通、或者短时间内申请次数超限(Let's Encrypt 有频率限制)。先手动验证 curl -I http://域名/.well-known/acme-challenge/ 能不能通。
2. 大文件上传失败
默认没有请求体大小限制,但反代链路里如果还有别的组件(比如另一个代理、或者应用自身限制),就会出现「传到一半失败」。逐个排查:应用配置 → Caddy → 上游服务。
3. 真实 IP 丢失
后端拿到的都是 127.0.0.1,日志里没法看来源。需要让 Caddy 设置转发头,并让后端信任它:
reverse_proxy 127.0.0.1:8080 {
header_up X-Real-IP {remote_host}
}
五、和内网服务的配合
安全上的正确姿势是:后端服务只监听 127.0.0.1,不映射到公网端口,所有外部访问都经过反向代理。
ports: ["127.0.0.1:8080:8080"] # 只绑本地
# 而不是 ports: ["8080:8080"] # 全网可达
这一条能挡掉大量自动扫描——扫描器只扫公网端口,不扫回环地址。
六、需要登录保护怎么办
它自带 basic auth,但对多服务场景不够用。更合适的做法是接一层统一认证,见 Authelia。
七、什么时候该选传统方案
如果你的场景有复杂的路径改写规则、需要大量 location 正则、或者要和现有 nginx 配置体系共存,那还是用传统方案。它的优势在「简单场景下省事」,不是「功能更全」。
关于自建服务的整体取舍,见 自建 vs SaaS;容器管理界面见 Dockge 与 Portainer。






评论