脚本怎样自动化续期证书

wen 实用脚本 31

本文目录导读:

脚本怎样自动化续期证书

  1. 方案一:Certbot + cron(最通用,适用于 Nginx/Apache)
  2. 方案二:使用 acme.sh(更灵活,野卡证书 & 多种 DNS API)
  3. 方案三:使用 systemd timer(替代 cron,更精细的控制)
  4. 常见问题与检查
  5. 总结建议

要实现证书的自动化续期,最主流的方案是使用 Let's EncryptCertbot 工具,配合 cronsystemd timer 定时任务。

以下是几种常见场景的自动化续期脚本和配置方法:

Certbot + cron(最通用,适用于 Nginx/Apache)

这是最标准、最稳定的方式,Certbot 在安装时通常会自动添加一个 systemd timer,但如果想自己写脚本控制,可以按以下步骤操作。

核心命令

Certbot 续期命令非常简单,它会自动检测所有已安装但即将过期的证书并尝试续期:

certbot renew

这个命令非交互式运行,不会停止服务,如果续期成功,通常需要重载 Web 服务器以加载新证书。

续期后重载服务的钩子

创建一个脚本 /etc/letsencrypt/renewal-hooks/post/reload-services.sh如下:

#!/bin/bash
# 续期成功后执行(如果是 Nginx)
systemctl reload nginx
# 如果是 Apache
# systemctl reload apache2
# 如果是 Docker 内的 Nginx(示例,需要根据实际容器名调整)
# docker exec nginx-container nginx -s reload

给脚本加上执行权限:

chmod +x /etc/letsencrypt/renewal-hooks/post/reload-services.sh

Certbot 会自动执行 renewal-hooks/post/ 目录下的脚本。

设置定时任务 (cron)

使用 crontab -e 添加以下行:

# 每天凌晨 3 点检查一次,如果证书将在 30 天内过期则自动续期
0 3 * * * /usr/bin/certbot renew --quiet --deploy-hook "systemctl reload nginx"

参数说明:

  • --quiet:非错误信息不输出到日志。
  • --deploy-hook:在续期成功后才执行后面的命令(比写在 post-hook 里更直接)。
  • 频率建议:每天一次,Let's Encrypt 证书有效期 90 天,Certbot 会在证书剩余时间 < 30 天时自动续期,每天检查不会对服务器造成负担。

使用 acme.sh(更灵活,野卡证书 & 多种 DNS API)

如果你的证书是 通配符域名*.example.com),或者使用 DNS 验证(Cloudflare、阿里云 DNS),推荐使用 acme.sh

安装与配置(以 Cloudflare 为例)

# 安装
curl https://get.acme.sh | sh
# 设置 Cloudflare API(需要先设置环境变量)
export CF_Token="你的Cloudflare API Token"
export CF_Zone_ID="Zone ID"
# 第一次申请证书(自动续期)
acme.sh --issue --dns dns_cf -d example.com -d '*.example.com'

续期脚本

acme.sh 会自动安装一个 cron 任务,无需额外配置,你可以使用以下命令查看:

crontab -l
# 你会看到类似这样的行:
# 0 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null

续期后部署证书到 Nginx

在nginx配置中,引用 acme.sh 生成的证书路径(通常是 /root/.acme.sh/域名/fullchain.cer)。 然后在 cron 中或者使用 --reloadcmd 参数自动执行重载:

acme.sh --issue ... --reloadcmd "systemctl reload nginx"

这样每次自动续期后,Nginx 会自动重载。


使用 systemd timer(替代 cron,更精细的控制)

如果你更喜欢 systemd 而不是 cron,可以创建一个简单的 timer。

  1. 创建服务文件 /etc/systemd/system/certbot-renew.service
    
    [Unit]
    Description=Certbot Renewal

[Service] Type=oneshot ExecStart=/usr/bin/certbot renew --quiet --deploy-hook "systemctl reload nginx"


2. **创建定时器文件** `/etc/systemd/system/certbot-renew.timer`:

[Unit] Description=Daily Certbot Renewal

[Timer] OnCalendar=daily RandomizedDelaySec=1h Persistent=true

[Install] WantedBy=timers.target


3. **启用并启动定时器**:
```bash
systemctl daemon-reload
systemctl enable certbot-renew.timer
systemctl start certbot-renew.timer

常见问题与检查

如何测试脚本是否工作?

# 模拟续期(不会真正修改证书)
certbot renew --dry-run
# dry-run 成功,说明配置没问题

证书路径在哪里?

  • Certbot/etc/letsencrypt/live/yourdomain.com/
  • acme.sh/root/.acme.sh/yourdomain.com/

确保 Nginx/Apache 配置文件中 ssl_certificatessl_certificate_key 指向正确的路径。

手动触发一次续期(即使未到期)

# 强制续期(会受 Let's Encrypt 频率限制,建议仅在测试时用)
certbot renew --force-renewal

日志查看

# Certbot 日志
tail -f /var/log/letsencrypt/letsencrypt.log
# acme.sh 日志
tail -f /root/.acme.sh/acme.sh.log

总结建议

  • 如果你用的是标准的 HTTP 验证(如 Nginx/Apache):用 Certbot + cron 最省事。
  • 如果需要通配符证书或 DNS 验证:用 acme.sh,它支持更多 DNS 提供商,且自动续期机制更成熟。
  • 部署时:一定要把定时任务设置到 每天执行(而不是每周),因为即使失败也有机会重试,而 Let's Encrypt 不会在你重复运行命令时给你重复发证书,它只在需要时才续期。

一个完整的自动化脚本示例(适用于初学)

#!/bin/bash
# 1. 尝试续期
/usr/bin/certbot renew --quiet
# 2. 检查是否需要重载服务(如果续期成功,deploy-hook 会处理)
# 这里仅做兜底:如果证书文件有更新,就重载
if [ -f /var/run/nginx.pid ]; then
    nginx -t && systemctl reload nginx
fi

把这个脚本放入 cron,每天执行一次即可。

抱歉,评论功能暂时关闭!