nginx的server_name指令通过匹配请求host头实现单ip多域名分发,优先级为正则>通配符>精确匹配,未匹配请求由default_server兜底,https需sni配合对应证书。

三种匹配方式,顺序固定、命中即止
nginx 按以下优先级逐个尝试,一旦匹配就不再往下看:
-
正则表达式(最高):以
~(区分大小写)或~*(不区分)开头,适合动态子域,例如:server_name ~^([a-z0-9\-]+)\.example\.com$;
匹配后可通过$1引用捕获的子域名,用于日志、路径拼接或代理转发。 -
通配符(次之):支持左通配
*.example.com(匹配www.example.com、api.example.com),也支持右通配www.*(极少用,需确认实际需求);但不允许中间或双通配,如www.*.com是非法的。 -
精确匹配(最常用):如
server_name example.com www.example.com;,多个域名用空格分隔,不能加逗号、引号或换行。
必须显式处理“没匹配上的请求”
如果某个请求的 Host 不在任何 server_name 中,nginx 默认会交给配置文件中第一个监听该端口的 server 块——这容易暴露默认站点或导致意外交互。
稳妥做法是设一个兜底 server,并标记为 default_server:
- 监听 80 端口时:
server { listen 80 default_server; server_name _; return 444; } - 监听 443 端口时(HTTPS):
server { listen 443 ssl http2 default_server; server_name _; ssl_certificate /path/to/empty.pem; return 444; }
注意:HTTPS 必须提供证书才能完成 TLS 握手,所以即使兜底也要配一个最小可用证书(可自签)。
多域名共用一个 server 块,不是必须拆开
如果你希望 example.com 和 www.example.com 指向同一站点,不需要写两个 server 块,直接合并即可:
- 正确写法:
server_name example.com www.example.com; - 错误写法:
server_name "example.com, www.example.com";(带引号或逗号会被当做一个域名字符串) - 小写习惯很重要:虽然 Host 头不区分大小写,但 nginx 内部统一转小写比对,所以配置全小写更安全,避免
Example.Com这类写法。
HTTPS 场景下,SNI 和证书要对得上
浏览器通过 SNI(Server Name Indication)扩展在 TLS 握手阶段就发送 Host 名,nginx 依据它选择对应的 SSL 证书。这意味着:
- 每个
server块若启用 HTTPS,必须配独立的ssl_certificate和ssl_certificate_key; - 不能靠一个泛域名证书覆盖所有
server_name,除非它们都属于同一通配范围(如*.example.com无法匹配blog.another-site.org); - 若用 SAN 证书,需确保所有域名都包含在证书的 Subject Alternative Name 列表中。











