系统实践
Nginx 配置 HTTPS:Certbot 签发、自动续期与故障排查
从签发前检查到自动续期验证,完整梳理 Nginx 使用 Certbot 配置 HTTPS 的可靠流程,并说明端口、DNS、代理和回滚边界。

本文最初发布于 2021 年,当时主要记录了用 snap 安装 Certbot 的操作顺序。2026 年重写时保留这条实践路径,并按当前 Certbot、Let’s Encrypt 与 Nginx 官方文档补上签发前检查、自动续期验证、故障排查和回滚。
为 Nginx 网站开启 HTTPS,真正容易被忽略的不是 certbot --nginx 这一条命令,而是命令前后的条件:域名是否指向正确服务器、80 端口能否从公网访问、Nginx 配置是否有效,以及证书以后能不能自动续期。
下面以 example.com 和 www.example.com 为例。执行时必须替换成自己的域名。
签发前先确认四件事
1. 域名已经指向这台服务器
分别检查根域名和 www 记录:
dig +short A example.com
dig +short AAAA example.com
dig +short A www.example.com
dig +short AAAA www.example.com
返回地址应与当前服务器一致。如果域名保留了一条失效的 AAAA 记录,Let’s Encrypt 可能从 IPv6 访问到错误主机,导致验证失败。
2. HTTP 站点可以从公网访问
Certbot 的 Nginx 插件通常使用 HTTP-01 挑战。Let’s Encrypt 会请求:
http://example.com/.well-known/acme-challenge/<TOKEN>
HTTP-01 只能通过公网的 80 端口 完成。即使最终全部跳转到 HTTPS,也应让 80 端口接收请求并返回跳转;不能把外部 8080 端口映射误认为等价替代。
先从服务器外部确认:
curl -I http://example.com
如果请求超时,先检查云平台安全组、主机防火墙、路由器端口映射和运营商限制,而不是反复运行 Certbot。
3. Nginx 已识别正确域名
站点配置至少需要包含对应的 server_name:
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
root /var/www/example;
index index.html;
}
检查当前配置:
sudo nginx -t
nginx -t 不只检查语法,也会尝试打开配置引用的文件。只有测试成功,才进入证书签发。
4. 先备份配置
Certbot 可以自动修改 Nginx 配置。生产服务器执行前,先留下可回滚副本:
sudo cp -a /etc/nginx "/etc/nginx.backup-$(date +%Y%m%d-%H%M%S)"
如果你的发行版使用其他配置目录,应按 nginx -V 和实际安装方式调整路径。
安装 Certbot:先选定一种来源
Certbot 官方针对 Nginx on Linux 的当前说明仍优先推荐 snap。先按 Snapcraft 的发行版说明安装并启用 snapd,再执行:
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/local/bin/certbot
certbot --version
这里有两个容易踩坑的地方:
- 不要同时保留 apt、dnf、yum 与 snap 安装的多个 Certbot。混用可能让实际执行文件与续期任务来自不同安装源。
- 旧文使用
/usr/bin/certbot,当前官方 snap 指令使用/usr/local/bin/certbot。如果链接已存在,先用command -v certbot和readlink -f查明来源,不要直接覆盖。
如果服务器不使用 snap,应在 Certbot 官方安装选择器选择实际操作系统与安装方式。不同来源的更新和定时续期机制可能不同,不应把本文的 snap 命令机械套用到所有发行版。
让 Certbot 自动配置 Nginx
确认域名、80 端口和 nginx -t 都正常后,明确列出要写入证书的域名:
sudo certbot --nginx -d example.com -d www.example.com
Certbot 会完成域名验证、签发证书并修改匹配的 Nginx server block。交互过程中可以选择把 HTTP 请求跳转到 HTTPS。
完成后再次测试并平滑重载:
sudo nginx -t
sudo systemctl reload nginx
Nginx 在 reload 时会先检查新配置;应用失败时,主进程会继续使用旧配置。不过这不能代替修改前备份,因为“语法有效”不代表站点路由一定符合预期。
如果只想让 Certbot 签发证书、由自己维护 TLS 配置,可以使用:
sudo certbot certonly --nginx -d example.com -d www.example.com
这种方式控制更精细,但证书路径、443 监听、跳转和后续维护都由你负责。对于普通单站点,自动配置更简单;对于共享配置、复杂反向代理或严格变更流程,certonly 更可控。
签发后不要只看浏览器的小锁
先查看 Certbot 记录:
sudo certbot certificates
再检查 HTTP 跳转和 HTTPS 响应:
curl -I http://example.com
curl -I https://example.com
确认以下结果:
- HTTP 返回到正确 HTTPS 地址的 301 或 308,而不是循环跳转。
- HTTPS 返回预期站点,不是 Nginx 默认页或其他虚拟主机。
- 证书包含访问使用的所有域名。
- 页面中的脚本、样式、图片没有继续使用
http://导致混合内容。
自动续期必须亲自验证
Certbot 的安装包通常会配置 cron 或 systemd timer,但“装好了”不等于“以后一定能续”。先检查定时任务:
systemctl list-timers --all | grep -i certbot
然后执行官方推荐的模拟续期:
sudo certbot renew --dry-run
只有 dry run 成功,才能说明当前认证方式和续期配置基本可用。以后如果修改域名、Web 根目录、DNS、反向代理或 /etc/letsencrypt/renewal/ 下的设置,应重新运行测试。
不要为了“确认续期”连续使用 --force-renewal 申请真实证书。证书机构存在速率限制,日常验证应使用 --dry-run。
常见失败如何定位
域名解析到了错误地址
先同时检查 A 与 AAAA 记录。DNS 修改尚未传播、旧 IPv6 记录未删除、根域名与 www 指向不同主机,都会让部分验证请求落到错误服务器。
80 端口从公网不可达
HTTP-01 的验证入口固定是 80 端口。开放 Nginx 的 443 端口,或者让应用监听 8080,都不能替代它。无法开放 80 时,应评估 DNS-01,而不是寻找让 HTTP-01 改端口的参数。
CDN 或代理干扰挑战路径
使用 Cloudflare 等代理时,要确认 /.well-known/acme-challenge/ 最终到达运行 Certbot 的源站,没有被访问控制、重写规则或缓存返回错误内容。也可以根据实际架构改用受支持的 DNS 插件,但 DNS API 凭据必须最小权限保存,不能写进站点仓库或公开命令历史。
Certbot 找不到对应 server block
常见原因是 server_name 缺失、域名写错、站点配置未加载,或多个 server block 重复声明。使用以下命令查看 Nginx 实际加载的完整配置:
sudo nginx -T
-T 会把完整配置输出到终端,公开粘贴前应检查其中是否包含内部域名、路径或其他敏感信息。
续期测试失败
查看 Certbot 日志和证书的续期配置:
sudo less /var/log/letsencrypt/letsencrypt.log
sudo certbot certificates
不要随意手改 /etc/letsencrypt/renewal/*.conf。Certbot 文档明确提醒这类修改容易破坏续期;确需调整时先备份,并用 renew --dry-run 验证。
失败时怎样回滚
如果 Certbot 修改后站点异常:
- 保留错误日志和当前配置,便于判断问题。
- 从签发前备份恢复
/etc/nginx,或只还原受影响的 server block。 - 执行
sudo nginx -t,成功后再sudo systemctl reload nginx。 - 确认 HTTP 站点恢复,再重新处理证书配置。
不要在配置测试失败时直接重启 Nginx。reload 更适合日常配置变更;测试与备份则让回滚不依赖运气。
一套可靠流程的判断标准
HTTPS 配置完成,不是“浏览器今天能打开”就结束,而是同时满足:
- 域名解析和 Nginx 虚拟主机一致。
- 80 端口承担验证和 HTTPS 跳转,443 端口提供正确站点。
- Nginx 配置测试、证书域名与页面资源均正常。
- 自动续期任务存在,
certbot renew --dry-run成功。 - 修改前有备份,失败时知道恢复哪份配置。
旧文的一组安装命令解决了“第一次签发”的问题;真正可长期维护的 HTTPS,还要把验证、续期和回滚一起设计进去。
参考:Certbot 官方 Nginx 安装说明、Certbot 使用文档、Let’s Encrypt 挑战类型、Let’s Encrypt 关于 80 端口的建议与 Nginx 命令行参数。

