最稳妥的做法是利用 Certbot 自带的 `--deploy-hook` 参数或将脚本放入 /etc/letsencrypt/renewal-hooks/deploy/ 目录,这样只有在证书真正更新时才会触发通知,避免每次检查都发送警报。
先说结论:推荐使用 deploy-hook 机制,它仅在证书成功续签后执行,适合生产环境的通知需求。
- 适合:需要区分“例行检查”与“实际续签”场景,避免通知骚扰。
- 先准备:编写好可独立运行的 Shell 脚本,并确保具备执行权限。
- 验收:通过查看 Certbot 日志确认脚本是否在续签后被调用。
命令速用版
如果你是通过命令行手动续签,可以直接添加参数:
sudo certbot renew `--deploy-hook` "/path/to/notify.sh"如果是通过系统定时任务自动续签,建议将脚本放入专用目录,Certbot 会自动读取:
sudo cp notify.sh /etc/letsencrypt/renewal-hooks/deploy/
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/notify.sh核心机制简述
Certbot 提供了多种钩子(Hook)机制,运维中容易混淆的是 post-hook 和 deploy-hook。
post-hook 会在每次 Certbot 运行结束后执行,无论证书是否真的需要续签。如果定时任务每天运行,你就会每天收到通知,这在运维中属于噪音。
deploy-hook 仅在证书确实被更新成功后执行。对于 Let's Encrypt 这种通常 60 天有效期、30 天开始续签的证书,这意味着你大概每两个月才会收到一次通知,符合“异常或变更才告警”的运维原则。
实操步骤
1. 编写通知脚本
创建一个 Shell 脚本,例如 /usr/local/bin/cert-notify.sh。脚本内容可以是发送邮件、调用 webhook 或发送即时消息。确保脚本中使用的命令路径是绝对的,因为定时任务环境变量可能不同。
#!/bin/bash
# 示例:发送 curl 请求到通知接口
curl -X POST https://your-notification-api.com/notify \
-H "Content-Type: application/json" \
-d '{"text": "SSL 证书已续签成功"}'
# 建议显式退出,避免意外错误码
exit 02. 赋予执行权限
脚本必须具备执行权限,否则 Certbot 会跳过或报错:
sudo chmod +x /usr/local/bin/cert-notify.sh3. 配置钩子
推荐方案:将脚本链接或复制到自动读取目录,此方法对所有域名通用且不易被配置更新覆盖:
sudo ln -s /usr/local/bin/cert-notify.sh /etc/letsencrypt/renewal-hooks/deploy/notify.sh注意:不建议直接编辑
/etc/letsencrypt/renewal/*.conf文件添加 hook 配置,该文件可能在下一次续签时被 Certbot 自动覆盖。验证与排查
由于 Certbot 的
`--dry-run`模式默认会禁用钩子以防止副作用,你不能通过干跑来测试通知脚本。1. 手动测试脚本
先用当前用户和 root 用户分别运行一次脚本,确认通知能正常发出,排除脚本本身问题:
sudo /usr/local/bin/cert-notify.sh2. 查看日志
等待自动续签任务运行,或在不命中速率限制的前提下强制续签(生产环境谨慎使用)。检查 Certbot 日志:
sudo cat /var/log/letsencrypt/letsencrypt.log搜索
Deploy hook关键字,确认脚本被执行且返回码为 0:sudo grep "Deploy hook" /var/log/letsencrypt/letsencrypt.log常见坑与注意事项
1. 干跑不触发
很多教程建议用
certbot renew `--dry-run`测试配置,但这不会运行deploy-hook。如果你没收到通知,不一定是配置错了,可能是测试方法不对。2. 环境变量缺失
定时任务通常使用最小化环境变量。脚本里如果用了
python、node或其他非标准路径命令,建议写绝对路径,或在脚本开头 source 配置文件。3. 脚本错误影响续签
根据 Certbot 机制,钩子脚本执行失败通常不会导致证书续签失败,但会在日志中报错。不过为了稳妥,建议脚本内部做好错误处理,避免返回非零退出码。
4. 权限问题
Certbot 续签通常由 root 运行,但如果你将脚本放在用户目录下,root 可能无权读取。建议将通知脚本放在
/usr/local/bin或/etc/letsencrypt目录下。参考来源
- Certbot 官方文档 - Renewal 章节,关于 hooks 的说明,URL: https://eff-certbot.readthedocs.io/en/stable/using.html#renewal