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