Let’s Encrypt 泛域名证书:服务器多站点 SSL 自动续期部署

Let's Encrypt 泛域名证书自动续期部署封面图

为什么你需要一张泛域名证书

当一台服务器同时跑着主站、博客、接口服务和后台管理等多个子域名时,手动给每个域名单独签一张 SSL 证书,既繁琐又容易出错。证书到期一旦忘记续期,浏览器就会弹出”连接不安全”警告,用户信任和搜索排名都受影响。泛域名证书(即通配符证书)能一次性覆盖主域下的全部子域名,配合定时任务自动续期,基本可以做到”证书到期从日常运维里消失”。下面我会一步步教你用 Let’s Encrypt 免费签出泛域名证书并自动续期。如果你刚接触服务器运维,可先过一遍服务器配置与优化分类建立基础。

泛域名证书为何必须走 DNS 校验

签发泛域名证书的关键是域名所有权校验。Let’s Encrypt 提供 HTTP 和 DNS 两种校验,但泛域名只能用 DNS 校验:HTTP 校验要求服务器上存在与证书范围对应的真实站点,而 *.example.com 不指向具体主机,无法放置校验文件。

DNS 校验的思路是:Let’s Encrypt 生成一段随机 TXT 记录值,你要把它加到域名解析里,解析生效即证明域名控制权。因此你需要能操作域名解析面板。绝大多数第三方权威 DNS 服务商提供 API,certbot 这类客户端可通过 API 自动写入和删除 TXT 记录,从而做到无人工介入的自动签发与续期。

需要澄清的是,DNS 校验并不是泛域的专属限制,而是在泛域名场景下的必然选择。因为通配符证书本身声明的是”这一整组子域名”,并没有一个可以被 HTTP 请求命中的实体页面来承接校验文件,只有解析记录能代表整组域名的归属。了解这一点,你在配置时就不会因为”为什么不能用命令行直接免插件签发”而困惑。此外,DNS 校验还有个额外的安全性收益:校验过程完全在解析层完成,不依赖 Web 服务是否正常运行,即使某段时间站点挂了,只要解析服务正常,续期仍然可以进行。

相比 HTTP 校验,DNS 校验多一步解析传播等待,通常几十秒到几分钟,但对自动化部署影响不大,反而因为不依赖站点路径,更适合批量签发。

第一步:安装 Certbot

签发和续期证书的官方客户端是 Certbot。以 Ubuntu、Debian 为例:

sudo apt update
sudo apt install certbot python3-certbot-nginx python3-certbot-dns-cloudflare
  • python3-certbot-nginx:自动把证书装进 Nginx 配置(用 Apache 则装 python3-certbot-apache)。
  • python3-certbot-dns-cloudflare:DNS 服务商插件,让 Certbot 通过 API 自动增删 TXT 记录,是自动续期的关键。

若你用别的 DNS 服务商,也有对应插件,如 python3-certbot-dns-dnsimplepython3-certbot-dns-route53。装完执行 certbot --version 确认可用。

第二步:配置 DNS 凭据

先在 DNS 服务商后台生成 API 令牌(Cloudflare 至少需 Zone 级 DNS 编辑权限),写入仅 root 可读的凭据文件:

sudo mkdir -p /etc/letsencrypt
sudo tee /etc/letsencrypt/cloudflare.ini > /dev/null <<'EOF'
dns_cloudflare_api_token = your_token_here
EOF
sudo chmod 600 /etc/letsencrypt/cloudflare.ini
sudo chown root:root /etc/letsencrypt/cloudflare.ini

chmod 600chown root:root 必须执行:API 令牌泄露等于交出该域名 DNS 控制权,风险远高于证书本身。非 Cloudflare 时字段名不同(如 dns_digitalocean_token),但文件位置与权限逻辑一致。

泛域名证书覆盖子域名的示意图

第三步:签发泛域名证书

example.com 换成真实主域名后执行:

sudo certbot certonly \
  --dns-cloudflare \
  --dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \
  -d "*.example.com" \
  -d "example.com" \
  --email you@example.com \
  --agree-tos \
  --no-eff-email

同时写 *.example.comexample.com 是因为通配符不覆盖裸域,一起签可保证访问主域也有证书。--certonly 只申请证书、不改 Web 配置。签发时插件会自动添加并稍后删除 _acme-challenge 的 TXT 记录,无需进 DNS 面板。证书存于 /etc/letsencrypt/live/example.com/,其中 fullchain.pem 是证书链、privkey.pem 是私钥。

第四步:把证书接入 Nginx 多站点

各子域名共用一张证书,只要在各自 server 配置里引用同一证书路径:

server {
    listen 443 ssl http2;
    server_name www.example.com;
    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    root /var/www/www.example.com;
    index index.html;
}

第二个站点 blog.example.com 只需改 server_name,证书路径不变,这正是泛域名证书省事之处。改完先测语法再重载:

sudo nginx -t
sudo systemctl reload nginx

nginx -t 输出 syntax is oktest is successful 即可重载,不中断访问。用 Apache 则把所有 HTTPS 站点的 SSLCertificateFile 指向 fullchain.pemSSLCertificateKeyFile 指向 privkey.pem,原理一致。

cron 定时自动续期与重载服务的示意图

第五步:用 Cron 自动续期

Let’s Encrypt 证书有效期仅 90 天,必须让自动续期接管。先手动验证续期流程:

sudo certbot renew --dry-run

--dry-run 是模拟、不真正签发。成功后再写进 crontab:

sudo crontab -e

加入一行:

15 2 * * * /usr/bin/certbot renew --quiet --deploy-hook "systemctl reload nginx"

含义是每天 2:15 检查续期,--quiet 正常静默、出错才输出,--deploy-hook 在续期成功后自动重载 Nginx 让新证书生效。要澄清一个误区:cron 每次运行 certbot renew,不代表证书都被重签。Certbot 只在证书 30 天内到期时才真正续期,其余时间自动跳过,所以每天跑一次既不会产生无谓签发压力,也不会触发速率限制。

常见续期问题与排查

自动续期上线后,偶尔会遇到续期失败的情况,提前熟悉几个高频问题能帮你快速定位。除了上面列出的 DNS 超时、凭据权限和未重载三类问题,还有几点值得留意。

第一,证书的续期窗口判断。Certbot 默认只在证书到期前 30 天内才真正执行续期,所以如果你的站点刚签完证书,运行 certbot renew 看到”no renewals were attempted”是正常现象,不代表自动续期没配置好。第二,多域名同一张证书时,只要其中任意一个域名解析异常,整张证书的续期都会失败,因为签发命令是整体处理的,排障时要逐个检查涉及的所有域名解析。第三,--deploy-hook 只会在证书真正被续期后触发,如果你希望验证重载环节是否正常,可以手动跑一次带 --force-renewal 的测试命令来观察钩子是否执行。

续期失败、日志报 DNS 校验超时。 多为 TXT 记录传播过慢。可在命令里加 --dns-cloudflare-propagation-seconds 60 拉长等待时间后重跑 sudo certbot renew --dry-run

凭据文件权限不对。 Certbot 强制凭据只允许 root 读;若之前用了 chmod 644 或放到普通用户目录会直接报错,执行 sudo chmod 600 /etc/letsencrypt/cloudflare.ini 收回即可。

证书续期成功但站点仍显示旧证书。 说明续期后未重载 Web 服务,补上 --deploy-hook 并手敲一次 sudo systemctl reload nginx

若以上都没解决,先确认服务器系统时间是否准确——证书校验强依赖时间同步,偏差过大会导致签发和续期失败。

总结与后续建议

泛域名证书配合自动续期,是服务器跑多个子站点时的省心方案。核心链路四步:用 DNS 插件让 Certbot 能操作 TXT 记录 → 签发覆盖通配符和裸域的证书 → 统一接入 Nginx 或 Apache → 用 cron 每天跑 certbot renew 并配合 --deploy-hook 重载。首次搭建约一两个小时,之后基本不用再管证书。

我建议先在测试服务器完整走一遍签发、续期、重载三个环节,确认无误再上生产,避免把证书问题带到线上。如果你还想了解加载速度对访问体验的影响,可参考我们关于网站性能优化的文章。总结来说,若要一台配置空间足够的机器承载多站点,可了解 Hostease 的独立服务器方案;预算有限又想灵活拓展的场景,可以考虑VPS主机虚拟专用服务器,即在一台物理机上划分出的独立运行环境)。

发表评论