系统实践

Nginx 配置 HTTPS:Certbot 签发、自动续期与故障排查

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

· 约 11 分钟阅读 · 更新于 2026年7月17日 · 近 30 天 20 次浏览

浏览器通过证书验证连接到 Nginx 服务器的山海风格示意图

本文最初发布于 2021 年,当时主要记录了用 snap 安装 Certbot 的操作顺序。2026 年重写时保留这条实践路径,并按当前 Certbot、Let’s Encrypt 与 Nginx 官方文档补上签发前检查、自动续期验证、故障排查和回滚。

为 Nginx 网站开启 HTTPS,真正容易被忽略的不是 certbot --nginx 这一条命令,而是命令前后的条件:域名是否指向正确服务器、80 端口能否从公网访问、Nginx 配置是否有效,以及证书以后能不能自动续期。

下面以 example.comwww.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 certbotreadlink -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 修改后站点异常:

  1. 保留错误日志和当前配置,便于判断问题。
  2. 从签发前备份恢复 /etc/nginx,或只还原受影响的 server block。
  3. 执行 sudo nginx -t,成功后再 sudo systemctl reload nginx
  4. 确认 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 命令行参数