Nginx可通过map+server_name+root组合实现子域名自动映射目录:将admin.test.staging.example.com解析为/var/www/example/staging/test/admin。原理是提取子域名、按点分隔并反转顺序拼接路径,需在http块中用正则逐级捕获并反序组装,server块中直接引用$dynamic_root变量。

Nginx 的 root 指令本身不支持动态解析子域名,但可以通过 map + server_name + root 的组合方式,实现多级子域名(如 admin.test.staging.example.com)自动映射到对应层级目录(如 /var/www/example/admin/test/staging)的效果。
核心原理:子域名转路径
把请求域名中主域名前的子域名部分(如 admin.test.staging)按点(.)分隔、反转顺序,再拼成路径片段。例如:
-
blog.example.com→blog→/var/www/example/blog -
api.v2.dev.example.com→api.v2.dev→ 反转为dev/v2/api→/var/www/example/dev/v2/api -
admin.test.staging.example.com→admin.test.staging→ 反转为staging/test/admin→/var/www/example/staging/test/admin
在 http 块中定义 map 映射逻辑
必须放在 http{...} 全局块内,不能写在 server 块里:
map $host $subdomain_path {
~^(?<sub>[^.]+\.)*example\.com$ $sub;
default "";
}
map $subdomain_path $docroot_path {
"~^([^.]*)\.?$" "/$1";
"~^([^.]*)\.([^.]*)\.?$" "/$2/$1";
"~^([^.]*)\.([^.]*)\.([^.]*)\.?$" "/$3/$2/$1";
default "";
}
map $docroot_path $dynamic_root {
"~^/(.+)$" "/var/www/example/$1";
default "/var/www/example";
}
说明:上面用三级正则覆盖常见子域级数(1~3 级),每级捕获后按反序拼接。若需支持更深(如 4 级),可继续扩展正则分支。
在 server 块中启用动态 root
直接引用 $dynamic_root 变量作为 root 值:
server {
listen 80;
server_name ~^(?:.+\.)*example\.com$;
root $dynamic_root;
location / {
index index.html;
try_files $uri $uri/ =404;
}
}
注意:server_name 必须用正则匹配所有子域名形式;root 后不可加引号,且变量必须已由 map 定义生效。
验证与调试技巧
配置完成后,建议做这几件事:
- 运行
nginx -t检查语法是否正确 - 用
curl -H "Host: api.v2.dev.example.com" http://127.0.0.1测试是否命中预期目录 - 在目标目录下放一个
info.php或debug.txt,内容输出$document_root(可通过 fastcgi_param 或日志变量临时确认) - 查看错误日志:
tail -f /var/log/nginx/error.log,常见报错如 “directory not found” 多因路径拼错或权限不足


















