综合新闻
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生成的配置可以直接用
`
content = content.indexOf('') > 0 ? content.replace('', viewstyle + '') : viewstyle + content
const iframe = document.querySelector('#viewcontent')
const viewdoc = iframe.contentDocument
viewdoc.open()
viewdoc.write(content)
viewdoc.close()
iframe.height = viewdoc.body.scrollHeight + 20
})