稳定续期Let's Encrypt证书需用certbot webroot插件配合Nginx静态验证,配置/.well-known/acme-challenge路径透传,编写原子化续期脚本(仅证书更新时reload且先校验Nginx配置),并通过双时段cron定时执行。

Let's Encrypt 提供免费、自动化、开放的 TLS 证书,配合 Nginx 使用时,最常遇到的问题不是“怎么申请”,而是“怎么稳定续期”——尤其在生产环境里,手动操作不可靠,cron 脚本写错一行就可能让网站 HTTPS 中断。核心要点是:用 certbot 的 webroot 插件 + Nginx 静态响应验证 + 独立续期脚本,避免 reload 冲突和权限问题。
一、Nginx 配置必须支持 ACME HTTP-01 验证
Let's Encrypt 默认通过 HTTP-01 挑战验证域名控制权,要求访问 /.well-known/acme-challenge/xxx 能返回指定文件。Nginx 不能代理、不能重定向、不能加鉴权,必须原样透传静态内容。
在对应 server 块中加入(替换 /var/www/challenges 为你实际路径):
location ^~ /.well-known/acme-challenge/ {
root /var/www/challenges;
try_files $uri =404;
}
注意:
• 不要用 alias,容易因末尾斜杠引发 404
• 不要放在 location / 内部做嵌套匹配,优先级易出错
• 所有需申请证书的域名(包括 www 和根域)都要配置该 location
二、首次申请证书并测试续期流程
确保 certbot 已安装(推荐用 snap 安装以保持自动更新):
sudo snap install --classic certbot sudo ln -sf /snap/bin/certbot /usr/bin/certbot
运行一次手动申请(不自动修改 Nginx 配置,更可控):
sudo certbot certonly \ --webroot \ -w /var/www/challenges \ -d example.com \ -d www.example.com
成功后检查:
• 证书路径:/etc/letsencrypt/live/example.com/{fullchain.pem,privkey.pem}
• 自动续期测试命令(不真正续,只模拟):sudo certbot renew --dry-run
• 若报错 “Failed authorization procedure”,重点查 Nginx 日志和 curl -I http://example.com/.well-known/acme-challenge/test 是否返回 404 或超时
三、编写安全可靠的续期脚本
不要直接在 crontab 里调用 certbot renew 后 reload Nginx —— 续期成功但 reload 失败会导致服务中断。应封装为原子操作:
- 先执行
certbot renew --quiet --no-self-upgrade - 检查退出码:0 表示无更新或已更新;1 表示出错;2 表示有证书被更新
- 仅当退出码为 2 时,才 reload Nginx(避免无谓重启)
- reload 前用
nginx -t校验配置有效性
示例脚本 /usr/local/bin/renew-nginx-cert.sh:
#!/bin/bash
/usr/bin/certbot renew --quiet --no-self-upgrade
if [ $? -eq 2 ]; then
if nginx -t > /dev/null 2>&1; then
systemctl reload nginx
else
logger "Nginx config test failed after cert renewal"
fi
fi
赋予可执行权限:sudo chmod +x /usr/local/bin/renew-nginx-cert.sh
四、设置定时任务并验证执行效果
编辑 root 的 crontab:sudo crontab -e,添加:
# 每天凌晨 3:12 和 15:12 各尝试一次(避开高峰,双保险) 12 3,15 * * * /usr/local/bin/renew-nginx-cert.sh >> /var/log/cert-renew.log 2>&1
验证是否生效:
• 查看 cron 日志:sudo grep CRON /var/log/syslog
• 手动触发一次:sudo /usr/local/bin/renew-nginx-cert.sh,观察日志与 Nginx 进程时间戳
• 检查证书有效期:openssl x509 -in /etc/letsencrypt/live/example.com/fullchain.pem -text -noout | grep "Not After"











