Nginx 与 Let's Encrypt 证书续期可靠的关键是确保续期后服务不中断,需将验证、更新、加载三环节串成原子操作,并在 reload 前校验配置有效性;必须保障 ACME 挑战路径可访问、使用 webroot 插件、编写带 nginx -t 校验的 reload 脚本,并辅以双时段定时与外部监控兜底。

要让 Nginx 和 Let's Encrypt 的证书续期真正可靠,关键不是“能不能续”,而是“续完之后服务会不会断”。核心矛盾在于:certbot 续期成功 ≠ Nginx 用上新证书 ≠ 用户访问不中断。必须把验证、更新、加载三个环节串成原子操作,且 reload 前必须校验配置有效性。
确保 ACME 验证路径始终可访问
Let's Encrypt 每次续期都走 HTTP-01 挑战,必须保证 /.well-known/acme-challenge/ 能被公网直接读取静态文件,Nginx 不能代理、重写或加鉴权。
- 在每个需续期的
server块中单独添加该 location,不要嵌套在location /内 - 用
root(非alias),路径末尾不带斜杠,例如:location ^~ /.well-known/acme-challenge/ { root /var/www/challenges; try_files $uri =404; } - 所有域名(
example.com和www.example.com)都要配,否则多域名证书续期会失败 - 用
curl -I http://yourdomain.com/.well-known/acme-challenge/test验证返回 404(而非 502/403/timeout)才算通
用 webroot 插件申请并控制续期逻辑
避免使用 --nginx 插件自动改配置,它容易覆盖自定义设置;改用 --webroot 手动指定挑战目录,完全掌控证书生命周期。
- 首次申请:
sudo certbot certonly --webroot -w /var/www/challenges -d example.com -d www.example.com - 证书存放在
/etc/letsencrypt/live/example.com/,Nginx 配置中直接引用fullchain.pem和privkey.pem - 后续续期只更新证书文件,不碰 Nginx 配置——这样 reload 才是纯粹的“热加载”,无配置冲突风险
编写带校验的原子化 reload 脚本
直接 certbot renew && nginx -s reload 是危险的:若证书更新成功但 Nginx 配置有语法错误,reload 失败会导致 HTTPS 服务中断。
- 脚本应先运行
certbot renew --quiet --no-self-upgrade - 检查命令退出码:仅当返回 0(有更新)或 1(无更新需续)时才继续;返回其他值说明出错,立即退出
- 执行
nginx -t校验配置语法和证书路径有效性,失败则中止,不 reload - 确认通过后,再
systemctl reload nginx(或nginx -s reload) - 建议将该脚本保存为
/usr/local/bin/renew-nginx-cert.sh,并设为可执行
双时段定时 + 外部监控兜底
单靠 cron 不足以应对所有异常,需分层保障。
- cron 设置两个时段(如每天 03:17 和 15:23),避开整点高峰,降低并发冲突概率
- 每次执行后记录日志到
/var/log/certbot-renew.log,含时间戳和 certbot 输出 - 部署外部监控(如 UptimeRobot 或自建 Prometheus+Blackbox Exporter),对
https://yourdomain.com做证书过期天数探测,剩余 ≤7 天即告警 - 保留最近 3 次证书备份(
cp -r /etc/letsencrypt/archive/example.com /backup/cert-$(date +%F)),故障时可快速回退


















