一个天大的好消息,Let’s Encrypt 已经发布了通配符版本 SSL 证书。顾名思义,通配符 SSL 证书不再需要为每一个二级域名重复申请 SSL 证书,以域名 bugprogrammer.tk 为例,只需要申请 *.bugprogrammer.tk 以及 bugprogrammer.tk 即可用于根域名以及所有二级域名,非常方便。申请教程如下。

为 Nginx 配置 Let's Encrypt 通配符证书(Wildcard Certificate,如 *.example.com)与配置普通单域名证书有本质区别:通配符证书必须使用 DNS-01 验证方式,无法使用传统的 HTTP-01(即无法通过 Web 服务器自动验证)。
以下是基于最佳实践的配置全流程,以 Certbot 配合 Cloudflare DNS 插件为例(其他 DNS 服务商如阿里云、腾讯云、AWS Route53 原理类似,只需更换对应的 Certbot 插件)。
1. 核心前置条件
域名控制权:你必须能够修改域名的 DNS 记录(添加 TXT 记录)。
DNS API 权限:为了实现自动化续期,建议在 DNS 服务商处生成 API Token 或 Key。
覆盖范围注意:
*.example.com 仅覆盖一级子域名(如 api.example.com, www.example.com)。
不覆盖根域名(example.com),申请时需同时指定 -d example.com -d *.example.com。
不覆盖多级子域名(如 dev.api.example.com),如需支持需单独申请 *.api.example.com。
2. 安装 Certbot 及 DNS 插件
根据你的操作系统和 DNS 服务商安装对应的插件。以下以 Ubuntu/Debian 和 Cloudflare 为例:
bash
# 更新包列表
sudo apt update
# 安装 Certbot 和 Cloudflare DNS 插件
sudo apt install certbot python3-certbot-dns-cloudflare -y
其他常见插件:
阿里云:python3-certbot-dns-aliyun
腾讯云(DNSPod):python3-certbot-dns-dnspod
AWS Route53:python3-certbot-dns-route53
3. 配置 DNS API 凭证
为了安全且自动化地通过 DNS 验证,需要创建一个凭证文件。
获取 API Token:
登录 Cloudflare 控制台 -> 我的个人资料 -> API 令牌 -> 创建令牌。
使用模板“编辑区域 DNS”,选择你的域名,生成 Token。
创建凭证文件:
bash
sudo mkdir -p /etc/letsencrypt/cloudflare
sudo nano /etc/letsencrypt/cloudflare/credentials.ini
填入内容:
ini
dns_cloudflare_api_token = YOUR_CLOUDFLARE_API_TOKEN
(注:如果使用 Global API Key,字段名为 dns_cloudflare_email 和 dns_cloudflare_api_key,但推荐使用 API Token 以提高安全性)
设置严格权限(至关重要,否则 Certbot 会拒绝运行):
bash
sudo chmod 600 /etc/letsencrypt/cloudflare/credentials.ini
4. 申请通配符证书
执行以下命令申请证书。注意必须包含根域名和通配符域名。
bash
sudo certbot certonly \
--dns-cloudflare \
--dns-cloudflare-credentials /etc/letsencrypt/cloudflare/credentials.ini \
--dns-cloudflare-propagation-seconds 30 \
-d example.com \
-d "*.example.com" \
--email your-email@example.com \
--agree-tos \
--no-eff-email
--dns-cloudflare-propagation-seconds 30:等待 DNS 记录全球传播的时间,若申请失败可适当增加至 60 或 120。
成功后,证书文件将保存在 /etc/letsencrypt/live/example.com/ 目录下。
验证证书内容:
bash
sudo openssl x509 -in /etc/letsencrypt/live/example.com/fullchain.pem -text -noout | grep "Subject Alternative Name"
输出应包含 DNS:*.example.com, DNS:example.com。
5. 配置 Nginx
通配符证书的优势在于只需配置一次,即可服务于所有匹配的子域名。
方案 A:统一配置(推荐,适合子域名行为一致的场景)
使用正则表达式匹配所有一级子域名。
nginx
# /etc/nginx/sites-available/wildcard.conf
# 1. HTTP 强制跳转 HTTPS
server {
listen 80;
server_name example.com *.example.com;
return 301 https://$host$request_uri;
}
# 2. HTTPS 主配置
server {
listen 443 ssl http2;
# 使用正则匹配所有一级子域名
server_name ~^(?<subdomain>.+)\.example\.com$;
# 证书路径
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# SSL 优化配置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
ssl_prefer_server_ciphers off;
# 示例:根据子域名转发到不同后端或目录
location / {
root /var/www/html/$subdomain; # 动态根目录
index index.html;
try_files $uri $uri/ =404;
}
}
# 3. 根域名单独配置(因为正则不匹配根域名)
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
root /var/www/html/root;
index index.html;
}
方案 B:独立 Server 块(适合子域名差异大的场景)
如果每个子域名指向完全不同的应用(如 blog 是 WordPress,api 是 Node.js),建议为每个子域名写独立的 server 块,但共用同一组证书文件。
nginx
server {
listen 443 ssl http2;
server_name api.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:3000;
}
}
server {
listen 443 ssl http2;
server_name blog.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
root /var/www/blog;
index index.php;
# ... PHP 配置
}
6. 测试与重载
检查 Nginx 配置语法:
bash
sudo nginx -t
重载 Nginx:
bash
sudo systemctl reload nginx
浏览器访问测试:
访问 https://test.example.com(确保该子域名已解析到服务器 IP),点击地址栏锁图标,确认证书有效且覆盖 *.example.com。
7. 配置自动续期
Let's Encrypt 证书有效期为 90 天。由于使用了 DNS 插件,Certbot 可以自动完成续期,无需人工干预。
测试续期命令:
bash
sudo certbot renew --dry-run
如果显示 Congratulations, all simulated renewals succeeded,则配置正确。
确认定时任务:
Certbot 安装时会自动创建 systemd timer 或 cron job。
bash
sudo systemctl list-timers | grep certbot
通常每天会检查两次,若证书剩余时间少于 30 天则自动续期并重新加载 Nginx(需在 /etc/letsencrypt/renewal-hooks/deploy/ 中添加重载脚本,或确保证书路径未变,Nginx reload 即可识别新证书)。
若需手动确保重载,可创建部署钩子:
bash
sudo nano /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
内容:
bash
#!/bin/bash
systemctl reload nginx
赋予执行权限:
bash
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
常见问题排查
错误:PluginError 或 Credentials error:检查 /etc/letsencrypt/cloudflare/credentials.ini 的权限是否为 600,且文件格式正确(无多余空格)。
错误:DNS problem: NXDOMAIN:检查域名解析是否正确,以及 API Token 是否有权限编辑该域名的 DNS 记录。
浏览器提示证书不安全:确保证书链完整,Nginx 中必须使用 fullchain.pem 而不是 cert.pem。
根域名无法访问:确保证书申请时包含了 -d example.com,且 Nginx 中有针对 example.com 的独立 server_name 配置。
版权声明
本文仅代表作者观点,不代表本站立场。
本文系作者授权本站发表,未经许可,不得转载。
评论列表
发表评论