You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Nginx根据子域名动态设置root根目录配置未生效排查

配置存在的问题
  • 核心问题是滥用Nginx的if指令触发已知bug:Nginx中server块层级的if属于rewrite模块,执行时会生成隐式的location上下文,很容易出现变量赋值不生效、配置继承错乱的问题,也就是Nginx社区长期提到的If is Evil坑,这是规则不生效的主要原因。
  • 子域名匹配正则写得太松:规则里(?<subdomain>.+)的.会匹配包含.在内的所有字符,会把test.src.mydomain.com这类多级子域名错误捕获,不符合只匹配xxx.mydomain.com格式二级子域名的需求。
  • 缺少必要的请求处理逻辑:现有配置没有PHP解析规则、没有路径兜底逻辑,就算目录映射正确,也会出现PHP文件直接下载、前端路由404的问题。
修正方案

推荐两种写法,按需选择即可:

方案1:单server块+map映射(配置简洁)

map指令在请求早期阶段执行,不会有if的上下文bug,是做变量映射的官方推荐方案。
首先在Nginx配置的http层级(和server块平级,不能写在server块内部)添加映射规则:

map $subdomain $site_folder {
    default "dist";
    "src"   "public";
    "api"   "public";
}

然后修改server块配置:

server {
    listen 8080;
    listen [::]:8080;
    
    # 正则收紧为[^.]+,仅匹配不含点的二级子域名,避免多级域名误命中
    server_name ~^(?<subdomain>[^.]+)\.mydomain\.com$;
    
    root /home/site/wwwroot/$site_folder;
    index index.php index.html;

    location / {
        # 路径兜底:先找对应文件/目录,找不到则走入口文件,适配静态资源、前端history路由、PHP单入口
        try_files $uri $uri/ /index.php?$query_string;
    }

    # PHP解析规则,按需保留,fastcgi_pass地址根据自己的PHP运行环境调整(端口或sock文件路径)
    location ~ \.php$ {
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }
}

如果站点是纯静态页面,不需要PHP支持,直接删掉PHP解析的location块,把try_files最后一段改成/index.html即可。

方案2:多server块精确匹配(兼容性最好)

完全不用正则捕获和变量,靠Nginx原生的server_name优先级匹配,逻辑直白,所有Nginx版本都兼容,没有任何隐式坑:

# 匹配src、api子域名,指向public目录
server {
    listen 8080;
    listen [::]:8080;
    server_name src.mydomain.com api.mydomain.com;
    
    root /home/site/wwwroot/public;
    index index.php index.html;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    # 同样按需添加PHP解析规则
    location ~ \.php$ {
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }
}

# 匹配其余所有二级子域名,指向dist目录
server {
    listen 8080;
    listen [::]:8080;
    server_name ~^[^.]+\.mydomain\.com$;
    
    root /home/site/wwwroot/dist;
    index index.php index.html;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    # 同样按需添加PHP解析规则
    location ~ \.php$ {
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }
}

内容的提问来源于stack exchange,提问作者jssDev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 11:09:28