证书过期,是一种很冤的故障
证书过期的开场大都差不多:半夜收到用户反馈,或者第二天上班发现官网打不开。点开一看,Chrome 直接甩出红色警告页——「您的连接不是私密连接」。用户可以点「高级 → 继续访问」进来,但绝大多数访客看到警告就走了。
浏览器警告页只是看得见的那层,背后还有:
- 依赖 HTTPS 的接口会握手失败——App 的 API 请求、支付回调、小程序后台全都会断,而且往往挑半夜或节假日爆发;
- 搜索引擎对出现安全警告的站点会降低信任评级,警告解除后恢复也需要时间;
- 支付、登录这类关键链路一断,损失就不是「页面难看」的问题了。
说到底,证书过期几乎从来不是技术难题,纯粹是没人盯着。所以真正值得讨论的不是「怎么查」,而是怎么让「查」这件事不再依赖人。下面按场景说三种做法。
方法一:浏览器里点两下(临时确认单个站)
- 用 Chrome / Edge 打开目标网站;
- 点地址栏左侧的锁图标;
- 选「连接是安全的」→「证书有效」,就能看到有效期至(Not After)。
零门槛,适合「我就想看看这个站还剩几天」的场景。缺点也很直白:一次只能看一个,看不到未来,更不会提醒你。手上域名超过三五个,这条路基本就走不通了。
方法二:openssl 一条命令(上服务器排查用)
在任意能联网的机器上:
echo | openssl s_client -servername example.com \
-connect example.com:443 2>/dev/null | \
openssl x509 -noout -enddate
输出长这样:
notAfter=Dec 30 23:59:59 2026 GMT
配上 -checkend 可以做阈值判断,写成脚本丢进 crontab——很多团队确实就是这么干的。但坑在通知这一层:脚本只负责查,查出来问题谁来告诉你?接邮件、接群机器人、排值班表,每一样都是额外的工程。漏了这一层,脚本天天跑,证书照样过期。
方法三:交给监控工具盯着(域名多、用免费证书的正解)
如果你管着十几二十个域名,或者用的是 Let's Encrypt 这类 90 天有效期的证书——一年要续四次——人工台账早晚要漏。到这个规模,合理的做法就是把「查」外包给工具。
比如本站的监控(免费):添加域名后,系统会定时做 TLS 握手、算好剩余天数放在控制台里,低于阈值(默认 30 天,可调)自动推钉钉、企业微信或邮件。网站可用性也在同一套告警里,宕机、恢复、证书异常不用分开盯。数据在自己服务器上,域名清单不出门。
比较省心的组合:方法一、二处理临时排查,方法三做长期兜底。另外别太相信自动续期——acme.sh 定时任务跑成功了、但忘了 reload Nginx 的例子一抓一大把,到期监控这时候就是最后一道网。
证书为什么总是「悄悄」过期
事后复盘,基本都落在三种情况里:
- 有效期越来越短。Let's Encrypt 只有 90 天,一年续 4 次,靠台账记早晚漏;
- 证书分散。主站、API、支付回调、小程序后台各一张,到期日错开,没有统一视图谁也记不住;
- 续期不等于部署。新证书签下来了,服务器上的旧证书没换、Nginx 没 reload,一样过期。
根子上是缺一个自动的、能统一看到所有到期日的视图。人盯人是盯不住的,这件事只能交给系统做。
常见问题
证书到期会怎样?
浏览器弹「不安全」警告,多数访客直接走人;API 和支付回调握手失败;SEO 信任评级也会掉。具体见开头那节。
到期前多久续期合适?
30 天内就该收到预警了,7 天以内算紧急。用了自动续期也别撤监控——acme.sh 跑成功了但忘了 reload Nginx 的情况太常见,监控是兜底。
免费证书和付费证书的区别?
加密强度没区别。差别在有效期(免费的一般 90 天)和保障条款(付费的带保险、能做 OV/EV)。有效期越短越靠自动化,所以免费证书反而更需要配监控。
An expired certificate is the most avoidable outage
Most expiry incidents start the same way: a user report late at night, or a "the site is down" message the next morning. Open the browser and there it is — Chrome's red warning page, "Your connection is not private". Visitors can click through via Advanced, but most of them just leave.
The warning page is only the visible part:
- Anything depending on HTTPS fails its TLS handshake — app APIs, payment webhooks, admin panels. These tend to break at night or on holidays;
- Search engines lower their trust in sites showing security warnings, and recovery takes time even after the cert is fixed;
- When payment or login flows break, the cost goes well beyond an ugly page.
An expired certificate is almost never a hard technical problem — it's a nobody-was-watching problem. So the real question isn't "how do I check the expiry" but "how do I stop checking it manually". Three approaches below, by scenario.
Method 1: The browser (quick check for one site)
- Open the site in Chrome / Edge;
- Click the padlock icon in the address bar;
- Choose "Connection is secure" → "Certificate is valid" to see the Not After date.
Zero setup, fine for "how many days left on this one site?". But it doesn't scale: one domain at a time, no visibility into the future, no reminders. Past a handful of domains, this path is dead.
Method 2: One openssl command (server-side checks)
From any machine with network access:
echo | openssl s_client -servername example.com \
-connect example.com:443 2>/dev/null | \
openssl x509 -noout -enddate
Output looks like:
notAfter=Dec 30 23:59:59 2026 GMT
Pair it with -checkend for threshold checks, wrap it in a cron script — plenty of teams do exactly that. The catch is the notification layer: the script only checks. Who tells you when something's wrong? Email, a chat bot, an on-call rota — all extra engineering. Skip that layer and the script runs every day while the certificate still expires.
Method 3: Let a monitoring tool watch it (many domains / free certs)
If you manage a dozen-plus domains, or run Let's Encrypt certificates with their 90-day lifetime — four renewals a year — manual tracking will slip eventually. At that scale, checking should be delegated.
This site's monitoring (free) does exactly that: add a domain and it runs periodic TLS handshakes, keeps days-until-expiry in the dashboard, and pushes alerts to Slack, Telegram, Discord or email once the remaining days drop below a threshold (30 by default, adjustable). Uptime monitoring rides on the same alert stream — downtime, recovery and certificate issues in one place. Self-hosted, so your domain inventory never leaves your server.
A combination that works well: methods 1–2 for ad-hoc checks, method 3 as the safety net. And don't trust auto-renewal alone — acme.sh succeeding while nobody reloads Nginx is a classic. Expiry monitoring is the last line of defense.
Why certificates expire "silently"
Post-mortems usually land on one of three things:
- Shorter lifetimes. Let's Encrypt gives you 90 days, four renewals a year — a spreadsheet will slip;
- Scattered certificates. Main site, API, payment webhook, admin panel — each with its own expiry date and no unified view;
- Renewal is not deployment. A fresh certificate in a directory changes nothing until it's installed and Nginx is reloaded.
The underlying issue is the lack of one automatic view of every expiry date. Humans can't be relied on for this; it has to be a system.
FAQ
What happens when an SSL certificate expires?
Browsers show the security warning and most visitors leave; APIs and payment callbacks fail TLS handshakes; SEO trust drops. Details in the first section.
How early should I renew?
You want an alert by 30 days out; 7 days is urgent. Keep monitoring even with auto-renewal — a successful acme.sh run with a forgotten Nginx reload is far too common. Monitoring is the fallback.
Free vs paid certificates?
No difference in encryption strength. Paid certs offer longer validity, warranty and OV/EV validation; free ones are typically 90 days. Shorter validity means more dependence on automation — so free certificates actually need monitoring more.