当 Caddy 被配置为反向代理时,它会使用 Let's Encrypt 或 ZeroSSL 等 ACME 提供商,自动为您的域名申请、续期和管理 TLS 证书,无需人工干预即可默认启用 HTTPS。该特性省去了手动管理证书的工作,简化了安全 Web 服务器的部署。
理解 Caddy 的自动 HTTPS
Caddy 最大的差异化在于它对 HTTPS 采用零配置方式。当 Caddy 收到某个域名的请求时,如果该域名尚无有效证书且未显式配置证书,它会尝试为该域名申请 TLS 证书。这一过程基于 ACME(Automatic Certificate Management Environment)协议。
ACME 与 Caddy 如何协同工作
- 域名解析: Caddy 识别与该请求关联的域名。
- 证书检查: 它在本地存储中查找该域名是否已有有效证书。
- ACME 验证: 若未找到有效证书,Caddy 会与已配置的 ACME 提供商(默认 Let's Encrypt,ZeroSSL 作为备选)发起一次 ACME 验证。最常见的验证类型是 HTTP-01 和 DNS-01。
- HTTP-01 验证: Caddy 在服务器上的特定路径(
/.well-known/acme-challenge/)创建一个临时文件。ACME 提供商随后通过 80 端口的 HTTP 访问该文件以验证域名归属。这要求 Caddy 在 80 端口上可被公网访问。 - DNS-01 验证: Caddy 指示 ACME 提供商通过检查域名 DNS 区域中特定的 TXT 记录来验证归属。通配符证书必须使用此方式,在 80 端口不可用时也可采用。它要求 Caddy 拥有受支持 DNS 提供商的凭据。
- HTTP-01 验证: Caddy 在服务器上的特定路径(
- 证书签发: 验证成功完成后,ACME 提供商为该域名签发 TLS 证书。
- 证书存储: Caddy 将证书及其私钥安全地保存在磁盘上。
- 自动续期: Caddy 监控证书到期时间,并使用同样的 ACME 验证流程提前充分地自动续期(通常在到期前 30 天)。
- OCSP Stapling: Caddy 还会自动获取 OCSP 响应并装订到证书上,使客户端无需直接联系证书颁发机构即可验证证书吊销状态,从而提升客户端性能与隐私性。
带自动 HTTPS 的基础反向代理配置
一份最简的反向代理 Caddyfile 配置就会隐式启用自动 HTTPS。
简单的反向代理示例
yourdomain.com {
reverse_proxy localhost:8080
}
在这个示例中:
* yourdomain.com:这是站点标签。Caddy 会同时在 80 端口(用于 HTTP 跳转和 ACME 验证)和 443 端口(用于 HTTPS)监听该域名的请求。
* reverse_proxy localhost:8080:该指令把所有发往 yourdomain.com 的请求转发到运行在 localhost 的 8080 端口上的上游应用。
使用该配置启动时,Caddy 会自动执行以下步骤:
1. 尝试从 ACME 提供商为 yourdomain.com 申请 TLS 证书。
2. 为 80 端口上的全部流量设置 HTTP 到 HTTPS 的跳转。
3. 使用获得的证书通过 HTTPS 提供 yourdomain.com 服务。
运行 Caddy
使用该配置运行 Caddy 的步骤:
- 将上述内容保存为目标目录中的
Caddyfile。 - 在终端中进入该目录。
- 执行:
caddy run
在生产环境中,建议将 Caddy 作为 systemd 服务或在 Docker 容器中运行。
高级 HTTPS 配置
自定义证书
如果您已有 TLS 证书(例如来自企业 CA,或手动获取的通配符证书),可以配置 Caddy 使用这些证书,而不是自动申请。
yourdomain.com {
tls /path/to/your/cert.pem /path/to/your/key.pem
reverse_proxy localhost:8080
}
tls /path/to/your/cert.pem /path/to/your/key.pem:指定完整证书链文件和私钥文件。Caddy 将使用这些文件,不再尝试为yourdomain.com申请证书。
通过 DNS-01 验证获取通配符证书
通配符证书(*.yourdomain.com)必须使用 DNS-01 ACME 验证,因为 HTTP-01 验证无法证明对任意子域名的归属。因此需要为 Caddy 配置您的 DNS 提供商凭据。
*.yourdomain.com {
tls {
dns cloudflare {
api_token "YOUR_CLOUDFLARE_API_TOKEN"
}
}
reverse_proxy localhost:8080
}
tls { dns cloudflare { ... } }:该配置块告诉 Caddy 使用 Cloudflare DNS 提供商执行 DNS-01 验证。api_token "YOUR_CLOUDFLARE_API_TOKEN":请替换为您真实的 Cloudflare API token。Caddy 通过插件支持众多 DNS 提供商,具体配置请参阅 Caddy 官方文档。
多域名与站点块
Caddy 可以同时服务多个域名,每个域名都有自己的自动 HTTPS。
yourdomain.com {
reverse_proxy localhost:8080
}
anotherdomain.org {
reverse_proxy localhost:8081
}
Caddy 会为 yourdomain.com 和 anotherdomain.org 各自独立地申请并管理证书。
HTTP-01 与 DNS-01 验证对比
| 特性 | HTTP-01 验证 | DNS-01 验证 |
|---|---|---|
| 验证方式 | 在 80 端口提供一个文件 | 向 DNS 添加一条 TXT 记录 |
| 所需端口 | 80(用于 ACME 验证) | 无特定端口,仅需 DNS 访问权限 |
| 通配符支持 | 不支持 | 支持(*.yourdomain.com) |
| 内网服务器 | Caddy 不可公网访问时不适用 | 若 DNS 可管理,适用于内网服务器 |
| 配置 | 通常自动完成,无需额外配置 | 需要 DNS 提供商凭据和插件 |
| 防火墙要求 | 80 端口必须对公网开放 | 验证时 Caddy 主机无需开放任何入站端口 |
ACME 提供商
Caddy 默认使用 Let's Encrypt 申请证书,ZeroSSL 作为备选。您可以显式配置要使用的 ACME 提供商。
yourdomain.com {
tls [email protected] {
ca https://acme-v02.api.letsencrypt.org/directory
}
reverse_proxy localhost:8080
}
ca https://acme-v02.api.letsencrypt.org/directory:指定 ACME CA 的 URL。[email protected]:建议提供邮箱地址,用于 ACME 账户注册以及接收 CA 的重要通知。
管理证书
Caddy 会自动管理证书,但了解其存储位置和手动操作方式仍然有用。
证书存储
默认情况下,Caddy 将证书、私钥和 ACME 账户信息保存在数据目录中。具体位置取决于操作系统以及 Caddy 的运行方式:
* Linux: /var/lib/caddy/.local/share/caddy(通过 systemd 以 root 运行时)或 $HOME/.local/share/caddy(以普通用户运行时)。
* Docker: 位于容器的 /data 卷内。
该目录应当持久化(例如在 Docker 中挂载卷),以免每次重启都要重新申请证书。
手动续期与吊销
尽管 Caddy 已自动化续期,直接操作证书存储的场景很少见。
* 续期: 如果需要立即续期(例如证书泄露后),可以从 Caddy 的数据目录中删除对应的证书文件。Caddy 会在下次启动或收到请求时尝试申请新证书。
* 吊销: 证书吊销属于高级操作,通常在私钥泄露时执行。Caddy 没有提供直接的命令行吊销工具。必要时通常通过 ACME 提供商的 API 或专用客户端完成。
常见 HTTPS 问题排查
防火墙配置
确认 Caddy 服务器的 80 和 443 端口对入站流量开放。80 端口对 HTTP-01 ACME 验证以及 HTTP 到 HTTPS 的跳转至关重要。
DNS 传播
如果使用 DNS-01 验证,请确认您的 DNS 记录(特别是用于验证的 TXT 记录)已正确传播。可使用 dig 等工具或在线 DNS 查询服务。DNS 记录错误或传播缓慢会导致证书无法签发。
ACME 速率限制
Let's Encrypt 等 ACME 提供商对证书签发设有速率限制。反复失败的尝试可能导致临时封禁。
* Staging 环境: 测试时使用 ACME staging 环境,避免触及生产环境的速率限制。
caddyfile
yourdomain.com {
tls [email protected] {
ca https://acme-staging-v02.api.letsencrypt.org/directory
}
reverse_proxy localhost:8080
}
* 合并域名: 如果需要服务大量子域名,可考虑使用通配符证书以减少单独的证书申请次数。
Caddy 日志
Caddy 日志详细记录了证书申请、续期尝试以及各类错误。若 HTTPS 未按预期工作,请在日志中查找具体错误信息。
* 默认日志位置: 日志通常写入标准输出(stdout)或配置的日志文件。
* 详细日志: 您可以提高日志级别以获取更多诊断信息。
{
log {
output file /var/log/caddy/caddy.log
level DEBUG
}
}
yourdomain.com {
reverse_proxy localhost:8080
}
部署注意事项
Docker
在 Docker 中部署 Caddy 时,请确保数据目录映射到持久化卷。
version: '3.8'
services:
caddy:
image: caddy:latest
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data # 证书的持久化存储
- caddy_config:/config
myapp:
image: myapp:latest
restart: unless-stopped
expose:
- "8080" # 内部端口,不对外暴露
volumes:
caddy_data:
caddy_config:
Systemd 服务
对于物理机或虚拟机部署,将 Caddy 作为 systemd 服务运行是标准做法。Caddy 官方文档提供了示例 caddy.service 文件,可将 Caddy 配置为以专用用户运行并正确管理其数据目录。
资源占用
Caddy 很轻量。证书管理操作消耗的资源极少,且通常在后台进行。主要的资源开销来自流量代理本身。
安全最佳实践
Caddy 的自动 HTTPS 默认处理了许多安全方面的问题:
* 强 TLS 加密套件: Caddy 使用现代且安全的 TLS 加密套件。
* HTTP Strict Transport Security(HSTS): Caddy 可以自动添加 Strict-Transport-Security 响应头,指示浏览器始终通过 HTTPS 连接。
* OCSP Stapling: 降低延迟并增强隐私性。
尽管 Caddy 处理了大部分 TLS 复杂性,通用的安全实践依然适用:
* 保持 Caddy 更新: 定期将 Caddy 升级到最新版本,以获得安全补丁和新特性。
* 最小权限: 以所需的最小权限运行 Caddy。官方 systemd 服务文件已将 Caddy 配置为以非 root 用户运行。
* 防火墙: 限制对上游应用(例如 localhost:8080)的访问,使其只能从 Caddy 实例访问。
* 访问控制: 如有需要,为代理后面的特定路由或应用实施额外的访问控制或身份验证。
