acme.sh 自动续签证书的部署模式与巡检方法(Docker + Nginx)


很多人把证书装上就以为万事大吉,结果半年后访问网站突然报 NET::ERR_CERT_DATE_INVALID——一看,证书早过期了,自动续签压根没生效。本文基于一套已经稳定运行的 Docker + Nginx 部署模式,讲清 acme.sh 自动续签的完整链路,以及 如何确认”自动续签真的在工作”

以下配置均已脱敏:域名用 example.com 代指,证书目录用 /path/to/nginx/cert,容器名用 nginx-container

一、部署模式概述:证书是怎么”自动”起来的

1.1 整体架构

宿主机                          Docker 容器
┌──────────────────────┐       ┌──────────────────────┐
│  acme.sh(cron)      │       │     nginx-container   │
│  │                   │       │                      │
│  ├─ DNS API 签发      │       │  /etc/nginx/cert:ro   │←── 挂载
│  ├─ 写证书到 cert 目录 │       │  /etc/nginx/conf.d:ro │←── 挂载
│  └─ reload 容器        │       │                      │
└──────────────────────┘       └──────────────────────┘

几个关键设计点:

  1. 证书文件直接用域名命名(如 example.com.pem / example.com.key),不做订单号前缀,文件名稳定,配置里永远引用同一个路径。
  2. acme.sh 跑在宿主机,写入的是挂载给 nginx 容器的宿主目录(/path/to/nginx/cert)。挂载是 :ro,但 ro 只限制容器内写入,宿主机写不受影响。
  3. 签发后同步回”部署源”:项目的 ./nginx/cert 目录(部署脚本会 rsync --delete 用它推送线上)。这一步很关键——如果不回源,部署脚本的 --delete 会把刚签的新证当成”多余文件”删掉。
  4. reload 命令mkdir -p 部署源 && cp 新证 部署源/ && docker exec nginx-container nginx -s reload。续期成功后自动执行。

1.2 一张通配证书覆盖所有子域

用 2 张通配证书覆盖全部子域名(不细算具体数量,通常十几个):

acme.sh --issue --dns dns_ali -d example.com -d "*.example.com"

这是一条命令、一张证书(SAN 多域名证书),不是签两张:

证书里的 SAN 覆盖范围
example.com 域名本体(apex)
*.example.com 所有一级子域(www、blog、static、api…)

为什么必须两个域名一起签?通配符不匹配 apex 本身——*.example.com 能命中 www.example.com,但命中不了 example.com。所以签发时要把本体域名也放进 SAN,和通配共用同一张证书。

  • DNS API 方式签发,无需 80 端口验证、无需在每台服务器开 webroot

1.3 续期机制

# acme.sh 安装时自动登记的 cron(典型输出)
crontab -l | grep acme
39 1,7,13,19 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null
  • 每天固定时刻跑 4 次 --cron每次只是检查,到期前 60 天内才真正续签(Let’s Encrypt 证书有效期 90 天)
  • 续签成功后自动执行 --reloadcmd(同步回源 + reload 容器)
  • 跑得频繁没有副作用:未到续期窗口时 acme.sh --cron 空跑退出,不会骚扰 CA

二、如何确认自动续签真的生效(五层验证)

第 1 层:cron 任务在不在

crontab -l | grep acme

看到 acme.sh --cron 行 = 定时任务已登记。这是”自动”的前提,但只代表任务挂了,不代表续签成功过。

第 2 层:续签日志

tail -50 ~/.acme.sh/acme.sh.log
  • 看到 Renew: example.comSuccessInstall cert 等 → 续签执行过
  • 看到 Cert not due for renewal / Skip, Next renewal time is: → 未到续期窗口,正常
  • 没有任何 Renew 记录 + 证书又快到期 → 有问题,需排查

第 3 层:证书有效期(核心判断)

openssl x509 -in /path/to/nginx/cert/example.com.pem -noout -dates

输出示例:

notBefore=Jul 20 12:00:00 2026 GMT
notAfter=Oct 18 12:00:00 2026 GMT

判断标准:

现象 结论
notBefore 在最近 60 天内 + notAfter ≈ 90 天后 ✅ 自动续签生效过
notAfter 距今 < 60 天,cron 正常 ⏳ 下次 cron 跑时会续,等待即可
notAfter 距今 < 30 天 ⚠️ 逼近到期,检查 cron 和日志
notAfter 已过期 ❌ 续签失效,立即手动 --renew --force

第 4 层:证书文件写入时间

ls -l /path/to/nginx/cert/*.pem

续签会 覆盖 证书文件,文件 mtime 接近续签时间。如果 notBefore 是新的但文件时间很旧,说明写盘链路有问题。

第 5 层:线上实际加载的证书

宿主机看文件 ≠ 容器里加载的就是它。外部验证最真实:

echo | openssl s_client -connect www.example.com:443 -servername www.example.com 2>/dev/null \
  | openssl x509 -noout -dates -issuer

线上返回的 notAfter 与第 3 层一致 = nginx 已加载新证书。

三、常见问题排查

Q1:cron 在,但从来没有 Renew 记录,正常吗?

正常。acme.sh 是”到期前 60 天内才续”,证书刚签完 3 个月里每次 cron 都是空跑。只要 notAfter 没过期,就是健康的。

Q2:证书文件在 /etc/nginx/cert/ 里看不到?

检查容器挂载:

docker inspect nginx-container --format '{{json .Mounts}}' | python3 -m json.tool

确认宿主目录和容器路径与 acme.sh 写入的是同一个宿主机路径。

Q3:续签成功了,但网站还是旧证书?

  • 确认 --reloadcmd 里有没有 docker exec nginx-container nginx -s reload(续期后必须 reload 才生效)
  • 浏览器缓存:用 openssl s_client 外部验证,别用浏览器判断

Q4:换了域名/证书,旧的还自动续吗?

acme.sh 按域名管理证书,旧域名证书到 60 天窗口还会续。不用了应显式停止:

acme.sh --remove -d old.example.com

四、巡检清单(建议每季度跑一次)

# 0. 所有证书一览(确认域名都还在 acme.sh 管理列表中)
acme.sh --list
# 1. 任务在
crontab -l | grep acme
# 2. 证书没过期
openssl x509 -in /path/to/nginx/cert/example.com.pem -noout -dates
# 3. 线上加载的是新证
echo | openssl s_client -connect www.example.com:443 -servername www.example.com 2>/dev/null \
  | openssl x509 -noout -dates

三条命令、30 秒,确认自动续签链路健康。只要 cron 在、证书没到期、线上和文件一致,就放心让它自己跑——这套模式跑起来后,基本可以做到”证书管理零维护”。

补充提醒:acme.sh 自身也会迭代,建议偶尔执行 acme.sh --upgrade 升级到最新版,避免旧版本逻辑导致签发/续期异常。升级不影响已签证书,重启 cron 后自动续期照常生效。

参考


文章作者: 弈心
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 弈心 !
评论
 本篇
acme.sh 自动续签证书的部署模式与巡检方法(Docker + Nginx) acme.sh 自动续签证书的部署模式与巡检方法(Docker + Nginx)
基于 Docker + Nginx 的站点,acme.sh 在宿主机签发通配证书、双写部署源并登记 cron 自动续期。本文讲清这套部署模式的完整链路,以及如何确认自动续签真的生效:crontab 检查、续期日志、证书有效期、文件时间戳、线上实际加载证书五层验证。
2026-08-07
下一篇 
Nuxt3 三种渲染模式的优缺点分析 Nuxt3 三种渲染模式的优缺点分析
详细分析 Nuxt3 SSR、SSG、SPA 三种渲染模式的优缺点,提供博客+后台分离部署方案与 Nginx 配置示例
2026-08-07
  目录