certbot-dns
通过 DNS 验证方式申请和续签 SSL 证书
补充说明
Certbot 是 EFF 开发的 Let's Encrypt SSL 证书管理工具。DNS 验证通过在域名 DNS 中添加 TXT 记录证明所有权,无需开放 80/443 端口,支持通配符证书,适用于服务器无公网端口或 HTTP 验证不便的场景。
安装
# Debian/Ubuntu
sudo apt update && sudo apt install -y certbot
# CentOS/RHEL
sudo yum install -y epel-release && sudo yum install -y certbot
# Fedora
sudo dnf install -y certbot
# Alpine
sudo apk add certbot
# 验证
certbot --version
certbot plugins
目录结构
/etc/letsencrypt/
├── live/ # 当前证书符号链接
├── archive/ # 历史证书存档
├── renewal/ # 续订配置
└── keys/ # 私钥文件
手动 DNS 验证
适用于无法安装自动化 DNS 插件的场景,需在域名控制面板手动添加 TXT 记录。
申请证书
sudo certbot certonly --manual --preferred-challenges dns \
-d "example.com" \
-d "*.example.com" \
--register-unsafely-without-email \
--agree-tos
操作流程
- 执行命令后 Certbot 提示添加 TXT 记录:
Please deploy a DNS TXT record under the name:
_acme-challenge.example.com
with the following value:
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- 登录域名 DNS 管理面板添加记录:
| 字段 | 值 |
|---|---|
| 记录类型 | TXT |
| 名称 | _acme-challenge |
| 值 | Certbot 给出的随机字符串 |
| TTL | 300 |
- 验证记录生效:
dig -t TXT _acme-challenge.example.com
- 返回终端按 Enter 完成验证
自动 DNS 验证
通过 DNS 服务商 API 自动添加和删除 TXT 记录,实现全流程无人值守。Cloudflare API 自动化流程详见 certbot-api。
Cloudflare
sudo apt install -y python3-certbot-dns-cloudflare
mkdir -p ~/.secrets
cat > ~/.secrets/cloudflare.ini <<EOF
dns_cloudflare_api_token = YOUR_API_TOKEN
EOF
chmod 600 ~/.secrets/cloudflare.ini
sudo certbot certonly --dns-cloudflare \
--dns-cloudflare-credentials ~/.secrets/cloudflare.ini \
-d example.com -d "*.example.com"
详细 Cloudflare API 自动化流程见 certbot-api。
其他 DNS 服务商
| 服务商 | 插件包 | 凭据配置项 |
|---|---|---|
| DNSPod | python3-certbot-dns-dnspod |
dns_dnspod_email / dns_dnspod_api_key |
| 阿里云 | python3-certbot-dns-aliyun |
dns_aliyun_access_key / dns_aliyun_access_secret |
| 华为云 | python3-certbot-dns-huaweicloud |
dns_huaweicloud_username / dns_huaweicloud_password |
| AWS Route53 | python3-certbot-dns-route53 |
AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY(环境变量) |
| Google Cloud | python3-certbot-dns-google-domains |
dns_google_domains_access_token |
部署证书
# 创建续签钩子
sudo mkdir -p /etc/letsencrypt/renewal-hooks/deploy
sudo tee /etc/letsencrypt/renewal-hooks/deploy/reload.sh > /dev/null <<'EOF'
#!/bin/bash
systemctl reload nginx 2>/dev/null || systemctl reload apache2 2>/dev/null
EOF
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload.sh
server {
listen 443 ssl;
server_name example.com *.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
}
自动续签
# 每天凌晨 3 点检查续签(仅到期前 30 天内才实际续签)
echo "0 3 * * * certbot renew --quiet" | crontab -
管理命令
sudo certbot certificates # 查看所有证书
sudo certbot renew --dry-run # 测试续签
sudo certbot renew --force-renewal # 强制续签
sudo certbot delete --cert-name example.com # 删除证书
sudo tail -f /var/log/letsencrypt/letsencrypt.log # 查看日志
故障排除
# 检查 DNS 记录是否生效
dig -t TXT _acme-challenge.example.com
# 检查证书有效期
openssl x509 -in /etc/letsencrypt/live/example.com/cert.pem -noout -dates
# 验证证书链
openssl verify -CAfile /etc/letsencrypt/live/example.com/chain.pem \
/etc/letsencrypt/live/example.com/cert.pem
# 查看错误日志
grep -iE "error|failed" /var/log/letsencrypt/letsencrypt.log
# 修复目录权限
sudo chown -R root:root /etc/letsencrypt
健康检查脚本
#!/bin/bash
DOMAIN="example.com"
ADMIN_EMAIL="admin@example.com"
expiry_date=$(openssl x509 -enddate -noout \
-in /etc/letsencrypt/live/$DOMAIN/cert.pem | cut -d= -f2)
days_left=$(( ($(date -d "$expiry_date" +%s) - $(date +%s)) / 86400 ))
chain_ok=$(openssl verify -CAfile \
/etc/letsencrypt/live/$DOMAIN/chain.pem \
/etc/letsencrypt/live/$DOMAIN/cert.pem 2>&1)
if [ "$days_left" -le 30 ]; then
echo "证书将在 $days_left 天后过期" | mail -s "SSL 警告: $DOMAIN" "$ADMIN_EMAIL"
fi
if [[ "$chain_ok" != *"OK"* ]]; then
echo "证书链错误: $chain_ok" | mail -s "SSL 错误: $DOMAIN" "$ADMIN_EMAIL"
fi
echo "域名: $DOMAIN 有效期: ${days_left}天 证书链: $chain_ok"
参数说明
相关命令
- certbot-api — 使用 Cloudflare API 自动验证
- certbot-dns 👈 当前所在位置
参数说明
| 参数 | 说明 |
|---|---|
certonly |
仅获取证书,不自动安装 |
--manual |
手动交互模式 |
--preferred-challenges dns |
使用 DNS-01 挑战 |
-d |
域名,可重复使用 |
--dns-cloudflare |
使用 Cloudflare DNS 插件 |
--dns-cloudflare-credentials |
指定 Cloudflare 凭据文件路径 |
--force-renewal |
强制重新申请 |
--dry-run |
测试运行,不实际申请 |
--agree-tos |
同意 Let's Encrypt 服务条款 |