用 DNS-01 在 Nginx 上签一张通配符证书,并让它自动续期
很多人第一次想给 *.example.com 签通配符证书时,才发现 HTTP-01 不支持通配符。本文走一遍 DNS-01 的完整流程:前置条件、签发、Nginx 配置、自动续期验证,以及几个容易踩的坑。

见过不少人是这样发现问题的:HTTP-01 用得好好的,某一天想给 *.example.com 签张通配符证书,签发直接被拒。原因不复杂——Let's Encrypt 的 HTTP-01 质询只能验证单个主机名,签通配符必须走 DNS-01。这不是 bug,是 ACME 协议设计里就写死的限制。
这篇就把 DNS-01 从签发、配 Nginx 到自动续期走一遍。
前置条件
动手之前先确认三件事:
- 域名 DNS 托管在哪里,以及能否通过 API 增删 TXT 记录。这是 DNS-01 的核心:每次签发和续期都要临时写一条
_acme-challenge记录,手动改记录意味着续期也得手动,基本等于放弃自动化。 - 如果 DNS 服务商没有 API,或者不想把主域的 API 凭据放到服务器上,可以用 CNAME 委托:把
_acme-challenge.example.comCNAME 到另一个专门做验证的域,只需把那个域的 API 凭据交给签发程序。 - Nginx 已装好,
nginx -t能过,且你有 root 或 sudo 权限。
签发
CertbotX 一类的 ACME 客户端可以走 DNS-01 自动签发:创建质询 TXT 记录、等 DNS 传播、完成验证、清理记录,全程不需要人工碰 DNS 控制台。如果主域凭据不方便给出去,就配置 CNAME 委托,验证记录写到委托域里。
命令层面的请求大致是申请 *.example.com 和 example.com 两个 SAN——通配符只覆盖一级子域,裸域要单独列上,漏了的话访问裸域照样告警。
签发成功后,证书和私钥落在本机,ACME 客户端会记录到期时间,到期前自动重新签发。这一步不需要 cron 自己拼,客户端自带调度。
Nginx 配置
拿到证书后,server 块里最少要有这几行:
server {
listen 443 ssl;
server_name app.example.com;
ssl_certificate /path/to/fullchain.pem;
ssl_certificate_key /path/to/privkey.pem;
}注意 ssl_certificate 要用 fullchain(服务器证书 + 中间证书),只放叶子证书会导致部分客户端(尤其是老的 Android 和某些 Java 栈)报链不完整。这是运维现场最常见的“证书明明没过期却告警”的原因之一。
HTTP 跳转按需加:
server {
listen 80;
server_name app.example.com;
return 301 https://$host$request_uri;
}改完 nginx -t,再 reload。别把 nginx -s reload 当验证手段本身,它只是应用配置;语法检查永远先做。
续期后的部署这一步别漏
证书续期成功 ≠ 服务器在用新证书。Nginx 只在启动或 reload 时读证书文件,续期后必须触发 reload,否则会一直用到旧证书过期。签发工具一般支持 deploy hook,把 reload 挂进去。
在 CertbotX 里,这一步可以交给部署流程处理:签发或续期完成后,证书自动推送到 Agent 管理的 Nginx 实例,或者同步到 EdgeOne、CDN 侧的证书配置,同时触发重载。每次部署都有记录可查,谁在什么时间把哪张证书推到了哪个目标,审计时能翻出来,而不是靠记忆和聊天记录拼线索。
验证
配完别只看浏览器绿锁,用命令确认:
openssl s_client -connect app.example.com:443 -servername app.example.com </dev/null 2>/dev/null | openssl x509 -noout -dates -issuer -ext subjectAltName看三点:notAfter 是不是新证书的时间、issuer 是不是预期的 CA、SAN 里有没有你的域名。再从外部网络访问一次 443,排除内网 hosts 的干扰。
续期不想等到 59 天后才发现挂了,可以手动触发一次 dry-run 续期测试;通配符场景下尤其要测,因为 DNS API 凭据过期是静默失败的常客。
几个小坑集中说一下:
- CNAME 委托的目标域本身也要能被 ACME 服务器解析到,改完先用
dig TXT _acme-challenge.example.com看 CNAME 链对不对。 - 通配符不覆盖多级子域,
*.example.com管不了a.b.example.com。 - DNS 传播慢的服务商,客户端的等待时间可能要调大,不然验证会偶发超时。
参考材料:



