
Let's Encrypt 证书不能靠人记
以前 Let's Encrypt SSL/TLS 证书 90 天续一次,很多团队还能靠日历提醒、表格、运维群消息勉强撑着。以后不行了。Let's Encrypt 已经公布计划:2027 年 2 月 10 日开始变成 64 天,2028 年 2 月 16 日开始变成 45 天。官方也明确提醒,短有效期下手工续期不再推荐。
有效期短本身不是坏事——证书或私钥出问题时,风险窗口更小。但它逼着每个团队把证书管理彻底自动化。如果脚本还写死“每 60 天续一次”,到 45 天证书就已经来不及了。Let's Encrypt 在缩短有效期的公告里也提到,不支持 ARI 的客户端要重新确认续期调度,不能再用固定 60 天这种老逻辑。
截至 2026 年 4 月,Let's Encrypt 默认证书仍是 90 天。变化会分阶段推进:2027 年进入 64 天,2028 年进入 45 天。现在检查自动化链路,还来得及。
更难的是签出之后那一段:
- 证书续了,但 Nginx 没有 reload。
- 新证书在一台服务器上,另一台服务器还在用旧证书。
- CDN 边缘证书正常,源站证书已经快过期。
- 泛域名证书要走 DNS-01,DNS Token 权限、传播等待、TXT 记录清理都有可能出问题。
- 证书文件更新了,但线上入口实际返回的还是旧证书。
certbot renew 只能覆盖续期这一步。真正上线时,还要确认验证可重复执行、证书能分发到正确位置、相关服务已经重载,并且用户入口实际返回的是新证书。
只跑 certbot renew 还不够
很多团队一开始是这样处理的:
certbot renew --dry-run
certbot renew
systemctl reload nginx
如果一台机器上只跑一个 Nginx,这套足够用——certbot 自带 systemd timer 或 cron,定期跑 renew,hook 里再 reload 一下就完事。
问题在于多数生产环境的证书不是只服务于本机。一张 example.com 证书可能同时放在多台 Nginx、负载均衡监听器、CDN、Kubernetes Ingress、内网 API 网关上。这时候 certbot renew 只更新了本机文件,分发、导入、绑定、reload 全要你自己接。
更容易翻车的是半自动流程。证书自动续好了,却还等着人复制到另一台机器;部署脚本返回成功了,但线上入口实际返回的还是旧证书。这种状态比纯手工更难发现,因为团队会误以为续期链路已经闭环。
续期、部署、检查要串成一条链路
可以把 Let's Encrypt 自动续期拆成 6 个动作。
| 动作 | 要回答的问题 |
|---|---|
| 检查 | 哪些证书快到期了?线上入口实际返回的是哪张证书? |
| 验证 | HTTP-01 或 DNS-01 还能不能跑通? |
| 续期 | ACME 客户端能不能按正确时间续证书? |
| 部署 | 新证书要放到哪些服务器、云产品、CDN 或网关? |
| 生效 | Nginx reload 了吗?云资源绑定换新了吗? |
| 告警 | 哪一步失败了?谁需要处理? |
这 6 个动作少一个,都可能导致线上过期。最隐蔽的是“生效”那一步:磁盘上的证书已经是新的,进程内存里加载的还是旧的,用 ls 看文件没问题,用户访问时拿到的还是旧证书。
单机 Nginx:Certbot 自己就能跑
只有一台服务器、一个 Nginx 时,Certbot 自带的自动续期加一个 reload hook 通常就解决问题。没必要一上来引入平台,多一层系统也意味着多一层维护成本。
需要做的就是把下面三件事检查到位。
定时任务真的存在
在 systemd 系统上看 timer:
systemctl list-timers | grep certbot
如果是 cron,就检查系统 crontab 或当前用户的 crontab。不要只记得“我当时好像装过 Certbot”,要看到明确的定时任务。
dry-run 能跑通
改完证书配置、DNS 配置或 Web 入口规则后,跑一次测试续期:
certbot renew --dry-run
它能提前暴露 HTTP-01 路径被拦、DNS-01 Token 没权限、插件参数失效这类问题。
续期后会 reload 服务
Certbot 支持 hook。续期成功后 reload Nginx:
certbot renew --deploy-hook "systemctl reload nginx"
不想每次在命令里写也可以把脚本放到 Certbot 的 renewal hooks 目录里。关键不是写在哪,而是证书真的更新后服务会重新加载。
certbot renew --dry-run 默认不会直接替换正式证书。新版 Certbot 有
--run-deploy-hooks 参数,可以在 dry-run 成功后执行 deploy
hook,但它用的是当前正式证书,不是测试证书。测试 reload 时要看清楚这一点。
泛域名:DNS-01 的问题通常出在细节
如果你要申请 *.example.com,就不能用 HTTP-01,必须用 DNS-01。用 Certbot 的话,通常需要配一个DNS 插件,让它自动创建和清理 _acme-challenge 的 TXT 记录。
DNS-01 的原理很简单:ACME 客户端在 _acme-challenge.example.com 写一条 TXT 记录,Let's Encrypt 查到了正确值,就认为你控制这个域名。
麻烦在工程细节:
- DNS 服务商必须支持 API。
- API Token 权限要收小,不能直接用全局密钥。
- DNS 记录有传播时间,不是控制台显示创建成功就马上能被 CA 查到。
- 同一个
_acme-challenge可能需要多个 TXT 值,脚本不能简单覆盖。 - Token 过期、权限被改、zone 迁移,都会导致续期失败。
周期越短,这些边角条件被触发得越频繁。只要其中一步依赖人工记忆,续期失败就只是时间问题。
多入口部署:签发成功只是第一步
一张 *.example.com 证书可能同时用于:
api.example.com的 Nginx。admin.example.com的负载均衡。docs.example.com的 CDN。internal.example.com的内网网关。
续期后要把同一张证书部署到这些地方,方式还不一样:
- SSH 主机要复制文件并 reload 服务。
- 云负载均衡要上传证书并切换监听器绑定。
- CDN 要调用平台 API 或进控制台替换证书。
- Kubernetes 要更新 Secret,再等 Ingress 控制器加载。
到这一步,你维护的已经不是一条续期命令,而是一套分发和生效确认流程。部署完成后还要反查线上结果——不能只相信“API 返回成功”,要检查用户访问到的证书是不是新证书。否则就会出现证书平台显示已更新,某个边缘节点或某个旧入口还在返回旧证书的情况。
什么时候该用 CertFlow
CertFlow 不是替代所有 ACME 客户端。单机单站点,用 Certbot 很合适。
它更适合这种场景:
- 你有多个域名或多张证书。
- 你在用泛域名证书,需要 DNS-01。
- 同一张证书要部署到多台服务器或多个云产品。
- 你不想靠表格记录“这张证书现在放在哪里”。
- 你希望失败时能知道失败在哪一步,而不是等用户报错。
证书已经分散在多台主机、云产品和 CDN 上时,CertFlow 的价值不在“再签一张证书”,而在续期之后的动作能被串起来:
- 证书快到期时自动触发续期。
- 通过 DNS-01 完成域名验证。
- 续期成功后部署到指定目标。
- 跟踪部署目标状态,并配合证书监控发现线上入口是否还在使用旧证书。
- 失败时给出明确状态,方便处理。
这样能把问题定位到具体环节:DNS 验证失败、证书续期失败、部署目标失败,还是线上入口仍在返回旧证书。
证书过期是最不复杂的故障
证书有效期从 90 天走向 64 天、45 天以后,原来那些“偶尔手工处理一下”的地方,会越来越容易出事。
证书过期不是复杂故障,它很简单也很刺眼。页面打不开,浏览器直接报错,用户不会关心你是 DNS Token 失效还是某台机器没 reload。