起因
一个测试用的域名,底下要挂一堆子域名:每个项目一个,随开随关。原来的做法是每建一个站就签一张单域名证书,很快就不可持续了——签发要人工点、续期要人工管,忘一个就是线上 HTTPS 失效。
通配证书 *.example.cn 能一次解决:签一张,所有子域名复用同一份证书文件,新建站点只要在 nginx 里指过去就行。
绕不开的前提:必须 DNS-01
Let’s Encrypt 的域名验证有三种方式,能签通配的只有一种:
| 验证方式 | 怎么证明 | 能签通配吗 |
|---|---|---|
| HTTP-01 | 在 http://域名/.well-known/acme-challenge/<token> 放一个文件 | 不能 |
| TLS-ALPN-01 | 在 443 端口用特殊 ALPN 协议响应 | 不能 |
| DNS-01 | 在 _acme-challenge.域名 加一条 TXT 记录 | 能 |
原因不难理解。HTTP-01 是「我能控制这个域名指向的那台服务器」——但 *.example.cn 代表无穷多个子域名,你没法对每一个都放文件,CA 也没法挑一个来验。DNS-01 验的是「我能改这个域名的 DNS 记录」,这才是对整个域名(含所有子域名)控制权的证明。
所以:想要通配证书,就必须能改 DNS。没有别的路。
两种改 DNS 的方式
acme.sh 支持这两种,区别只在续期:
手动模式——它打印出要加的 TXT 记录,你去 DNS 控制台加,回来继续:
acme.sh --issue --dns -d example.cn -d '*.example.cn' \
--yes-I-know-dns-manual-mode-enough-go-ahead-please
那个又臭又长的参数名是故意的,它在提醒你:手动模式不能自动续期。60~90 天后到期,整套流程要人工重来一遍。
API 模式——把 DNS 服务商的 API 凭据给 acme.sh,它自己加记录、自己删:
export DP_Id="..." DP_Key="..." # DNSPod 的示例,各家变量名不同
acme.sh --issue --dns dns_dp -d example.cn -d '*.example.cn'
凭据会存进 ~/.acme.sh/account.conf,之后全自动续期。
如果这是个要长期活着的站,直接上 API 模式。 手动模式适合「先验证流程能跑通」,但别指望三个月后的自己记得这回事。
两个实操细节
同名 TXT 记录是两条,不是一条。 签 example.cn + *.example.cn 时,CA 会下发两个不同的 challenge,但主机记录名字都是 _acme-challenge。DNS 允许同名多条 TXT,你必须两条都加、并存。很多人加了第二条时把第一条覆盖掉了,然后验证失败。
提交前自己先查一遍。 Let’s Encrypt 对验证失败有频率限制,撞上了要等。加完记录别急着点继续,先确认权威 NS 上真的有了:
dig +short TXT _acme-challenge.example.cn @<权威NS>
dig +short TXT _acme-challenge.example.cn @8.8.8.8
两条值都出现,再去提交。多花二十秒,省掉被限流的风险。
acme.sh 默认 CA 不是 Let’s Encrypt
acme.sh 3.x 起默认 CA 是 ZeroSSL,不是 Let’s Encrypt。ZeroSSL 也能用,但它要 EAB 凭据、多一次账户注册,多一个续期时可能出问题的环节。如果你其它证书都是 LE,保持一致更省心:
acme.sh --set-default-ca --server letsencrypt
要换就在签之前换。 换 CA 会重新生成 challenge,签完再换等于前面加的 TXT 记录白加了。
装到位,顺便把续期钩子挂上
别手动拷贝 pem 文件。用 --install-cert,它会记住部署位置,续期后自动更新并执行 reload:
acme.sh --install-cert -d example.cn --ecc \
--key-file /path/to/cert/privkey.pem \
--fullchain-file /path/to/cert/fullchain.pem \
--reloadcmd "nginx -s reload"
签完之后
确认一下拿到的确实是通配:
openssl x509 -in fullchain.pem -noout -subject -dates -ext subjectAltName
要看到 DNS:*.example.cn, DNS:example.cn 两个都在。
之后新增子域名就只剩一件事——写个 nginx server 块指向这份证书,reload。不用签发、不用等审核、不用点任何界面。
备份的时候记得校验配对
证书是签给域名的,跟服务器无关。换机器直接把 fullchain.pem + privkey.pem 拷过去就能继续用,不用重签。
但备份最怕的是存了一份对不上的证书和私钥,等到换机器那天才发现。校验很简单——两条命令的输出必须一致:
openssl x509 -in fullchain.pem -noout -pubkey | openssl md5
openssl pkey -in privkey.pem -pubout | openssl md5
顺便把 ~/.acme.sh/ 里的账户密钥也一起备份,这样在新机器上能接着自动续期,不用重新注册 ACME 账户。