Nginx SSL 证书自动续期
大家好,今天想跟你们聊聊 Nginx 环境下 SSL 证书自动续期 的完整实践。现在的站点几乎都离不开 HTTPS,而 Let's Encrypt 提供的免费证书虽然只有 90 天有效期,但配合自动续期脚本,完全可以做到“一次部署,长期免维护”。下面把我在生产环境里跑的那套方案整理成文,希望对有需要的同学有所帮助。
---1. 为何选 Let's Encrypt + Certbot
- 免费:不需要额外付费,适合个人站点或中小型业务。
- 自动化:Certbot 官方提供完整的自动申请、续期、部署流程。
- 插件丰富:支持 Nginx、Apache、Standalone 等多种模式,Nginx 插件甚至可以在续期后自动重新加载配置,省去手动干预。
如果你已经在使用商业证书,只要把 Renewal 脚本改成对应的证书路径,同样可以复用下面的思路。
---2. 安装 Certbot 与 Nginx 插件
2.1 一键安装(以 Ubuntu/Debian 为例)
sudo apt update
sudo apt install -y certbot python3-certbot-nginx
2.2 验证安装
certbot --version
应该看到类似 "certbot 1.21.0" 的输出
2.3 申请第一张证书
假设你的域名已经解析到这台机器,Nginx 已经配置好对应的 server块。执行:
sudo certbot --nginx -d example.com -d www.example.com
Certbot 会自动修改 Nginx 配置,添加 listen 443 ssl http2; 等必要指令,并写入证书路径。申请成功后,浏览器访问 https://example.com 就会显示绿色小锁。
> 小技巧:如果只想先测试流程,可以使用 --dry-run 参数,Certbot 会模拟续期而不真正写入证书。
3. 配置自动续期任务
Let's Encrypt 证书的有效期是 90 天,Certbot 默认会在证书到期前 30 天尝试续期。我们只需要把这一步交给系统的定时任务。
3.1 使用 Cron(适用于大多数 Linux 发行版)
编辑系统 crontab:
sudo crontab -e
加入以下行(每天凌晨 3 点执行):
0 3 * * * /usr/bin/certbot renew --quiet --deploy-hook "systemctl reload nginx"
- --quiet:只输出错误,避免邮件打扰。
- --deploy-hook:在证书成功续期后立即执行指定命令,这里我们让它 reload Nginx,使新证书生效。
> 注意:如果你使用的是 systemctl restart nginx,会导致一次服务中断,建议使用 reload(平滑重载),用户体验更好。
3.2 使用 Systemd Timer(更可靠)
如果你更倾向于使用 systemd,可以创建如下两个文件:
1. /etc/systemd/system/certbot.timer(定时器)
[Unit]
Description=Run certbot renewal twice a day
[Timer]
OnCalendar=*-*-* 03,15:00:00
Persistent=true
[Install]
WantedBy=timers.target
2. /etc/systemd/system/certbot.service(实际任务)
[Unit]
Description=Let's Encrypt renewal
[Service]
Type=oneshot
ExecStart=/usr/bin/certbot renew --quiet --deploy-hook "systemctl reload nginx"
然后启用并启动:
sudo systemctl daemon-reload
sudo systemctl enable --now certbot.timer
这样每天会在 03:00 和 15:00 自动检查并续期,且系统会在机器重启后自动恢复定时任务。
---4. 编写 Renewal Hook,确保 Nginx 平滑重载
Certbot 提供的 --deploy-hook 已经足够大多数场景,但如果你有更复杂的需求(比如先备份旧证书、发送通知等),可以自定义脚本。
4.1 简单的 deploy-hook 脚本
创建 /usr/local/bin/certbot-nginx-reload.sh:
#!/bin/bash
certbot-nginx-reload.sh
记录日志
echo "$(date '+%Y-%m-%d %H:%M:%S') Cert renewed for $RENEWED_DOMAINS" >> /var/log/certbot-renew.log
平滑重载 Nginx
systemctl reload nginx
赋予执行权限:
sudo chmod +x /usr/local/bin/certbot-nginx-reload.sh
在 cron 或 systemd service 中使用:
--deploy-hook "/usr/local/bin/certbot-nginx-reload.sh"
4.2 常见坑点
| 场景 | 可能出现的错误 | 解决办法 |
|------|----------------|----------|
| Nginx 配置错误导致 reload 失败 | nginx: [error] reload 失败,证书已更新但服务仍用旧证书 | 在脚本里加入 nginx -t 检查配置,或使用 nginx -s reload 捕获返回码 |
| 证书路径权限不足 | Permission denied 读取 /etc/letsencrypt/live/... | 确保 Nginx 运行用户(通常是 www-data)对证书目录有读取权限 |
| 续期后 DNS 解析失效 | 续期时域名解析到别的机器,导致验证失败 | 使用 DNS-01 挑战或确保域名解析始终指向当前机器 |
---5. 监控与告警
自动续期虽然省事,但一旦失手,站点会在证书过期后出现安全警告,影响用户体验甚至 SEO。下面两种监控方式可以帮你早发现、早处理。
5.1 检查证书到期时间
openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -dates
可以写一个小脚本放在监控平台(如 Prometheus + Alertmanager)中,阈值设为 7 天。
5.2 利用 Certbot 自带的日志
前面我们在 hook 里写入了 /var/log/certbot-renew.log,可以用 logwatch 或 fluentd 采集,出现 Cert renewed 则说明续期成功;出现异常则触发告警。
5.3 第三方监控服务
如 UptimeRobot、Pingdom、CertSpotter(专门检测证书到期)等,都提供邮件或 Slack 通知,建议至少开启一个作为兜底。
---结语
通过 Let's Encrypt + Certbot 搭配 Nginx 的插件与 cron / systemd timer,我们完全可以实现“一键部署、长期自动续期”。关键点在于:
1. 使用 Certbot 的 Nginx 插件,让证书写入和配置更新一步到位。
2. 把续期任务交给系统定时,并加上 --deploy-hook 触发 nginx reload,实现平滑更新。
3. 做好监控,防止因意外导致证书失效。
只要把上面的步骤走通,后续基本不需要再手动干预,站点会一直在 HTTPS 的保护下安全运行。希望这篇文章能帮你省掉手动续期的麻烦,如果还有其他 Nginx 相关的需求,欢迎在评论区一起交流。祝部署顺利!
Nginx SSL 证书自动续期
本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
评论交流
欢迎留下你的想法