在服务器部署 Web 服务时,我们经常会遇到这样一个需求:
程序已经运行在服务器的某个端口,例如:
http://127.0.0.1:8080但是对外访问时,希望变成:
https://api.example.com如果使用 Nginx,一般还需要:
- 配置 Nginx
- 安装 Certbot
- 申请 SSL 证书
- 配置证书路径
- 设置证书自动续期
- 配置 HTTP 跳转 HTTPS
而使用Caddy,这些工作可以简化很多。
Caddy 最大的特点之一就是支持Automatic HTTPS。只要配置中使用了一个有效域名,并且 DNS 已经正确指向服务器、80 和 443 端口可以访问,Caddy 就可以自动申请并管理 HTTPS 证书。
本文就通过一个实际案例,演示如何使用 Caddy:
域名 ↓ https://api.example.com ↓ Caddy ↓ http://127.0.0.1:8080 ↓ Python / Go / Java / Node.js 服务整个过程不需要手动下载 SSL 证书。
一、准备环境
假设现在有:
服务器公网 IP:203.0.113.10 域名: api.example.com 后端程序: http://127.0.0.1:8080我们的最终目标是:
https://api.example.com访问这个地址时,由 Caddy 转发到:
http://127.0.0.1:8080服务器这里以 Ubuntu 为例。
二、首先配置域名 DNS
在域名服务商后台添加一条 A 记录。
例如:
类型:A 主机记录: api 记录值: 203.0.113.10最终:
api.example.com解析到:
203.0.113.10可以通过下面的命令检查:
pingapi.example.com也可以:
nslookupapi.example.com例如:
Name: api.example.com Address: 203.0.113.10说明 DNS 已经基本生效。
这里非常重要。
如果域名没有正确解析到当前服务器,Caddy 就无法正常完成公网 HTTPS 证书的申请。
三、检查 80 和 443 端口
Caddy 对外主要使用:
80 HTTP 443 HTTPS因此需要保证服务器防火墙以及云服务器安全组已经放行这两个端口。Caddy 官方 HTTPS 文档同样要求公网 HTTPS 场景下域名正确解析,并确保 80、443 可以从外部访问。
如果 Ubuntu 开启了 UFW,可以执行:
sudoufw allow80/tcpsudoufw allow443/tcp查看:
sudoufw status如果使用的是阿里云、腾讯云、AWS、Azure 等云服务器,还需要检查云平台的:
安全组 Firewall Security Group确认:
TCP 80 TCP 443允许访问。
四、安装 Caddy
Ubuntu / Debian 推荐直接使用官方软件源安装,官方安装包同时支持将 Caddy 作为 systemd 服务运行。
首先安装依赖:
sudoaptinstall-ydebian-keyring debian-archive-keyring apt-transport-httpscurl添加 Caddy 官方 GPG Key:
curl-1sLf'https://dl.cloudsmith.io/public/caddy/stable/gpg.key'\|sudogpg--dearmor-o/usr/share/keyrings/caddy-stable-archive-keyring.gpg添加软件源:
curl-1sLf'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt'\|sudotee/etc/apt/sources.list.d/caddy-stable.list更新:
sudoaptupdate安装:
sudoaptinstallcaddy查看版本:
caddy version如果能够看到类似:
v2.x.x说明安装成功。
五、查看 Caddy 服务状态
安装完成后,可以执行:
systemctl status caddy如果正常,应该可以看到:
Active: active (running)也可以执行:
sudosystemctlenablecaddy设置开机启动。
然后:
sudosystemctl start caddy六、找到 Caddyfile
通过官方 Ubuntu 软件包安装后,我们一般直接编辑:
/etc/caddy/Caddyfile执行:
sudonano/etc/caddy/Caddyfile也可以使用 vim:
sudovim/etc/caddy/Caddyfile七、最简单的 HTTPS 配置
假设域名为:
api.example.com最简单的配置甚至可以写成:
api.example.com { respond "Hello HTTPS" }保存配置。
然后检查配置:
sudocaddy validate--config/etc/caddy/Caddyfile没有问题后重新加载:
sudosystemctl reload caddy现在浏览器访问:
https://api.example.com就应该可以看到:
Hello HTTPS注意我们整个过程中:
没有手动申请 SSL 证书。
也没有配置:
ssl_certificate ssl_certificate_key因为这些事情 Caddy 会自动处理。
八、Caddy 自动 HTTPS 的原理
这是 Caddy 相比传统 Web Server 非常方便的地方。
当 Caddyfile 中出现:
api.example.com { }这样的域名配置后,Caddy 会识别这是一个需要 HTTPS 的站点。
在满足公网证书申请条件时,它会自动完成类似下面的流程:
读取 Caddyfile ↓ 发现 api.example.com ↓ 检查域名 ↓ 向 CA 申请 TLS 证书 ↓ 安装证书 ↓ 启动 HTTPS ↓ 监听 443 ↓ HTTP 自动跳转 HTTPS而且证书生命周期由 Caddy 自动管理,不需要自己写一个定时任务每隔几个月执行 Certbot。Caddy 官方将这套能力称为 Automatic HTTPS,包括自动证书管理以及默认的 HTTP → HTTPS 重定向。
九、实战:反向代理到 8080
真实项目一般不会直接让 Caddy 返回文本。
例如我们有一个 Python 服务运行:
127.0.0.1:8080或者:
localhost:8080我们希望:
https://api.example.com转发到:
http://127.0.0.1:8080修改:
sudonano/etc/caddy/Caddyfile配置:
api.example.com { reverse_proxy 127.0.0.1:8080 }就这么几行。
Caddy 官方提供的 HTTPS reverse proxy 用法也是直接使用域名作为站点地址,然后通过reverse_proxy指向后端。
检查配置:
sudocaddy validate--config/etc/caddy/Caddyfile重新加载:
sudosystemctl reload caddy现在:
https://api.example.com实际上访问的是:
http://127.0.0.1:8080十、完整请求流程
现在服务器结构就变成:
浏览器 │ │ HTTPS ▼ https://api.example.com │ │ 443 ▼ Caddy Server │ │ HTTP ▼ 127.0.0.1:8080 │ ▼ 后端程序对于 Python、Go、Node.js 等程序来说,可以只监听:
127.0.0.1例如:
127.0.0.1:8080而不需要直接暴露:
8080到公网。
公网用户只访问:
443十一、加入 gzip / zstd 压缩
可以继续修改 Caddyfile:
api.example.com { encode zstd gzip reverse_proxy 127.0.0.1:8080 }然后:
sudocaddy validate--config/etc/caddy/Caddyfilesudosystemctl reload caddy对于 Web 页面、JSON、文本接口等,可以降低一定的网络传输量。
十二、同时配置多个域名
Caddy 配置多个网站同样非常方便。
例如:
api.example.com { reverse_proxy 127.0.0.1:8080 } admin.example.com { reverse_proxy 127.0.0.1:9000 } www.example.com { reverse_proxy 127.0.0.1:3000 }对应:
api.example.com ↓ localhost:8080 admin.example.com ↓ localhost:9000 www.example.com ↓ localhost:3000只需要保证这几个域名的 DNS 都已经指向当前服务器。
Caddy 会分别处理相应的 HTTPS 配置。
十三、配置 API 服务
如果部署的是 FastAPI、Flask、Go API 或 Node.js API,例如:
http://127.0.0.1:8083那么配置只需要:
api.example.com { reverse_proxy 127.0.0.1:8083 }前端调用:
https://api.example.com/api/users请求会经过:
Internet ↓ 443 ↓ Caddy ↓ 127.0.0.1:8083十四、后端使用 Docker 也没问题
例如 Docker:
dockerrun-d\--namemy-api\-p127.0.0.1:8080:8080\my-api:latest注意这里我特意写成:
127.0.0.1:8080:8080而不是:
8080:8080这样 8080 只绑定到本机。
公网不能直接:
http://服务器IP:8080访问。
但是 Caddy 可以:
api.example.com { reverse_proxy 127.0.0.1:8080 }整个结构就是:
Internet │ │ HTTPS :443 ▼ Caddy │ │ HTTP :8080 ▼ Docker Container这是我比较推荐的一种部署方式。
十五、修改 Caddyfile 后不要直接重启
每次修改配置后,最好先执行:
sudocaddy validate--config/etc/caddy/Caddyfile确认配置没有问题。
然后使用:
sudosystemctl reload caddy而不是:
sudosystemctl restart caddyreload可以让 Caddy 加载新的配置,同时减少服务中断。
正常流程:
sudonano/etc/caddy/Caddyfile然后:
sudocaddy validate--config/etc/caddy/Caddyfile最后:
sudosystemctl reload caddy可以记成:
修改 ↓ validate ↓ reload十六、查看 Caddy 日志
如果 HTTPS 申请失败,首先不要反复修改配置。
直接看日志:
sudojournalctl-ucaddy查看最近内容:
sudojournalctl-ucaddy-n100实时查看:
sudojournalctl-ucaddy-f这条命令非常有用:
sudojournalctl-ucaddy-f然后重新加载:
sudosystemctl reload caddy就能实时看到:
证书申请 域名验证 配置错误 端口占用 后端连接失败等信息。
十七、502 Bad Gateway 怎么解决?
如果浏览器出现:
502 Bad Gateway通常说明:
Caddy 已经正常工作,但是 Caddy 无法访问后端。
例如配置:
api.example.com { reverse_proxy 127.0.0.1:8080 }首先在服务器执行:
curlhttp://127.0.0.1:8080如果这里都失败:
Connection refused那么不是 Caddy 的问题。
而是后端:
8080根本没有启动。
执行:
ss-lntp|grep8080看看有没有程序监听:
127.0.0.1:8080十八、HTTPS 证书申请失败怎么办?
常见原因基本集中在以下几个方面。
1. DNS 没生效
检查:
nslookupapi.example.com确认解析出来的是当前服务器 IP。
2. 80 端口没有开放
检查:
sudoufw status以及云服务器:
Security Group3. 443 端口没有开放
同样需要检查:
TCP 4434. Nginx 占用了 80 / 443
检查:
sudoss-lntp|grep':80 '以及:
sudoss-lntp|grep':443 '如果看到:
nginx说明 Nginx 已经占用了端口。
如果准备完全使用 Caddy,可以先:
sudosystemctl stop nginx再启动 Caddy:
sudosystemctl restart caddy十九、检查 HTTPS
配置完成后,可以直接:
curl-Ihttps://api.example.com或者:
curl-vhttps://api.example.com如果正常,就会看到 TLS 握手以及 HTTP Response。
浏览器中打开:
https://api.example.com地址栏也应该出现 HTTPS 安全标识。
二十、只用一条命令也能启动 HTTPS 反向代理
如果只是测试,并不一定要写 Caddyfile。
Caddy 本身提供:
caddy reverse-proxy\--fromapi.example.com\--tolocalhost:8080这样同样可以快速创建一个 HTTPS reverse proxy。官方命令行文档也说明,当--from使用主机名时,Caddy 默认会尝试为该地址提供 HTTPS。
不过正式生产环境中,我还是更建议:
/etc/caddy/Caddyfile配合:
systemd运行。
方便管理,也方便以后增加更多域名。
二十一、生产环境推荐配置
一个普通 API 项目,我一般可以从下面这个配置开始:
api.example.com { encode zstd gzip reverse_proxy 127.0.0.1:8080 }如果有多个项目:
api.example.com { encode zstd gzip reverse_proxy 127.0.0.1:8080 } admin.example.com { encode zstd gzip reverse_proxy 127.0.0.1:9000 } app.example.com { encode zstd gzip reverse_proxy 127.0.0.1:3000 }非常直观。
二十二、Caddy 和 Nginx 最大的区别
对于简单的个人项目、小型 API、Docker 服务来说,Caddy 的优势非常明显。
Nginx 通常需要考虑:
域名配置 + 反向代理 + SSL证书 + 证书路径 + Certbot + 自动续期 + HTTP → HTTPSCaddy 则可以简化为:
api.example.com { reverse_proxy localhost:8080 }这是 Caddy 最吸引我的地方。
它并不是说 Nginx 不好。
复杂、高度定制化的 Web 架构中,Nginx 依然非常成熟。
但是对于:
个人服务器 独立开发者 Side Project Python API Go API Node.js Docker 服务 内部工具 MCP Server Webhook这种场景,Caddy 的配置体验确实非常舒服。
二十三、最终部署结构
完成之后,我们的服务器架构实际上非常简单:
Internet │ │ api.example.com │ │ HTTPS :443 ▼ ┌───────────┐ │ Caddy │ └─────┬─────┘ │ │ HTTP │ 127.0.0.1:8080 │ ▼ ┌───────────────┐ │ Backend API │ │ Python / Go │ │ Node / Java │ └───────────────┘公网只需要开放:
80 443业务端口:
8080 9000 3000则可以只监听:
127.0.0.1不直接暴露到公网。
二十四、常用命令汇总
最后把 Caddy 常用命令整理一下。
查看版本
caddy version查看运行状态
systemctl status caddy启动
sudosystemctl start caddy停止
sudosystemctl stop caddy重启
sudosystemctl restart caddy平滑重新加载配置
sudosystemctl reload caddy检查 Caddyfile
sudocaddy validate--config/etc/caddy/Caddyfile格式化 Caddyfile
sudocaddyfmt--overwrite/etc/caddy/Caddyfile查看日志
sudojournalctl-ucaddy实时查看日志
sudojournalctl-ucaddy-f总结
如果只是想给一个运行在服务器上的 Web 服务快速增加 HTTPS,Caddy 确实非常适合。
整个流程可以总结成:
1. 域名解析到服务器 IP ↓ 2. 开放 80 / 443 ↓ 3. 安装 Caddy ↓ 4. 编辑 /etc/caddy/Caddyfile ↓ 5. 配置 reverse_proxy ↓ 6. Caddy 自动申请 HTTPS 证书 ↓ 7. https://域名 直接访问最终真正核心的配置可能只有:
api.example.com { reverse_proxy 127.0.0.1:8080 }几行配置,就完成了:
域名绑定 HTTPS SSL 证书申请 证书管理 HTTP → HTTPS 反向代理如果经常在 Ubuntu 服务器上部署各种 Python、Go、Node.js、Docker API 服务,Caddy 是一个非常值得掌握的工具。