用免费通配符证书有个绕不开的问题:90 天就过期。
我管着三个子域名,api.xxx.com、admin.xxx.com、cdn.xxx.com,一开始每个域名各申请一张单域名证书,后来换了通配符证书,*.xxx.com 一张搞定。省事是省事了,但每隔三个月就得续签一次,忘了就全挂。
上个月就翻了一次车。周一早上收到用户反馈说网站打不开,我一看浏览器,NET::ERR_CERT_DATE_INVALID------证书两天前就过期了。三个子域名全红。
从那之后我把续签流程从头理了一遍,记录在这里。
先看当前证书什么时候到期
续签之前先确认一下现状。终端跑这条:
bash
echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null \
| openssl x509 -noout -dates
输出类似:
ini
notBefore=May 1 00:00:00 2026 GMT
notAfter=Jul 30 23:59:59 2026 GMT
notAfter 就是到期时间。管好几个域名的话,写个循环一次查完:
bash
for domain in api.xxx.com admin.xxx.com cdn.xxx.com; do
end=$(echo | openssl s_client -servername "$domain" -connect "$domain":443 2>/dev/null \
| openssl x509 -noout -enddate | cut -d= -f2)
echo "$domain → $end"
done
续签:拿到新证书
免费通配符证书签发需要 DNS 验证------CA 要求你在域名 DNS 里加一条 TXT 记录,证明域名是你的。
如果你的证书管理平台支持对接 DNS 服务商(阿里云 DNS、Cloudflare 这类),这一步可以自动完成:提前配好 DNS 服务商的密钥,续签时平台自动加 TXT 记录、等验证通过、签发新证书。几分钟搞定。
手动的话,得自己去 DNS 控制台加记录、等生效、再回来点签发,来回十几分钟。域名一多很容易漏。
拿到新证书后,通常是两个文件:
fullchain.pem:你的证书 + 中间证书(CA 的信任链)privkey.pem:私钥
有些地方给的是分开的三个文件(证书、中间证书、私钥),需要自己合并:
bash
cat your_cert.pem intermediate.pem > fullchain.pem
部署到 Nginx
拿到新的证书文件,替换 Nginx 配置里指向的路径。
我习惯用固定路径,这样每次续签只替换文件,不改 Nginx 配置:
nginx
server {
listen 443 ssl;
server_name *.xxx.com;
ssl_certificate /etc/nginx/ssl/xxx.com/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/xxx.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers on;
# ...
}
替换完证书文件之后:
bash
# 先检查配置语法
nginx -t
# 没问题再 reload(不是 restart)
nginx -s reload
这里有个容易踩的坑:不要用 systemctl restart nginx。reload 就够了,restart 会断开所有现有连接。如果线上有 WebSocket 长连接,用户会直接感知到断连。reload 是平滑切换,旧的 worker 处理完手头请求再退出。
续签后验证
reload 之后,再跑一次 openssl 确认新证书生效:
bash
echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null \
| openssl x509 -noout -dates -subject
看 notAfter 是不是已经刷新到 90 天之后。
浏览器测试的话要注意,浏览器有 TLS session 缓存,可能看到的还是旧证书。换隐私窗口,或者用 curl 更靠谱:
bash
curl -vI https://example.com 2>&1 | grep -E "expire date|subject"
踩过的几个坑
只换了证书,没换中间证书
证书的信任链是"根证书 → 中间证书 → 你的证书"。如果你只替换了自己的证书,中间证书没更新,Chrome 可能正常(它会自动补链),但 Firefox、Safari 报错。
所以每次续签,fullchain.pem 要整个替换。别只换里面第一段。
证书文件权限
新证书文件权限别忘了设。Nginx worker 通常以 www-data 或 nginx 用户运行,需要能读到证书:
bash
chmod 644 /etc/nginx/ssl/xxx.com/fullchain.pem
chmod 600 /etc/nginx/ssl/xxx.com/privkey.pem
chown root:root /etc/nginx/ssl/xxx.com/*.pem
私钥 600 就够,不要给太大。
改了文件但没 reload
听起来不可能,但我真干过。半夜续签完证书,nginx -t 也跑了,然后直接关了终端去睡觉。第二天用户反馈还是旧证书------因为忘了 nginx -s reload。
多台机器只更新了一台
如果有多台 Nginx 做负载均衡,每台都得更新证书。漏了一台,用户会随机碰到新证书或旧证书,排查起来非常迷惑。
90 天一轮,靠脑子记不住
免费通配符证书 90 天到期,一年续签四次。靠自己记日子不现实。
最早我试过 crontab 跑脚本检查剩余天数,不到 14 天就发邮件提醒。原理可行,但出过几次状况:
- 机器重装,crontab 没了,我也忘了重新加
- 发邮件依赖本机 postfix,没配好的话邮件发不出去也不报错
- DNS 偶尔抽风,openssl 连接超时,脚本静默退出
一个监控脚本自己都不可靠,它还能监控什么。
后来换了在线的证书监控。填个域名就行,到期前自动通过微信推提醒。这类服务不用自己运维,不存在"crontab 丢了"的问题。
另外,如果你同时用了阿里云 CDN,有些证书管理平台在续签完成后能把新证书自动同步到 CDN,不用再手动去阿里云控制台换。但 Nginx 服务器上的证书替换没法省,这一步还是得自己来。
整个流程说起来不复杂,真正麻烦的是"定时记得做"。把到期提醒设好,剩下的几条命令跑一遍,十分钟搞定。
我目前用 ssl.spug.cc 管通配符证书和到期提醒,够用。