如何在 Let's Encrypt 续签成功后执行自定义 Shell 脚本通知管理员?

文章导读
最稳妥的做法是利用 Certbot 自带的 `--deploy-hook` 参数或将脚本放入 /etc/letsencrypt/renewal-hooks/deploy/ 目录,这样只有在证书真正更新时才会触发通知,避免每次检查都发送警报。
📋 目录
  1. A 命令速用版
  2. B 核心机制简述
  3. C 实操步骤
  4. D 验证与排查
  5. E 常见坑与注意事项
  6. F 参考来源
A A

最稳妥的做法是利用 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-hookdeploy-hook

post-hook 会在每次 Certbot 运行结束后执行,无论证书是否真的需要续签。如果定时任务每天运行,你就会每天收到通知,这在运维中属于噪音。

deploy-hook 仅在证书确实被更新成功后执行。对于 Let's Encrypt 这种通常 60 天有效期、30 天开始续签的证书,这意味着你大概每两个月才会收到一次通知,符合“异常或变更才告警”的运维原则。

实操步骤

1. 编写通知脚本

如何在 Let's Encrypt 续签成功后执行自定义 Shell 脚本通知管理员?

创建一个 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 0

2. 赋予执行权限

脚本必须具备执行权限,否则 Certbot 会跳过或报错:

sudo chmod +x /usr/local/bin/cert-notify.sh

3. 配置钩子

推荐方案:将脚本链接或复制到自动读取目录,此方法对所有域名通用且不易被配置更新覆盖:

sudo ln -s /usr/local/bin/cert-notify.sh /etc/letsencrypt/renewal-hooks/deploy/notify.sh

注意:不建议直接编辑 /etc/letsencrypt/renewal/*.conf 文件添加 hook 配置,该文件可能在下一次续签时被 Certbot 自动覆盖。

如何在 Let's Encrypt 续签成功后执行自定义 Shell 脚本通知管理员?

验证与排查

由于 Certbot 的 `--dry-run` 模式默认会禁用钩子以防止副作用,你不能通过干跑来测试通知脚本。

1. 手动测试脚本

先用当前用户和 root 用户分别运行一次脚本,确认通知能正常发出,排除脚本本身问题:

sudo /usr/local/bin/cert-notify.sh

2. 查看日志

等待自动续签任务运行,或在不命中速率限制的前提下强制续签(生产环境谨慎使用)。检查 Certbot 日志:

sudo cat /var/log/letsencrypt/letsencrypt.log

搜索 Deploy hook 关键字,确认脚本被执行且返回码为 0:

sudo grep "Deploy hook" /var/log/letsencrypt/letsencrypt.log

常见坑与注意事项

1. 干跑不触发

如何在 Let's Encrypt 续签成功后执行自定义 Shell 脚本通知管理员?

很多教程建议用 certbot renew `--dry-run` 测试配置,但这不会运行 deploy-hook。如果你没收到通知,不一定是配置错了,可能是测试方法不对。

2. 环境变量缺失

定时任务通常使用最小化环境变量。脚本里如果用了 pythonnode 或其他非标准路径命令,建议写绝对路径,或在脚本开头 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