用一张SAN证书在Nginx上支持多个域名,本质是一个server块绑定所有域名并指向同一份覆盖全部域名的证书;需确保证书SAN字段显式包含每个域名(如example.com、www.example.com、api.example.com),server_name用空格分隔,配合ssl_certificate等指令及HSTS、会话复用等安全配置,且续期时必须完整指定所有域名。

用一张 SAN(Subject Alternative Name)证书在 Nginx 上支持多个域名,本质是“一个 server 块 + 一份覆盖全部域名的证书”,而不是为每个域名建多个 server 块。这种方式适合子域统一管理、API 多端点(如 api.example.com、webapi.example.com)、或品牌关联站点等场景,配置简洁、维护成本低。
确认证书已包含所有目标域名
SAN 证书必须显式列出所有要托管的域名,否则浏览器会报“证书名称不匹配”。验证方法:
- 运行命令:
openssl x509 -in /path/to/cert.pem -text -noout | grep -A1 "Subject Alternative Name" - 输出中应包含类似:
DNS:example.com, DNS:www.example.com, DNS:api.example.com, DNS:*.admin.example.com - 注意:通配符
*.example.com仅匹配一级子域,不能覆盖a.b.example.com;裸域(example.com)和带 www 的域名需同时写入,否则访问www.example.com会失败
单 server 块绑定全部域名与证书
无需为每个域名单独写 server 块。只需一个 HTTPS server 块,把所有域名都列在 server_name 中,并指向同一份 SAN 证书:
-
listen 443 ssl http2;—— 统一监听 443 -
server_name example.com www.example.com api.example.com rest.example.com;—— 空格分隔,无逗号 ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;- 后端转发可基于
$host或请求路径做条件判断,例如:proxy_pass https://backend-$host;或用map指令预定义路由规则
补充关键配置项(提升兼容性与安全性)
这些不是可选装饰,而是生产环境必需项:
-
ssl_protocols TLSv1.2 TLSv1.3;—— 禁用老旧协议 -
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:...;—— 使用现代强加密套件 -
ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m;—— 启用会话复用,降低握手开销 -
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;—— 强制 HSTS,防止降级攻击 - 若需 HTTP 自动跳转 HTTPS,另配一个
listen 80;块,用return 301 https://$host$request_uri;
验证与更新要点
SAN 证书的生命周期管理比单域名更敏感:
- Let’s Encrypt 申请时必须一次性指定所有域名:
certbot certonly --nginx -d example.com -d www.example.com -d api.example.com - 续期命令需完全一致,漏掉任一域名会导致该域名证书失效
- Nginx 配置修改后务必执行:
nginx -t && nginx -s reload,避免语法错误导致服务中断 - 建议用 SSL Labs Test 扫描,确认证书链完整、协议启用正确、无弱算法残留











