https下多个域名共用一个nginx实例时,server_name写多个仅首个生效,因sni机制只依据第一个域名查找证书san;http则无此限制。

多个域名共用一个 Nginx 实例时,server_name 写多个只生效一个,不是配置写错了,而是 HTTPS 下 SNI 协商机制决定的——它只认第一个域名去加载证书;HTTP 层虽能匹配全部,但 SSL/TLS 握手失败会导致整个连接中断。
server_name 多域名写法在 HTTP 和 HTTPS 中表现不同
HTTP 请求不走 TLS,server_name example.com www.example.com 完全可用,$host 也能取到真实值;HTTPS 则必须靠 SNI 告诉服务器该用哪张证书,而 Nginx 只用首个 server_name 查证书的 SAN 列表。如果证书没包含其余域名,浏览器就报 NET::ERR_CERT_COMMON_NAME_INVALID。
- HTTP 场景下可放心空格分隔多个域名,用于统一跳转或静态服务
- HTTPS 必须确保所有域名都出现在证书 SAN 中,生成命令类似:
certbot -d example.com -d www.example.com - 泛域名
*.example.com不覆盖根域名example.com,得额外加一行server_name example.com;
多个域名必须分设独立 server 块的典型场景
当你要为不同域名设置不同 root 路径、SSL 证书来源、访问日志路径或跳转逻辑时,就不能挤在一个 server 块里。否则会出现访问 blog.example.com 却返回 shop.example.com 的首页这类问题。
- 每个
server块必须有独立的server_name,且不能依赖空格“模拟”多站 - 所有
server块的listen指令要严格一致:比如都是listen 443 ssl,混用listen 443和listen 443 ssl会导致匹配失效 - DNS 或
/etc/hosts必须把域名解析到服务器 IP,否则 Host 头根本送不到 Nginx
root 和 alias 在 location 中的行为差异极易出错
这是静态文件 404 最常见的原因:二者拼接路径的方式完全不同。你改了 location 或 root,却没意识到实际查找路径已经变了。
-
location /static/ { root /var/www; }→ 请求/static/js/app.js会找/var/www/static/js/app.js -
location /static/ { alias /var/www/static/; }→ 同样请求会找/var/www/static/js/app.js(注意alias值末尾必须带斜杠) -
alias是“替换掉 location 路径部分”,root是“拼接到 location 路径之后”——这个区别决定了你能不能拿到文件
配置生效前必须验证和重载,不能只改文件
server 块必须放在 http 块内部才有效,顶格写或塞进 events 块里会直接报 unknown directive "server"。改完不验证就 reload,等于把错误配置推上线。
- 推荐做法:在
/etc/nginx/conf.d/下新建example.com.conf,只放一个server块 - 每次修改后必须运行
sudo nginx -t验证语法,成功后再sudo systemctl reload nginx - 监听 80 端口对外不可达?检查是否写了
listen 127.0.0.1:80(仅本地),应改为listen 80;或listen *:80;
真正容易被忽略的是:SNI 匹配和证书 SAN 的对应关系是硬性限制,不是 Nginx 配置技巧能绕过的;而 root 和 alias 的语义差异,往往要等到文件 404 了才回头翻文档。











