nginx多域名虚拟主机冲突本质是匹配逻辑、加载顺序与ssl上下文三者失控:每个域名须独占独立server块并精准配置证书,按字典序命名conf文件控制加载,http/https端口均需显式设default_server,最终以nginx -t验证合并配置。

确保每个域名有唯一且明确的 server 块
Nginx 不会智能合并多个域名,它只按规则选一个 server 块处理请求。若两个配置文件里都写了 server_name example.com;,后加载的那个会被忽略——不是报错,是静默失效。
- 一个域名(含 www 和非 www)应统一写在同一 server 块里:server_name example.com www.example.com;
- 避免泛用通配符,如 server_name *.com; —— 它可能意外匹配到无关域名
- 检查重复项:运行 grep -r "server_name" /etc/nginx/conf.d/ | grep -v "#",确认没有相同域名出现在多个文件中
- 废弃旧配置(如 default.conf、test.conf),防止干扰
控制配置加载顺序与 default_server 设置
Nginx 按字典序读取 /etc/nginx/conf.d/*.conf,顺序决定“谁先被选为默认”。没设 default_server 时,第一个定义的 server 就是兜底者,容易误接管流量。
- 给主站命名 00-main.conf,测试站用 10-test.conf,兜底站用 99-default.conf
- HTTP 和 HTTPS 端口必须分别设 default_server:listen 80 default_server; 和 listen 443 ssl default_server;
- 兜底块建议最小化,例如返回 444(直接断连)或跳转维护页,避免泄露主站证书或内容
HTTPS 场景必须独立配置,不能共用证书块
HTTP 可靠,HTTPS 很脆弱——TLS 握手依赖 SNI(Server Name Indication)。如果多个域名塞进同一个 server { listen 443 ssl; } 块,Nginx 无法在握手阶段区分它们,必然证书错配。
- 每个域名对应一个独立的 server 块,且必须包含完整 SSL 上下文:ssl_certificate、ssl_certificate_key(权限 600)、推荐加 ssl_trusted_certificate
- 不要写 server_name a.com b.com; 却只配 a.com 的证书——b.com 访问时浏览器会直接拦截
- 跨主域(如 site-a.com 和 site-b.net)需 SAN 证书;同主域多子域(如 api.example.com、www.example.com)可用通配符证书
- 验证是否生效:curl -I --resolve site-a.com:443:你的IP https://site-a.com,观察响应头和证书信息
验证最终生效配置,别只信文件名
改完配置,光看文件不等于 Nginx 看得懂。真正起作用的是合并后的结果。
- 执行 nginx -t 检查语法,重点留意警告如 "conflicting server name"
- 运行 nginx -T 输出全部合并配置,人工核对每个 server 块的 listen 和 server_name 是否唯一、合理
- 确认 DNS 已解析到当前服务器 IP,否则请求根本到不了 Nginx











