acme.sh 实现全自动 ssl 续签与无中断重载:通过 dns 自动验证(如阿里云)、--install-cert 部署加 --reloadcmd 重载 nginx、每日 crontab 检测续签,并辅以到期告警。

自动续签免费SSL证书并平滑重载Web服务,核心在于三件事:可靠验证、静默续签、无中断 reload。用 acme.sh 最稳,它轻量、纯 Shell、适配宝塔和原生 Nginx/Apache,且支持 DNS 自动验证——这对国内服务器尤其关键。
用 acme.sh 实现全自动续签(推荐方案)
acme.sh 不依赖 Python 环境,不改系统文件,所有操作隔离在 ~/.acme.sh/ 目录下,适合长期维护。
- 一键安装并切换到 Let’s Encrypt:
curl https://get.acme.sh | sh -s email=your@domain.com
然后执行source ~/.bashrc,再运行acme.sh --set-default-ca --server letsencrypt - 配置 DNS API(以阿里云为例):
创建 RAM 子账号,授予AliyunDNSFullAccess权限,拿到 AccessKey ID 和 Secret;
在终端执行:export Ali_Key="xxx"export Ali_Secret="xxx" - 申请泛域名证书(含自动 DNS 验证):
acme.sh --issue --dns dns_ali -d example.com -d *.example.com
成功后证书会存放在~/.acme.sh/example.com/下 - 部署到 Web 服务并启用自动续签:
acme.sh --install-cert -d example.com \--key-file /www/wwwroot/example.com/privkey.pem \--fullchain-file /www/wwwroot/example.com/fullchain.pem \--reloadcmd "systemctl reload nginx"
注意:--reloadcmd是关键,它确保每次续签后立刻生效,不中断连接
让续签真正“自动”,靠 crontab 定时触发
acme.sh 默认每 60 天检查一次,但建议设为每天凌晨执行,早发现问题早处理。
- 编辑定时任务:
crontab -e - 添加一行(路径按你实际安装位置调整):
0 3 * * * "/root/.acme.sh/acme.sh" --cron --home "/root/.acme.sh/" > /dev/null - 保存退出。系统每天 3 点自动运行,检测过期、续签、reload 一气呵成
宝塔用户特别注意:避免“续签成功但 HTTPS 仍报错”
这不是证书没续上,而是 Nginx 没重载——宝塔的 SSL 页面点“强制续签”有时只更新文件,不 reload 服务。
- 确认你的
--reloadcmd命令有效:
手动执行一次systemctl reload nginx,看是否报错;若提示权限不足,改用/www/server/panel/pyenv/bin/python /www/server/panel/class/websoft.py reload(宝塔内置命令) - 检查 Nginx 配置中 SSL 路径是否指向 acme.sh 部署的文件(不是宝塔自动生成的旧路径)
- 续签后立即验证:
openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -dates
看notAfter是否已更新
兜底策略:加一层到期前告警
自动续签再稳,也怕 DNS 服务商临时故障或 API 权限过期。加个简单检测脚本,提前两天微信提醒你。
- 新建
/opt/check-ssl.sh,内容为:#!/bin/bash<br>DOMAIN="example.com"<br>END=$(openssl x509 -in "/www/wwwroot/$DOMAIN/fullchain.pem" -noout -enddate | cut -d= -f2-)<br>EXPIRE=$(date -d "$END" +%s)<br>NOW=$(date +%s)<br>DIFF=$((EXPIRE - NOW))<br>if [ $DIFF -lt 172800 ]; then # 小于2天<br> curl -X POST "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=YOUR_KEY" \<br> --data '{"msgtype":"text","text":{"content":"⚠️ '$DOMAIN' SSL证书将在48小时内过期!"}}'<br>fi - 加进 crontab 每天跑一次:
0 1 * * * /bin/bash /opt/check-ssl.sh











