服务公告
Let's Encrypt - LetsEncrypt常见问题汇总
发布时间:2026-05-02 20:01
本文解决Let's Encrypt证书申请、续期、验证失败等常见问题,提供CentOS/RHEL和Ubuntu双发行版实战方案
一、前言
干了10年运维,Let's Encrypt的坑基本踩了个遍。续期脚本突然不跑了、泛域名验证卡死、nginx reload后证书不生效——这些问题你肯定遇到过。今天把高频问题汇总一下,都是实战中验证过的解法。二、操作步骤
步骤1:检查证书状态和有效期
先确认证书当前状态,别一顿操作猛如虎结果证书还有半年才到期。 ```bash # CentOS/RHEL 和 Ubuntu 通用 openssl x509 -in /etc/letsencrypt/live/example.com/fullchain.pem -noout -dates ``` **预期输出:** ``` notBefore=Jan 15 00:00:00 2024 GMT notAfter=Apr 15 00:00:00 2024 GMT ``` 如果输出"unable to load certificate",说明路径错了或者证书文件损坏,用certbot certificates查看实际路径。步骤2:排查证书续期失败
续期是最容易出问题的环节,先看日志定位原因。 ```bash # CentOS/RHEL journalctl -u certbot -n 50 --no-pager # Ubuntu sudo tail -100 /var/log/letsencrypt/letsencrypt.log ``` **CentOS/RHEL预期输出:** ``` Jan 15 10:23:45 web01 certbot[12345]: Successfully received certificate. Jan 15 10:23:46 web01 certbot[12345]: Certificate is saved at: /etc/letsencrypt/live/example.com/fullchain.pem ``` **Ubuntu预期输出:** ``` 2024-01-15 10:23:45,123:DEBUG:certbot.auth_handler:Authorization for domain example.com successful 2024-01-15 10:23:45,456:INFO:certbot.hooks:Deploying certificate to VirtualHost /etc/nginx/sites-enabled/example.com ``` 看到"failed"或"error"关键字就往上翻,找到具体报错原因。步骤3:修复HTTP验证失败
HTTP验证是最常用的方式,失败一般是目录权限或.htaccess干扰。 ```bash # CentOS/RHEL - Apache sudo chmod -R 755 /var/www/html/.well-known/acme-challenge/ # CentOS/RHEL - Nginx sudo chmod -R 755 /usr/share/nginx/html/.well-known/acme-challenge/ # Ubuntu - Nginx sudo chmod -R 755 /var/www/html/.well-known/acme-challenge/ ``` 手动验证访问: ```bash curl -I http://example.com/.well-known/acme-challenge/test_file ``` **预期输出:** ``` HTTP/1.1 200 OK Content-Type: text/plain ``` 返回403或404说明配置有问题,检查nginx/apache的location块。步骤4:处理泛域名证书申请DNS验证
泛域名必须用DNS验证,txt记录传播需要时间。 ```bash # 手动添加DNS记录(以Cloudflare为例) # 先安装api插件 pip3 install certbot-dns-cloudflare # 创建配置文件 sudo mkdir -p /etc/letsencrypt/cloudflare.ini sudo chmod 600 /etc/letsencrypt/cloudflare.ini # 写入内容:dns_cloudflare_api_token = YOUR_CF_TOKEN # 申请泛域名证书 sudo certbot certonly --dns-cloudflare --dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini -d "example.com" -d "*.example.com" ``` **预期输出:** ``` Congratulations! Your certificate and chain have been saved at: /etc/letsencrypt/live/example.com/fullchain.pem ``` 验证TXT记录是否生效: ```bash dig _acme-challenge.example.com TXT +short ``` **预期输出:** ``` "glTF123456789abcdefghijklmnopqr" ``` DNS记录生效后再运行certbot,否则必败。步骤5:修复证书链不完整问题
有些客户端加载证书后报"certificate chain incomplete",需要确认fullchain.pem包含完整链。 ```bash # 验证证书链 openssl s_client -connect example.com:443 -servername example.com -showcerts 2>/dev/null | openssl x509 -noout -text | grep -A 5 "Subject Alternative Name" ``` **预期输出:** ``` X509v3 Subject Alternative Name: DNS:example.com, DNS:*.example.com ``` 如果SAN信息缺失,说明证书文件可能不是完整链。用certbot重新生成: ```bash # CentOS/RHEL 和 Ubuntu 通用 sudo certbot certonly --nginx -d example.com --force-renewal ```步骤6:配置自动续期脚本
Let's Encrypt证书90天过期,手动续期迟早出事,写个靠谱的脚本。 ```bash # 创建续期检查脚本 sudo cat > /usr/local/bin/le-renew.sh << 'EOF' #!/bin/bash LE_PATH="/usr/bin/certbot" LOGFILE="/var/log/le-renew.log" if [ ! -f $LE_PATH ]; then echo "[$(date)] certbot not found" >> $LOGFILE exit 1 fi # CentOS/RHEL 使用 systemctl # Ubuntu 使用 systemctl $LE_PATH renew --quiet --deploy-hook "systemctl reload nginx" if [ $? -eq 0 ]; then echo "[$(date)] Certificate renewed successfully" >> $LOGFILE else echo "[$(date)] Certificate renewal failed" >> $LOGFILE fi EOF sudo chmod +x /usr/local/bin/le-renew.sh # 添加定时任务 sudo crontab -e # 添加:0 3 * * * /usr/local/bin/le-renew.sh >> /var/log/le-renew.log 2>&1 ``` **预期输出:** ``` # crontab -e 编辑后的确认 crontab: installing new crontab ``` 测试一下续期命令: ```bash sudo certbot renew --dry-run ``` **预期输出:** ``` ** DRY RUN: simulating 'certbot renew' close to real time. ** Congratulations, all simulated renewals succeeded: ```三、常见问题FAQ
**Q:certbot renew一直报错"Client with the currently selected authenticator plugin is not working",怎么处理?** 这种报错一般是插件损坏或者路径问题。先确认certbot安装来源: ```bash which certbot certbot --version ``` 如果是pip安装的试试: ```bash sudo pip3 install --upgrade certbot certbot-dns-cloudflare ``` 如果是snap安装的: ```bash sudo snap refresh certbot sudo snap connect certbot:nginx-observe ``` **Q:申请泛域名证书时TXT记录验证一直超时,怎么解决?** DNS传播需要时间,但更多时候是记录格式问题。TXT记录值必须加引号,且不要太长。Cloudflare操作时要确认API Token权限包含Zone.DNS.write。 另一个野路子:分两次申请,先申请主域名证书,再单独申请泛域名证书,减少单次验证复杂度。 ```bash # 先申请主域名 sudo certbot certonly --nginx -d example.com # 再单独申请泛域名 sudo certbot certonly --nginx -d "*.example.com" --dry-run ``` **Q:nginx配置了正确的证书路径但浏览器还是报证书错误,怎么排查?** 证书文件没问题的情况下,一般是nginx没有reload。另一个坑是同时监听443和80,nginx只加载了default配置: ```bash # 确认加载的是哪个配置文件 nginx -T | grep "ssl_certificate" # 检查所有配置 sudo nginx -T | grep -E "(listen 443|ssl_certificate)" ``` 最常见的问题是/etc/nginx/sites-enabled/下有default配置覆盖了你的设置。 **Q:续期脚本执行了但证书没更新,怎么判断是否成功?** 看日志,别靠猜。检查/var/log/le-renew.log的时间戳: ```bash tail -20 /var/log/le-renew.log cat /etc/letsencrypt/renewal/example.com.conf | grep -E "(renewalparams|webroot)" ``` 如果配置里有renewalparams且最近一次success_after就是成功。另一个确认方式: ```bash stat /etc/letsencrypt/live/example.com/fullchain.pem | grep Modify ``` 这个时间戳应该在你运行renew之后。四、总结
Let's Encrypt的问题核心就三个:验证路径、权限配置、定时任务。 核心要点: - HTTP验证确保.well-known目录可读,权限755起步 - DNS验证必须等TXT记录完全传播,dig验证后再申请 - 续期用crontab定时,别指望手动操作 - 证书路径用fullchain.pem,别用cert.pem 延伸阅读: - certbot官方文档:https://certbot.eff.org/docs/ - Let's Encrypt官方论坛:排查问题前先搜一下,很多坑别人踩过了 - nginx + ssl配置最佳实践:Mozilla SSL Configuration Generator生成的配置可以直接用相关推荐
上一篇: Loki - 日志聚合 配置与优化
已经是最后一篇啦!