Nginx用server_name配置多域名虚拟主机的核心是单个server块通过空格分隔多个域名(如server_name example.com www.example.com;),匹配优先级为精确>左通配符>正则,HTTPS需SAN证书覆盖全部域名且首个域名必须在证书中,未匹配请求须设default_server兜底。

Nginx 用 server_name 匹配多个域名,核心是让一个 server 块响应多个 Host 请求,而不是靠堆砌多个 server 块。关键在写法、匹配逻辑和 HTTPS 兼容性。
空格分隔多个域名,一行写完
想让 example.com、www.example.com 和 shop.example.com 都走同一个站点配置,直接写:
server {
listen 80;
server_name example.com www.example.com shop.example.com;
root /var/www/html;
index index.html;
}- ✅ 正确:域名之间用空格分隔,写在同一行
- ❌ 错误:加引号、逗号(如
"example.com, www.example.com")会被当做一个非法域名 - ❌ 错误:换行或用
\n分隔,Nginx 不识别,整行失效
这样配置后,只要 HTTP 请求头里的 Host 字段匹配其中任意一个,请求就进入这个 server 块。$host 变量仍保留原始访问域名,可用于日志标记、条件跳转或路径拼接。
匹配优先级固定,不看书写顺序
Nginx 不是按配置先后扫描,而是按三类规则分组比对,命中即停:
- 精确匹配最优先:
server_name api.example.com;只响应Host: api.example.com - 左通配符次之:
server_name *.example.com;匹配shop.example.com,但不匹配example.com或dev.test.example.com - 正则匹配最灵活但性能稍低:
server_name ~^([a-z0-9\-]+)\.example\.com$;注意点号要转义,结尾加$防止部分匹配
如果同时存在 example.com 和 *.example.com,前者一定胜出——别指望调换顺序来控制优先级。
HTTPS 必须用 SAN 证书覆盖全部域名
HTTP 层靠 Host 头路由没问题,但 TLS 握手阶段依赖 SNI,Nginx 只拿 server_name 列表里的第一个域名去校验证书的 SAN(Subject Alternative Name)字段:
- 如果证书只含
example.com,而你写了server_name example.com www.example.com;,访问www.example.com就会提示证书错误 - 正确做法:申请证书时显式包含所有域名,例如 Certbot 命令:
certbot -d example.com -d www.example.com -d shop.example.com
- 证书文件本身无顺序,但 Nginx 加载时只检查首个
server_name是否在 SAN 列表中;其余域名靠$host在 HTTP 层区分。
未匹配请求必须设兜底 server
用户用 IP 直接访问、填错 Host 头、或 DNS 解析异常时,Nginx 默认把请求交给该端口下第一个 server 块——容易暴露测试页或跳错站:
- HTTP 兜底推荐:
server { listen 80 default_server; server_name _; return 444; # 直接断连,更安全 } - HTTPS 兜底同样必要,且需配对应证书:
server { listen 443 ssl http2 default_server; server_name _; ssl_certificate /path/to/default.pem; ssl_certificate_key /path/to/default.key; return 444; }


















