Nginx - location with root in other directory and PHP
nginx, nginx-location, php
Solution
Running two PHP applications side-by-side, you either need a common document root, or you need two `location ~* \.php` (or similar) blocks to ensure the correct `SCRIPT_FILENAME` is sent to the fastcgi backend.
Use nested `location` blocks to isolate the `/cut` subdirectory, and use the `^~` modifier at the top level to avoid other top level regular expression `location` blocks from interfering (see this documentation).
The `alias` directive (see this documentation) is used to map `/cut` to `/var/www/cut/public`. The `root` directive can only concatenate, which would make `/var/www/cut/public/cut` (which you do not want).
However, I would not recommend using the `alias` directive with the `try_files` directive because of this long term issue.
So, a solution would be to silently rewrite `/cut` to `/cut/public` and use a value of `root /var/www`.
For example:
location ^~ /cut {
rewrite ^/cut(.*)$ /cut/public$1 last;
}
location ^~ /cut/public {
root /var/www;
try_files $uri $uri/ /cut/index.php$is_args$args;
location ~* \.php(/|$) {
fastcgi_pass php:9000;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
Problem
I tried to set a location similar as "Apache Alias" with Nginx but I don't able to process PHP script in this folder. Here is my folder structure (for Dev environment): ``` /var/www +- dev/public/ <-- This is my normal Web root : "/" | +- assets/ | | +- app.css | | +- app.js | | | +- index.php | +- favicon.png | +- cut/public/ <-- This must like an "Apache Alias" : "/cut" +- assets/ | +- app.css | +- app.js | +- index.php +- other_other_file.php (why not) ``` I've tried different solutions but none of them are working. Here is my best Nginx configuration : ``` server { listen 80; server_name _; root /var/www/dev/public/; index index.php index.html; autoindex on; # Logs rewrite_log on; error_log /var/log/nginx/error.log; access_log /var/log/nginx/access.log; # Serving files location / { try_files $uri $uri/ @php; } location /cut { root /var/www/cut/public; try_files $uri $uri/ @php; } # PHP location @php { rewrite ^(.*)/?$ /index.php$is_args$args last; } location ~* \.php(/|$) { fastcgi_pass php:9000; fastcgi_split_path_info ^(.+\.php)(/.*)$; fastcgi_param DOCUMENT_ROOT $document_root; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } } ``` With this one, all the content of my `cut/public/` folder is redirected to the `dev/public/index.php` and interpreted (cause of `try_file`, I presume). That is why your help would be welcome. Final Solution After the answer of @richard-smith, here's the implemented solution : ``` server { listen 80; server_name _; root /var/www/dev/public/; index index.php index.html; error_log /var/log/nginx/error.log; access_log /var/log/nginx/access.log; location ^~ /cut { rewrite ^/cut/?(.*)$ /cut/public/$1 last; } location ^~ /cut/public { root /var/www/; try_files $uri $uri/ /cut/index.php$is_args$args; location ~* \.php(/|$) { fastcgi_pass php:9000; fastcgi_split_path_info ^(.+\.php)(/.*)$; fastcgi_param DOCUMENT_ROOT $document_root; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } } location / { try_files $uri $uri/ /index.php$is_args$args; } location ~* \.php(/|$) { fastcgi_pass php:9000; fastcgi_split_path_info ^(.+\.php)(/.*)$; fastcgi_param DOCUMENT_ROOT $document_root; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } } ```