Skip to content

Certbot + Let's Encrypt + 腾讯云 DNS 验证自动续期证书

本文介绍如何在 Ubuntu 环境下使用 Certbot 配合 certbot-dns-tencentcloud 插件,通过腾讯云 DNS 验证申请 Let's Encrypt 泛域名(Wildcard)证书,并实现自动续期。

注意:旧版 DNSPod API (https://dnsapi.cn) 使用 login_token 的方式已不再可靠(会返回 401 错误)。本文使用的 certbot-dns-tencentcloud 插件基于腾讯云新版 DNSPod API,无需手写签名脚本。

1. 安装

bash
sudo apt-get update
sudo apt-get install certbot python3-pip

安装腾讯云 DNS 插件:

bash
sudo pip3 install certbot-dns-tencentcloud

验证插件是否安装成功:

bash
sudo certbot plugins

输出中应包含 dns-tencentcloud

2. 配置腾讯云 API 凭证

2.1 获取 SecretId 和 SecretKey

  1. 登录 腾讯云控制台
  2. 前往 访问管理 -> API 密钥管理直达链接)。
  3. 创建或查看你的 SecretIdSecretKey

安全建议:不要使用主账号密钥。应创建一个子用户,仅授予 QcloudDNSPodFullAccess(DNSPod 全读写)权限,并限制来源 IP 为服务器地址。

2.2 创建凭证文件

凭证文件推荐存放路径:~/.secrets/certbot/tencentcloud.ini

bash
sudo mkdir -p ~/.secrets/certbot
sudo tee ~/.secrets/certbot/tencentcloud.ini > /dev/null << 'EOF'
dns_tencentcloud_secret_id  = YOUR_SECRET_ID
dns_tencentcloud_secret_key = YOUR_SECRET_KEY
EOF

设置严格权限(Certbot 会检查权限,如果其他用户可读会发出警告):

bash
sudo chmod 600 ~/.secrets/certbot/tencentcloud.ini

也可以通过环境变量提供凭证(适用于 CI/CD 等场景):

bash
export TENCENTCLOUD_SECRET_ID=<your_secret_id>
export TENCENTCLOUD_SECRET_KEY=<your_secret_key>

3. 申请证书

bash
sudo certbot certonly \
    -a dns-tencentcloud \
    --dns-tencentcloud-credentials ~/.secrets/certbot/tencentcloud.ini \
    -d example.com -d "*.example.com" \
    --email your_email@example.com \
    --agree-tos

参数说明:

参数说明
certonly仅获取证书,不自动修改 Web 服务器配置
-a dns-tencentcloud使用腾讯云 DNS 插件进行验证(等同于 --authenticator
--dns-tencentcloud-credentials凭证文件路径
--dns-tencentcloud-propagation-secondsDNS 记录生效等待时间(默认 10 秒,可选参数)
-d指定域名,可多次使用
--email接收证书到期通知的邮箱
--agree-tos同意 Let's Encrypt 服务条款

提示:Certbot 现在默认使用 ACME v2 服务器,无需显式指定 --server 参数。

同时申请 *.example.comexample.com,由于 DNSPod 的 TXT 记录 TTL 最低为 60 秒,Let's Encrypt 可能会读到缓存的旧记录导致验证失败。建议添加 --dns-tencentcloud-propagation-seconds 70 来延长等待时间。

申请成功后,证书保存在 /etc/letsencrypt/live/example.com/

bash
ls /etc/letsencrypt/live/example.com/
# cert.pem  chain.pem  fullchain.pem  privkey.pem
文件用途
fullchain.pem完整证书链,Nginx 的 ssl_certificate 使用此文件
privkey.pem私钥,Nginx 的 ssl_certificate_key 使用此文件

4. 配置部署钩子

证书更新后需要重载 Web 服务器。将脚本放入 Certbot 的标准部署钩子目录,无需在命令中指定 --deploy-hook,Certbot 会在任何域名证书成功续期后自动执行:

bash
sudo mkdir -p /etc/letsencrypt/renewal-hooks/deploy
sudo tee /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh > /dev/null << 'EOF'
#!/bin/bash
# 证书更新后自动重载 Nginx
if systemctl is-active --quiet nginx; then
    systemctl reload nginx
    echo "Nginx reloaded successfully."
fi
EOF
sudo chmod 700 /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh

5. 自动续期

Let's Encrypt 证书有效期为 90 天。Certbot 安装后会自动配置 Systemd Timer 或 Cron 定时任务(默认每天检查两次),在证书到期前 30 天自动续期。

5.1 测试自动续期

bash
sudo certbot renew --dry-run

如果输出无报错,说明自动续期配置正常。

5.2 确认定时任务

bash
# Systemd Timer
systemctl list-timers | grep certbot

# 或 Cron
cat /etc/cron.d/certbot

5.3 查看续期配置

首次申请成功后,Certbot 会自动生成配置文件,后续续期自动读取,无需人工干预:

bash
cat /etc/letsencrypt/renewal/example.com.conf

6. 常见问题

6.1 同时申请主域名和泛域名时验证失败

同时申请 example.com*.example.com 时,两者共用同一条 _acme-challenge TXT 记录。由于 DNSPod 的 TTL 最低 60 秒,Let's Encrypt 可能缓存旧记录导致第二次验证失败。

解决方案:设置等待时间大于 60 秒:

bash
--dns-tencentcloud-propagation-seconds 70

6.2 开启调试模式

遇到问题时可以开启插件调试输出:

bash
--dns-tencentcloud-debug true

6.3 API 权限策略

插件使用新版 DNSPod API,子用户需要授予 QcloudDNSPodFullAccess 策略(因为需要添加/删除记录,必须写权限)。

附录:为什么不用手写脚本调用 DNSPod API?

腾讯云 DNS API 已升级为 云 API v3,认证方式从简单的 login_token 变为 TC3-HMAC-SHA256 签名。用 bash 实现完整签名流程大约需要 200+ 行代码(参考 acme.sh 的 dns_tencent 插件)。

certbot-dns-tencentcloud 插件封装了完整的 API v3 调用逻辑,是目前最简洁可靠的方案。


参考来源: