Let’s Encrypt 证书续期失败的六种原因

Let’s Encrypt 证书 90 天到期,自动化续期失效是「定时炸弹」——平时看不出问题,某天浏览器突然全站报「不安全」。本文列六种常见的续期失败原因与对应诊断方法。

先说结论:先查「为什么失败」,再决定怎么续

不要直接手动跑 certbot renew --force-renewal。ACME 有「失败次数限制」(同一域名每周 5 次),盲目重试会把自己锁死一周。

# 1. 看续期日志(最关键)
docker logs <certbot容器> 2>&1 | tail -50
1. 或
tail -100 /var/log/letsencrypt/letsencrypt.log

1. 2. 先做 dry-run 测试(不消耗次数)
certbot renew --dry-run

1. 3. 看证书实际剩余时间
openssl x509 -in /etc/letsencrypt/live/example.com/fullchain.pem -noout -dates

原因一:验证方式失效(HTTP-01 的 80 端口问题)

ACME 要访问 http://yourdomain/.well-known/acme-challenge/xxx 验证域名控制权。以下都会失败:

  • 80 端口被防火墙封了(或安全组没开)
  • 80 全部 301 跳到 443,而跳转规则没放行 /.well-known/
  • Nginx 配置里给了 443 强制跳转但 ACME challenge location 写错
  • CDN 层拦了 80 请求(如 Cloudflare 的「始终 HTTPS」)
# 自测:模拟 ACME 的访问路径
curl -I http://example.com/.well-known/acme-challenge/test
1. 期望 404(路径不存在但可达),若 301/403 就是被跳转或拦了

1. 看 nginx 的 challenge 配置
grep -A5 "well-known" /etc/nginx/conf.d/*.conf

正确配置(位置要在跳转规则之前):

server {
    listen 80;
    server_name example.com;

    1. 先匹配 ACME,再跳转——顺序错了就永远走不到这里
    location ^~ /.well-known/acme-challenge/ {
        root /var/www/certbot;
        default_type "text/plain";
        try_files $uri =404;
    }

    location / {
        return 301 https://$host$request_uri;
    }
}

原因二:DNS 记录变了

  • 域名 A 记录指向了新 IP,但新服务器还没配好
  • 多级子域名的 DNS 解析没跟上(如 blog.x-rush.cn 的 CNAME)
  • DNS 传播未完成(TTL 还很长)
# 确认解析是否指向当前服务器
dig +short example.com A
curl -s ifconfig.me    # 或 curl -s ipinfo.io/ip

1. 对比:解析出的 IP 是否等于本机公网 IP

原因三:证书文件权限或路径错

certbot 写入证书时,如果你的容器以非 root 用户挂载了证书目录,可能写不进去。

# 看证书目录权限
ls -l /etc/letsencrypt/live/example.com/
ls -l /etc/letsencrypt/archive/

1. 看 certbot 容器的挂载与用户
docker inspect <certbot容器> --format '{{range .Mounts}}{{.Source}} -> {{.Destination}}{{"\n"}}{{end}}'
docker inspect <certbot容器> --format '{{.Config.User}}'

1. 常见问题:archive 目录属主 root 700,容器内非 root 写不进

原因四:ACME 客户端版本过旧 / 协议不兼容

Let’s Encrypt 已停止支持老版 ACME 客户端(如早年的 acme-tiny、旧版 certbot 1.x)。同时某些第三方 ACME 服务已下线。

# 看版本
certbot --version
1. 建议 2.x 以上

1. 若用 acme.sh
acme.sh --version

1. 注意:部分 ACME 端点已失效(如某些商业 CA 的免费接口),
1. 报 404 或 "unauthorized" 时要换回 Let's Encrypt 官方端点

我们实测遇到过:acme.sh 配了某商业 CA 的免签接口,对方端点下线后一直报 404,日志里看不出是「端点失效」还是「配置错」。换回 Let’s Encrypt 官方端点后立刻正常。

原因五:续期任务的 cron 时间不对

  • cron 任务被注释掉了(升级脚本时误删)
  • cron 里用的路径是旧路径(迁移目录后没改)
  • 容器重启后 cron 没跑(如果用 @reboot 触发但容器还没起来)
  • 续期成功后 Nginx 没 reload:证书更新了但 Nginx 还加载着旧证书
# 看 cron
crontab -l | grep -iE "certbot|acme|renew"

1. 看确切的续期脚本
cat /path/to/renew.sh

1. 关键:续期成功后必须 reload nginx
1. renew.sh 里应有:
docker exec <nginx容器> nginx -s reload
1. 或
docker exec <nginx容器> nginx -t && docker exec <nginx容器> nginx -s reload

原因六:域名数量太多或含已弃用域名

一张证书包含多个 SAN(如 x-rush.cn + blog + www),任何一个域名验证失败,整张证书都续不了。

# 看证书包含哪些域名
openssl x509 -in fullchain.pem -noout -ext subjectAltName

1. 逐个测试可达性
for d in example.com www.example.com blog.example.com; do
  echo -n "$d: "
  curl -sI "http://$d/.well-known/acme-challenge/test" | head -1
done

处理:把已不用的域名从证书里移除(用 --cert-name 重新签发一张不含它的证书)。

一条完整的诊断流程

# 1. 剩余天数
EXP=$(openssl x509 -in /path/fullchain.pem -noout -enddate | cut -d= -f2)
echo "到期: $EXP"

1. 2. 最近一次续期结果
docker logs <certbot容器> 2>&1 | grep -iE "error|fail|success" | tail -10

1. 3. dry-run(不消耗次数)
certbot renew --dry-run 2>&1 | tail -20

1. 4. 若 dry-run 失败,看具体哪个域名/哪个验证方式
1.    日志里会有 "Failed authorization procedure"

1. 5. 验证路径可达性
curl -I http://example.com/.well-known/acme-challenge/test

1. 6. 检查 nginx 配置顺序(challenge 必须在跳转之前)
grep -B2 -A8 "acme-challenge" /etc/nginx/conf.d/*.conf

总结

  • 先 dry-run 再动手:ACME 有失败次数限制(每周 5 次),盲目 force-renew 会锁死一周
  • 80 端口的 challenge 路径必须在 301 跳转之前:这是最常见也最容易忽略的配置错误
  • 多域名证书是「全或无」:任一个域名验证失败,整张证书都续不了
  • 续期成功后必须 reload nginx:否则证书文件更新了,进程里还是旧的
  • <优先查日志里的 “Failed authorization procedure”:它会直接告诉你是哪个域名、用哪种验证方式失败
暂无评论

发送评论 编辑评论

|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇