泛域名证书配置教程:通配符 SSL 的申请与 Nginx 部署实录
为什么很多站点最后都换成了泛域名证书
一个主域下面挂十几个二级子域,每个都单独申请证书、单独配一遍 Nginx,光是续期提醒就能把人逼疯。泛域名证书(Wildcard Certificate)解决的就是这个场景:一张证书覆盖 *.example.com,所有同级子域共用同一份文件。

它和普通单域证书的签发流程差别不大,真正的分水岭在验证环节。普通证书走 HTTP-01,往网站根目录丢个文件就完事;泛域名证书必须走 DNS-01,得在域名解析里加一条 TXT 记录。这一步挡掉了不少嫌麻烦的人,但配置一次之后,后续子域上线基本零成本。
下面这套流程我在两台服务器上跑过,环境是 Ubuntu 22.04 + Nginx 1.24,证书来源选 Let's Encrypt,工具用 certbot。其他 ACME 客户端思路相通,命令细节会有出入。
申请前的两个硬性前提
域名解析权限必须拿到手
DNS-01 验证要求你能修改目标域名的 DNS 记录,哪怕只是临时加一条 TXT。如果域名托管在别人手里、你又只有网站后台权限,这条路走不通。国内部分云厂商的 DNS 解析支持 API 调用,certbot 有对应插件可以自动加记录,省去手动复制粘贴。
这里有个容易忽略的点:泛域名证书只覆盖一级子域。*.example.com 能匹配 blog.example.com、api.example.com,但匹配不到 a.b.example.com。多层子域需要单独再签一张 *.b.example.com,或者把多级通配符写进同一张证书的 SAN 列表。
服务器 80/443 端口状态确认
证书签发本身走 DNS 验证,不依赖 80 端口,但后续 Nginx 要监听 443 做 TLS 握手。云服务器安全组和系统防火墙两层都要放行,我见过安全组开了、ufw 没开导致握手超时的案例,排查了半小时。
用 certbot 签发泛域名证书的完整命令
先装工具。Ubuntu 系直接 apt 装,版本够用:
sudo apt update && sudo apt install certbot- 如果要用 DNS 插件自动验证,再装对应插件,比如阿里云 DNS 用
certbot-dns-aliyun
手动 DNS 验证的签发命令长这样:
sudo certbot certonly --manual --preferred-challenges dns -d "*.example.com" -d example.com
注意 -d 写了两个:一个通配符,一个裸域。很多人只写通配符,结果 example.com 本身反而没证书可用。执行后终端会提示你添加一条 _acme-challenge.example.com 的 TXT 记录,值为一串随机字符。去 DNS 后台加上,等生效(通常几十秒到几分钟),回车继续。
验证通过后证书落在 /etc/letsencrypt/live/example.com/ 目录,里面有四个文件,Nginx 只需要用到 fullchain.pem 和 privkey.pem。
手动验证的缺点是每次续期都得重新加 TXT 记录,三个月一次,容易忘。所以生产环境更推荐把 DNS 插件配上,让 certbot 自动完成验证。插件配置涉及 API 密钥,这里不展开,各家云文档写得很细。
Nginx 侧的通配符证书配置写法
证书拿到手,落到 Nginx 配置里其实就几行。下面是一个子域的 server 块示例:
server { listen 443 ssl; server_name blog.example.com; ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; ... }
多个子域可以复用同一个证书路径,各写各的 server_name,不用为每个子域单独指定证书文件。这种写法在子域数量多的时候优势明显——加一个新子域,复制一份 server 块改个名字就行。
有一个细节值得单独说:ssl_certificate 指向的路径在证书续期后会变化吗?Let's Encrypt 的 live 目录是软链接,续期后链接指向新文件,Nginx 重载就能读到新证书,路径本身不用改。
HTTP 跳转 HTTPS 别忘了配
证书配好只解决加密,用户直接输 http:// 还是会走明文。加一个 301 跳转的 server 块,把 80 端口的请求全部引到 443。这段配置几乎是模板化的,但漏配的情况相当普遍。
自动续期与配置后的验证动作
Let's Encrypt 证书有效期 90 天,手动续期不现实。装好 certbot 后系统一般会自动生成 certbot.timer,用 systemctl list-timers | grep certbot 可以确认是否在运行。续期命令是 certbot renew --dry-run,先跑一遍测试,别等到真过期才发现验证失败。
验证环节我喜欢用 openssl s_client -connect blog.example.com:443 -servername blog.example.com 看握手返回的证书链,比浏览器点小锁更直接。另外 curl -I https://example.com 确认没有混合内容警告,能覆盖大部分配置疏漏。
证书透明度日志那块,泛域名证书会在 CT log 里暴露主域名,这对在意信息暴露的站点算个小代价。我个人更看重的是运维效率的提升,一个文件管住全部子域,续期脚本也只维护一份。
几个实际踩过的坑
- DNS 记录加了但没等传播就回车,验证失败三次后触发频率限制,只能等一小时。加完记录先用
dig TXT _acme-challenge.example.com确认返回值再继续。 - Nginx 配置里证书路径写错一个字母,
nginx -t直接报错,但线上 reload 前不测试就重启,会导致整个站点 443 不可用。 - 泛域名证书不覆盖裸域,这是设计如此,不是配置问题。签证书时把裸域一起写进
-d参数即可。
整套流程走顺之后,新增子域基本是「加解析、写 server 块、reload」三步。泛域名证书的价值不在单次配置有多省事,而在于子域规模上去之后,证书管理这件事从 N 份变成 1 份。