NGINX虚拟子目录配置问题:多区域路径继承现有规则
Alright, let's tackle this NGINX problem you're dealing with. So you've got a working config for www.site.com pointing to /srv/public_html, but when you added virtual subdirectories like /us, /ca, and /fr-ca (all supposed to use the same document root), static assets broke even though the root index.php loads fine. That makes sense—the issue is NGINX isn't stripping the virtual prefix when resolving static file paths, so it's looking for /srv/public_html/us/css/style.css instead of the correct /srv/public_html/css/style.css.
Here's how to fix this properly, making sure the virtual subdirectories fully inherit your existing rules:
1. Core Virtual Subdirectory Location Block
First, add a location block that matches your virtual prefixes, strips them from the request URI, and passes the rest through to your existing root rules. This ensures all requests to /us/xxx are treated like they're going to /xxx:
# Match our virtual subdirectories: /us, /ca, /fr-ca location ~ ^/(us|ca|fr-ca)(/.*)?$ { # Keep using our existing document root root /srv/public_html; # Strip the virtual prefix from the request URI rewrite ^/(us|ca|fr-ca)(/.*)?$ $2 break; # Inherit our existing index file rules index index.php index.html index.htm; # Reuse the existing try_files logic for clean URLs/rewrites try_files $uri $uri/ /index.php?$args; # If you have other root-level rules (like CORS headers, security settings), copy them here too }
2. Fix Static Asset Handling
If you have dedicated location blocks for static assets (like CSS, JS, images), you need to make sure they also handle the virtual prefixes. You can either adjust the existing blocks or nest them inside the virtual subdirectory block for cleaner organization.
Option A: Adjust Existing Static Asset Rules
Update your existing static asset location to recognize and strip the virtual prefix:
# Updated static asset rule that works with both root and virtual subdirectories location ~ ^/(us|ca|fr-ca)/(.+\.(css|js|png|jpg|gif|svg))$ { root /srv/public_html; rewrite ^/(us|ca|fr-ca)/(.+)$ /$2 break; # Keep your existing cache/expiry rules here expires 30d; add_header Cache-Control "public, no-transform"; } # Keep the original rule for root-level static assets location ~* \.(css|js|png|jpg|gif|svg)$ { expires 30d; add_header Cache-Control "public, no-transform"; }
Option B: Nest Static Asset Rules (Cleaner Approach)
If you prefer to keep all virtual subdirectory logic contained, nest the static asset and PHP rules inside the main virtual prefix location block:
location ~ ^/(us|ca|fr-ca)(/.*)?$ { root /srv/public_html; rewrite ^/(us|ca|fr-ca)(/.*)?$ $2 break; index index.php index.html; try_files $uri $uri/ /index.php?$args; # Nest static asset handling for virtual subdirectories location ~* \.(css|js|png|jpg|gif)$ { expires 30d; add_header Cache-Control "public"; } # Nest PHP processing (match your existing PHP config) location ~ \.php$ { fastcgi_pass unix:/var/run/php/php8.1-fpm.sock; # Adjust to your PHP-FPM socket/path fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } }
3. Key Things to Remember
- Avoid
aliashere: Whilealias /srv/public_html;might seem like a shortcut, it can cause unexpected path issues withtry_filesand complex rewrites. Usingroot+rewriteis more reliable for inheriting root-level rules. - Check relative vs absolute paths: If your HTML uses relative paths (like
css/style.css), browsers will automatically append the virtual prefix (e.g.,/us/css/style.css), which our rewrite rules fix. If you use absolute paths (like/css/style.css), they'll work fine out of the box. - Test before reloading: Always run
nginx -tto check for syntax errors, then reload withsystemctl reload nginx(or your distro's equivalent) to apply changes.
Full Working Config Example
Here's how this fits into a complete server block, assuming your original root config was already working:
server { listen 80; server_name www.site.com; root /srv/public_html; index index.php index.html; # Virtual subdirectory handling location ~ ^/(us|ca|fr-ca)(/.*)?$ { rewrite ^/(us|ca|fr-ca)(/.*)?$ $2 break; try_files $uri $uri/ /index.php?$args; location ~ \.php$ { fastcgi_pass unix:/var/run/php/php8.1-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } location ~* \.(css|js|png|jpg)$ { expires 30d; add_header Cache-Control "public"; } } # Original root directory rules (unchanged) location / { try_files $uri $uri/ /index.php?$args; } location ~ \.php$ { fastcgi_pass unix:/var/run/php/php8.1-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } location ~* \.(css|js|png|jpg)$ { expires 30d; add_header Cache-Control "public"; } }
This setup will make /us, /ca, and /fr-ca behave exactly like your root directory—all static assets load correctly, and your existing rewrite/PHP rules are fully inherited.
内容的提问来源于stack exchange,提问作者TylerMills

