证书过期导致整站打不开,是运维里最冤枉的一类事故——明明设了自动续期,却没人验证它到底有没有跑成。
先确认续期任务在不在
crontab -l | grep acme
systemctl list-timers | grep certbot
宝塔用的是 acme.sh,一般在 crontab 里能看到类似 20 4,10,16,22 * * * 这样的定时。没有这一行,就说明续期根本没被安排上。
原因一:域名解析变了
acme.sh 的 HTTP 验证需要访问到你的服务器。如果域名换过解析、CDN 接管了源站、或者 DNS 记录指向了别处,验证就会失败。日志里通常是 Challenge failed 或 Invalid response。
原因二:80 端口被占用或拦截
HTTP-01 验证要求 80 端口能从公网访问。以下几种情况会让它失败:
- 服务器防火墙只放行了 443
- Nginx 上配了强制跳转 HTTPS,把验证请求也跳走了
- CDN 开了"强制 HTTPS"或者"防止 CC"
排查方法很直接:用另一台机器 curl -I http://你的域名,看能不能拿到 200 或者 301。
原因三:证书文件权限被改
acme.sh 续期时需要读写自己的配置目录。如果之前用 root 跑,后来用 www 用户跑,或者目录被 chown 过,就会报权限错误。检查 ~/.acme.sh/ 的属主。
原因四:续期成功但站点没重载
这种情况最隐蔽:证书文件更新了,但 Nginx 还在用旧证书的内存副本,页面依旧显示过期。解决办法是在续期命令后面挂上重载:
acme.sh --renew -d yourdomain.com --force --reloadcmd "nginx -s reload"
原因五:域名数量或类型不匹配
申请时带了多个域名,续期时其中一个域名解析失效,整张证书都会续期失败。多域名站点要定期确认每个域名都还活着。
怎么验证续期真的有效
不要等到过期那天才知道。每季度手动跑一次强制续期,看输出:
acme.sh --renew -d yourdomain.com --force
成功会打印 Cert success。同时用 openssl x509 -in 证书路径 -noout -dates 看实际到期时间,确认文件真的被替换了。
更省心的做法是把"证书剩余天数"纳入监控:低于 15 天就告警。这样即使自动续期某天悄悄坏了,你也有半个月时间从容处理,而不是在用户打不开网站时才发现。




还没有评论,来说两句吧...