入门指南
续期从不报错:四个时限、三种验证,与一份不依赖邮件的证书巡检
Let’s Encrypt 已停止到期提醒邮件。能不能续上,取决于触发方式、验证端口与失败限额三件独立的事。把四个时限拆开,给一份十分钟巡检与上线验收单。
续期是四条独立链路,任何一条断了都不会报警。

先看答案
- 适合谁
- 把证书交给「自动续期」之后就没再看过的独立开发者
- 站点在 Cloudflare 后面、源站 80 端口被封却不自知的人
- 续期脚本日志全绿,浏览器却弹出证书过期警告的人
- 你会获得
- 续期是四条独立链路,任何一条断了都不会报警。
- 发布时间
- 实质更新
- 发布
- AOPC 编辑部
60 秒结论
一分钟看懂这篇文章
续期是四条独立链路,任何一条断了都不会报警。
人负责
- 决定巡检频率
- 判断该不该换验证方式
AI 负责
- 核对线上证书指纹
- 比对磁盘与部署产物
- 拆分
- 探活
- 比对
- 留证
直接答案
「证书不是自动续期吗,怎么还会过期?」这个问题里有四条互相独立的链路。任何一条断了,都不会有人给你发消息:
| 时钟 | 它回答的问题 | 断了之后的样子 |
|---|---|---|
| ① 有效期 | 这张证书什么时候到期? | 到期当天整站报错,之前一切正常 |
| ② 续期触发 | 谁在什么时候去申请新证书? | 定时任务早就不再运行,没人发现 |
| ③ 验证可达 | CA 能不能访问到你的验证路径? | 站点 443 正常,验证却一直失败 |
| ④ 失败限额 | 失败太多次之后还能不能申请? | 越重试越糟,最后连手工签都被暂停 |
最常见的错误是把四条合成一条:「我配了自动续期」=「证书不会过期」。而在 2026 年,连最后一道人工兜底——到期提醒邮件——在 Let’s Encrypt 这里也已经没有了。
本文只讨论 ACME 体系(Let’s Encrypt 是其中最大的一个 CA)的公开行为,不推荐具体客户端品牌,也不假设你的证书一定是 90 天。
一、兜底的那封邮件已经没有了
Let’s Encrypt 的到期提醒页面,现在整页只剩一条公告:
Expiration Email Service Shut Down
Let’s Encrypt has ended its email expiration service.
页面标注的 Last updated 是 June 25, 2025。也就是说,从 2025 年起,「等一封还有 20 天到期」的邮件再处理」这条路径不再存在。
这条要限定范围:这是 Let’s Encrypt 的行为,不代表其它 CA 也停了邮件;反过来,即使你的 CA 还发邮件,收件人邮箱是不是你常用的那个、会不会进垃圾箱,也不由你控制。把「邮件提醒」当成监控,本来就是借别人的管道做自己的告警。
二、续期触发:三代做法,与一个反直觉的 Retry-After
RFC 9773 在开头把 ACME 客户端决定「什么时候续期」的做法归成三类:
- they may be configured to renew at a specific interval (e.g., via cron),
- they may parse the issued certificate to determine its expiration date and renew a specific amount of time before then, or
- they may parse the issued certificate and renew when some percentage of its validity period has passed.
它同时点出前两类的结构性问题:CA 一旦改变证书寿命(缩短或延长),写死间隔或写死「提前 N 天」的客户端就会失效或过早续期,而且大量客户端会在同一时刻涌上来。
ARI(ACME Renewal Information)就是为这件事设计的。 它的关键不是「又一个接口」,而是把「什么时候续」从客户端猜,改成 CA 建议:
| 机制 | 原文口径 | 运维含义 |
|---|---|---|
suggestedWindow |
含 start 与 end 的时间窗,CA 建议在这段内续期 |
不是「第 60 天」,是一段区间 |
| 取点方式 | 建议在窗口内均匀随机选一个时间;若已过去则立即续 | 同一批域名不会同时打过去 |
replaces 字段 |
新订单里带上它要替换的那张证书的标识 | 让 CA 认出「这是续期」而非新签 |
Retry-After |
在 ARI 里表示期望的最小与最大等待时间;其它 HTTP 场景里它通常只是最小等待 | 不能用通用 HTTP 客户端的语义去理解 |
| 过期之后 | 客户端 MUST NOT 再查这张证书的 RenewalInfo | 过期后再查没有意义,也救不回来 |
| 长期错误 | 下一次查询应在 6 小时后(或本地配置的默认值) | 不是每秒重试 |
Let’s Encrypt 自己的接入指南给了两条可以照抄的节奏:
We recommend checking ACME Renewal Information for each certificate at least twice a day. The ARI endpoint will recommend when to renew.
As a backstop to ARI, we recommend renewing certificates automatically when they have a third of their total lifetime left. For certificates with a validity period under 10 days, we recommend renewing halfway through their total lifetime. For Let’s Encrypt’s current 90-day certificates, that means renewing 30 days before expiration.
拆成两层看:
- 主路径是 ARI:一天至少查两次,按它给的窗口续。
- 兜底是寿命比例:剩下三分之一时就该续;寿命不足 10 天的证书,用一半寿命作为节点。对 Let’s Encrypt 当前的 90 天证书,这个兜底点就是到期前 30 天。
「一天至少两次」不是随口给的数字:ARI 的窗口可能因为 CA 侧的原因(例如计划中的大规模吊销)提前,只查一次就会错过。这也是本文建议把「检查 ARI」放进每日任务、而不是每月任务的原因(编辑判断:具体次数按你的客户端能力定,两次是官方下限建议)。
同一个页面还有一条容易被忽略的运维建议:如果你的软件会装一个周期性批处理任务,请让它在一天里随机的那一秒运行,而不是固定整点——理由与本文无关但同源:整点的流量尖峰要由 CA 按峰值扩容。
续期失败不该被当成致命错误
同一份接入指南对失败重试给了具体节奏:
You should implement graceful retry logic in your issuing services using an exponential backoff pattern, maxing out at once per day per certificate. For instance, a reasonable backoff schedule would be: 1st retry after one minute, 2nd retry after ten minutes, 3rd retry after 100 minutes, 4th and subsequent retries after one day.
这里有一个方向性提醒:重试要退避,不能加速。 原因在下一节的限额里——失败次数本身是被计数的,越快重试,越快把配额打满。
三、三种验证方式:失败面完全不同
证书能不能签下来,取决于 CA 能不能验证「你控制这个域名」。三种方式做的事一样,失败的条件完全不一样:
| HTTP-01 | DNS-01 | TLS-ALPN-01 | |
|---|---|---|---|
| 验证位置 | http://<域名>/.well-known/acme-challenge/<TOKEN> |
_acme-challenge.<域名> 的 TXT 记录 |
443 端口上的 TLS 握手(自定义 ALPN) |
| 端口 | 只能 80 | 不涉及 | 443 |
| 通配符 | 不能 | 可以 | 不能 |
| 验证 IP | 可以 | 不可以 | 可以 |
| 自动化前提 | 80 端口可达、多台服务器返回同一文件 | DNS 服务商有 API、能确认传播 | 客户端支持(原文:支持有限) |
| 典型失败 | ISP 封 80、WAF 挡住挑战路径、多机不一致 | API 凭据风险、无 API、传播时间不明 | 反向代理不认这个 ALPN |
几条原文细节值得抄进排错清单:
- HTTP-01 只走 80 端口:「The HTTP-01 challenge can only be done on port 80. Allowing clients to specify arbitrary ports would make the challenge less secure, and so it is not allowed by the ACME standard.」
- 它跟随重定向,但最多 10 跳,且只接受
http:/https:、只接受 80/443 端口;跳到 HTTPS 时不校验证书(因为它本来就是在 bootstrap 证书,路上可能遇到自签名或过期证书)。 - 它可能从多个 vantage point 多次抓取,所以「我本机 curl 得到」不等于「CA 抓得到」。
- 多台服务器必须都能返回同一个文件,否则请求落到哪台就成哪台。
- DNS-01 的代价是凭据:原文把「Keeping API credentials on your web server is risky」列为 cons 第一条;另有「DNS API 可能不提供传播时间信息」。
- TLS-ALPN-01 不适合大多数人:原文是「This challenge is not suitable for most people. It is best suited to authors of TLS-terminating reverse proxies…」,且客户端支持有限。
这里有一个很常见的错位:站点在 443 上跑得好好的,于是「网站在线」被当成「验证没问题」。但 HTTP-01 走的是 80。80 被封、被 WAF 拦、被重定向到登录页,首页都仍然是 200。 监控首页证明不了验证路径可达(编辑判断,但不是推测:两者是不同端口、不同路径、不同规则集)。
四、失败会自我放大:限额不是「签多少张」那么简单
Let’s Encrypt 的限额按令牌桶逐请求计算,可以突发用完,也可以摊开用。更关键的是三条:没有临时重置的办法;容量只会随时间慢慢回填;吊销证书不会重置限额(「Revoking certificates does not reset rate limits, because the resources used to issue those certificates have already been consumed.」)。
对一人公司最相关的有四组:
| 限额 | 数值 | 计数范围 | 回填速度 |
|---|---|---|---|
| New Certificates per Registered Domain | 50 张 / 7 天(IPv4 按单地址、IPv6 按 /64 视作注册域) | 全局:不分账号,所有新订单都算 | 1 张 / 202 分钟 |
| New Certificates per Exact Set of Identifiers | 5 张 / 7 天(标识符集合完全相同) | 全局 | 1 张 / 34 小时 |
| Authorization Failures per Identifier per Account | 5 次 / 小时 | 单账号、单标识符 | 1 次 / 12 分钟 |
| Consecutive Authorization Failures per Identifier per Account | 1,152 次连续失败后暂停 | 单账号、单标识符 | 1 次 / 天,成功验证即归零 |
第 2 行是排错时最容易踩的:原文把「反复重装客户端」「每次部署都删掉 ACME 配置」列为常见原因,并说明这个限额故意设得低,就是为了防止有 bug 的系统快速吃掉别人的容量。改配置重试三次,就可能已经用掉 5 张里的 3 张。
第 4 行更隐蔽:它不是「每小时」限额,而是连续失败累计。官方给了一张换算表(Failures per Day → Time to Pause),摘几行:
| 每天失败次数 | 触发暂停需要 |
|---|---|
| 1 | 永不暂停 |
| 2 | 1,152 天(约 3.16 年) |
| 10 | 128 天 |
| 30 | 40 天 |
| 120 | 10 天 |
按 1,152 次总量与「每天回填 1 次」推算:每 5 分钟重试一次的脚本,一天 288 次失败,约 4 天就能把一个标识符打到暂停(这是按原文两个数字做的除法,非原文表述)。暂停之后每次申请都会返回一个指向自助门户的链接,可以在那里解封该标识符及账号下最多 49,999 个其它被暂停的标识符。
还有两类「看不见的」限额:
- 每 IP 的端点请求限额(如
/acme/new-order每秒 300 次、突发 200;/acme/new-nonce每秒 20 次)。超限返回 503 并带Retry-After。 - 续期豁免不是全豁免:ARI 续期豁免所有限额;非 ARI 续期(标识符集合完全相同、忽略大小写与顺序)只豁免 New Orders per Account 与 New Certificates per Registered Domain,仍受 Authorization Failures per Identifier per Account 与 New Certificates per Exact Set of Identifiers 限制。换句话说,「我在续期」不等于「不会撞限额」。
测试与排错该去哪,原文给了明确指向:staging 环境的限额「significantly higher」,且不消耗生产配额。
五、要监控的四个信号
把四件事分开监控,比监控「续期脚本退出码」有用得多:
- 到期时间:从外部看线上实际提供的那张证书,而不是看磁盘上的文件。
- 续期是否真的发生:证书指纹/序列号变了没有。命令退出 0 只说明命令跑完了。
- 部署是否跟上:新证书签下来之后,Web 服务器/负载均衡/CDN 边缘有没有加载它。磁盘上是新的、握手拿到的是旧的,是常见组合。
- 验证路径是否可达:80 端口、
.well-known路径、DNS TXT 三个入口分别探活。
再加一条「额度」:把续期失败的次数与原因记进日志,别让一个每 5 分钟重试的循环悄悄把连续失败次数推到 1,152。
过期不是「点一下继续访问」
如果域名带 HSTS,证书错误的后果会更硬。接入指南的原话:
while people can usually click through a browser warning about a name mismatch or expired certificate, browsers do not allow such a click through for hostnames with an active HSTS header.
也就是说,对启用了 HSTS 的站点,证书过期约等于整站不可用,不存在「用户点一下继续」的缓冲。至于 HSTS 的 max-age 该设多长、要不要 preload,是另一个话题,本文不展开。
六、十分钟巡检
以下命令在 macOS/Linux 自带工具范围内,按顺序执行。它们的共同点是都从外部看结果,不依赖续期脚本自己的日志。
① 线上实际提供的那张证书
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates -fingerprint -sha256
看三样:notAfter、签发者、SHA-256 指纹。把指纹抄下来,下次比对用。
② 还剩多少天(脚本友好)
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
| openssl x509 -noout -checkend 2592000
-checkend 2592000 是 30 天(秒)。输出 Certificate will not expire 时退出码为 0,否则非 0——这一条就能直接接进任何告警系统。
③ 磁盘上的证书与线上是不是同一张
openssl x509 -in /path/to/cert.pem -noout -fingerprint -sha256 -dates
两条指纹不一致,说明「签下来了但没部署」,或者「部署到了另一台机器」。这是本文最推荐先查的一项。
④ 链上的每一张都要看
echo | openssl s_client -connect example.com:443 -servername example.com -showcerts 2>/dev/null \
| grep -E '^ *[0-9]+ s:|^ *i:'
s: 是站点证书,i: 是签发者。中间证书也会过期;「我的证书没过期」不等于「链是完整的」。
⑤ HTTP-01 的路径是否可达
curl -sS -o /dev/null -w '%{http_code}\n' http://example.com/.well-known/acme-challenge/probe-not-exist
期望是 404(路径可达、文件不存在),不是 403、302 到登录页或 Cloudflare 的挑战页。真实验证时 CA 要的是那个 token 文件返回 200;这里用不存在的文件名,只为确认「请求能到达你的服务器」。
⑥ DNS-01 的记录是否还在
dig +short TXT _acme-challenge.example.com
不是每次都要有记录(验证完通常可以删),但如果你的客户端依赖「长期保留的 CNAME 委派」,这条能确认委派没断。
⑦ ARI 有没有在跑
没有一条通用命令——ARI 的地址与证书标识由 CA 与客户端决定。能查的是客户端日志里有没有 renewalInfo 相关请求,以及它上次给出的窗口是什么时候。如果你的客户端根本不支持 ARI,就退回到「寿命三分之一」的兜底,并把这件事写进运维笔记,而不是假设它在工作。
七、上线验收单
| # | 检查项 | 怎么验 | 不通过的样子 |
|---|---|---|---|
| 1 | 到期提醒邮件已不作为唯一告警 | 问自己:邮件停了会怎样 | 没人知道证书哪天到期 |
| 2 | 有独立的到期探测(外部握手) | 上面第 ② 条接进告警 | 只有续期脚本的日志 |
| 3 | 续期触发方式写下来了 | 文档里能查到是 ARI 还是固定间隔 | 换台机器就不知道原来怎么配的 |
| 4 | 有「寿命三分之一」的兜底 | 配置里能找到这个阈值 | ARI 一失效就永久不续 |
| 5 | 重试是退避的,不是每 5 分钟 | 看失败重试代码 | 失败越多、撞限额越快 |
| 6 | 测试走 staging | 配置里能切换 | 排错时把生产配额打满 |
| 7 | 验证端口(80 或 443)从公网可达 | 外部探测,不用本机 curl | 站点 443 正常、验证全失败 |
| 8 | 多台服务器返回同一验证内容 | 逐台请求同一路径 | 请求落到哪台全看运气 |
| 9 | 部署后比对指纹 | 第 ③ 条 | 磁盘新、线上旧 |
| 10 | 链证书也在检查范围内 | 第 ④ 条 | 叶子证书正常、中间证书过期 |
| 11 | 失败了有人知道 | 告警能到达人 | 日志里全是 error,没人看 |
八、五种常见误读
误读一:「自动续期配好了,就不会过期。」 「配好」只覆盖了第 ② 个时钟。验证路径、部署、限额任何一个变了,续期都会失败,而且失败通常不发出任何声音。
误读二:「续期命令退出 0,就是续上了。」
退出 0 只说明这个进程正常结束。要看指纹变没变、notAfter 有没有往后推。
误读三:「证书签下来了,网站就是新的了。」 签名与部署是两件事。反向代理、负载均衡、CDN 边缘都可能还拿着旧证书;磁盘上的文件更新不等于握手里的是它。
误读四:「HTTP-01 可以换个端口,也能签通配符。」 两件都不行。端口只能是 80,通配符只能走 DNS-01。
误读五:「续期不占限额。」 ARI 续期豁免所有限额;非 ARI 续期只豁免两条,仍受另外两条限制。而且失败次数本身就是一条独立的限额。
九、本周就能做的五件事
- 现在就跑一次第 ② 条,把「还剩多少天」变成一个数字。
- 把线上指纹与磁盘指纹各抄一份,对一下是不是同一张。
- 确认 80 端口从公网可达(哪怕你的站点全站 HTTPS)。不可达就把验证方式换成 DNS-01。
- 把重试逻辑改成退避:1 分钟、10 分钟、100 分钟,之后每天一次。
- 删掉「等邮件提醒」这个假设,在日历上留一个每月一次的巡检,或者把它接进现成的告警系统。
如果只能记住一件事:证书过期从来不是「续期那一步」失败,而是四条链路里最安静的那条先断了。
边界说明:本文关于 Let’s Encrypt 的陈述全部来自其四个公开文档页(2026-10-29 访问,均 HTTP 200:expiration-emails 25 466 B、rate-limits 44 071 B、challenge-types 34 029 B、integration-guide 40 181 B),ARI 的协议语义来自 RFC 9773(同日访问,HTTP 200,25 666 B,IETF Standards Track,2025-06)。不写「Let’s Encrypt 会发到期提醒」、「HTTP-01 支持任意端口/可签通配符」、「续期一定不撞限额」、「自动续期=不会过期」,也不写任何「续期成功率」「故障时长」数字。文中标注为编辑判断的三处:每日检查次数的具体取值、80 端口与站点可用性的错位、以及巡检项优先级排序。第六节的命令是通用工具用法,不是上述来源的原文;-checkend 的秒数按 30 天换算(30×24×3600),闰秒不影响该用途。第四节的「约 4 天」是按原文 1,152 次与每天 288 次做的除法,非官方表述;暂停换算表仅摘录四行,完整表以原文为准。本文不推荐任何 ACME 客户端或托管服务品牌。
来源
以下页面均于 2026-10-29 逐条访问并验证为 HTTP 200;字节数为当日抓取的实际大小。
- Expiration Emails · Let’s Encrypt核查于 2026/10/29(200,25 466 B;页面标注 Last updated June 25, 2025):整页只剩公告「Expiration Email Service Shut Down」与一句「Let’s Encrypt has ended its email expiration service.」。
- Rate Limits · Let’s Encrypt核查于 2026/10/29(200,44 071 B;Last updated August 5, 2026):限额按令牌桶逐请求计算;无临时重置手段、吊销不重置;New Registrations per IP 10 个 / 3 小时(回填 1 个 / 18 分钟)、per IPv6 /48 500 个 / 3 小时;New Orders per Account 300 个 / 3 小时(1 个 / 36 秒);New Certificates per Registered Domain 50 张 / 7 天、全局(IPv4 按单地址、IPv6 按 /64,回填 1 张 / 202 分钟);New Certificates per Exact Set of Identifiers 5 张 / 7 天、全局(回填 1 张 / 34 小时,不提供 override);Authorization Failures per Identifier per Account 5 次 / 小时(1 次 / 12 分钟);Consecutive Authorization Failures 1,152 次、回填 1 次 / 天、成功即归零,暂停后经自助门户解封(可含最多 49,999 个其它标识符),并附 Failures per Day → Time to Pause 换算表;端点级每 IP 限额(如
/acme/new-order300/s、突发 200;/acme/new-nonce20/s)超限返回 503 与Retry-After;ARI 续期豁免所有限额,非 ARI 续期豁免 New Orders per Account 与 New Certificates per Registered Domain、仍受另外两条限制;排错建议改用 staging(限额显著更高)。 - Challenge Types · Let’s Encrypt核查于 2026/10/29(200,34 029 B;Last updated February 12, 2026):HTTP-01 文件位于
/.well-known/acme-challenge/<TOKEN>、CA 可能从多个 vantage point 多次抓取;重定向最多 10 跳、仅 http/https、仅 80/443、跳 HTTPS 时不校验证书;只能 80 端口、不能签通配符、多台服务器须返回同一文件、ISP 封 80 会失败、可验证 IP;DNS-01 用_acme-challengeTXT、可签通配符、不能验证 IP,cons 含「API 凭据放在 Web 服务器上有风险」「服务商可能不提供 API」「可能不提供传播时间信息」;TLS-ALPN-01 走 443、RFC 8737、自定义 ALPN、「not suitable for most people」、客户端支持有限、多台服务器同样要一致、不能签通配符、可在 80 不可用时使用。 - Integration Guide · Let’s Encrypt核查于 2026/10/29(200,40 181 B):建议每张证书每天至少查两次 ARI;兜底为「剩余寿命三分之一」时续期,寿命不足 10 天的证书用一半寿命,对当前 90 天证书即到期前 30 天;失败应按指数退避、每张证书最多每天一次(示例 1 分钟 / 10 分钟 / 100 分钟 / 之后每天);周期任务应在一天中随机秒运行;启用 HSTS 时浏览器不允许对过期证书「点击继续」;建议前端优先从持久存储取证书,取不到再签发。
- RFC 9773: ACME Renewal Information (ARI) Extension核查于 2026/10/29(200,25 666 B;IETF Standards Track,2025-06):三种传统续期策略及其对 CA 调整寿命的阻碍;
suggestedWindow含start/end,建议窗口内均匀随机取点、已过去则立即续;replaces字段标识被替换的证书;ARI 的Retry-After表示期望的最小与最大等待(与一般 HTTP 语义不同);证书过期后或被视为已替换后客户端 MUST NOT 再查 RenewalInfo;长期错误后下一次查询应在 6 小时后(或本地默认值);服务端对Retry-After的取值考量(如预留 12 小时调查、6 小时拉取、6 小时续期)。