推荐用独立server块实现多虚拟主机隔离:每个server块配专属root、server_name或端口,语义明确、路径对齐、配置独立;避免在location中用root导致路径重复拼接,必要时用alias+^~前缀匹配。

直接用 root 指令在同一个 server 块里实现多个虚拟主机的目录隔离——不推荐,也容易出错。root 本身不是为“多站点路径隔离”设计的,它在 location 中的行为是覆盖+拼接,不是精准映射。
真正安全、清晰、可维护的做法,是 用独立 server 块 + server_name 或端口区分,每个 server 块配一个专属 root。这才是 Nginx 原生支持的虚拟主机模式。
正确做法:用多个 server 块隔离站点(推荐)
每个站点独占一个 server 块,靠域名或端口区分,root 在 server 级生效,语义明确、无干扰:
server {
listen 80;
server_name site1.example.com;
root /var/www/site1;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
server {
listen 80;
server_name site2.example.com;
root /var/www/site2;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}- ✅
root路径与请求 URI 完全对齐(访问/→/var/www/site1/index.html) - ✅ 各站点日志、SSL、限流等配置可完全独立
- ✅ 不会出现路径多拼一层(比如
/site2/xxx变成/var/www/site2/site2/xxx)
注意:
server_name需配合 DNS 或本地/etc/hosts解析;若仅内网测试,也可改用不同端口(如listen 8081/listen 8082)。
为什么不要在 location 里用 root 做站点隔离?
常见错误写法(会导致 404):
server {
root /var/www/default;
location /app1/ {
root /var/www/app1; # ❌ 错误:访问 /app1/css/main.css → 实际找 /var/www/app1/app1/css/main.css
}
location /app2/ {
root /var/www/app2; # ❌ 同样多拼一层 /app2/
}
}原因:
-
root在location中会完整保留请求 URI,再拼到指定路径后; - 所以
/app1/xxx会被拼成/var/www/app1/app1/xxx,而非你想要的/var/www/app1/xxx。
如果必须共用一个域名+路径前缀(如 /admin/, /api/)
那就放弃 root,改用 alias + 精确匹配:
location ^~ /admin/ {
alias /var/www/admin/;
try_files $uri $uri/ /admin/index.html;
}
location ^~ /portal/ {
alias /var/www/portal/;
try_files $uri $uri/ /portal/index.html;
}关键细节:
-
alias路径末尾必须带/,否则/admin/css/a.css会错映射为/var/www/admincss/a.css -
^~表示前缀匹配且优先于正则,避免被其他 location 覆盖 -
try_files的 fallback 路径(如/admin/index.html)要和alias的逻辑路径一致
补充:文件权限与安全加固
即使路径映射正确,也要防止越权访问:
- Linux 文件权限设为
750,属主为部署用户,属组为www-data(或nginx),Nginx 工作进程用该组运行 - 禁用
autoindex on,除非业务强需求;启用时务必加auth_basic认证 - 在敏感
location块中加过滤,例如:
location ~ \.\. {
deny all;
}
location ~ \.(htaccess|htpasswd|env|log|ini)$ {
deny all;
}不复杂但容易忽略。


















