Nginx location without initial path component

nginx

I have a location block that looks something like this:

root /var/www/ProjectP;

location /p/ {
    index index.php;
    try_files $uri $uri/ =404;
}

location ~ /p/.*\.php$ {
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/run/php/php7.0-fpm.sock;
}

In order to make that work, I created a directory /var/www/ProjectP/p/, which is a horrible hack, because it puts the knowledge of where in http space the project is served with the project and not with nginx. Nginx config should be able to move it to /pp/ without modifying project P.

This particular project doesn't have a proxy_pass directive, but that will happen next, and then my hack is quite unlikely to work.

I'm sure nginx has a correct way to handle something so common, but I've not found it. Any pointers?

Update 1

As @RichardSmith notes, the right approach is surely an alias directive. Testing this on static content works nicely:

location /a/ {
    alias /var/www/ProjectA/;
    index index.html;
    try_files $uri $uri/ =404;
}

When I do the same with the php code, I get half success:

location /p/ {
    alias /var/www/ProjectP/;
    index index.php;

    # First attempt to serve request as file, then
    # as directory, then fall back to displaying a 404.
    try_files $uri $uri/ =404;
}

# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
location ~ /p/(.+\.php)$ {
    alias /var/www/ProjectP/$1;
    include snippets/fastcgi-php.conf;

    # With php7.0-fpm:
    fastcgi_pass unix:/run/php/php7.0-fpm.sock;
    ## These next are largely set via snippets/fastcgi-php.conf.
    ## Trying them here doesn't help, but I leave them (commented out)
    ## for the moment...
    #fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    #include fastcgi_params;
    #fastcgi_param SCRIPT_FILENAME $uri;
}

Testing against a non-php file, I confirm that the first block works. But the second block does not, and so php files don't serve properly. (I get 404's.) I've tried a few variants on the commented-out fastcgi directives at the end, but clearly not the right combination.

Update 2

This works.

root /var/www/;

location /p/ {
    alias /var/www/ProjectP/;
    index index.php;

    # First attempt to serve request as file, then
    # as directory, then fall back to displaying a 404.
    try_files $uri $uri/ =404;

    # Pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;

        # With php7.0-fpm:
        fastcgi_pass unix:/run/php/php7.0-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $request_filename;
    }
}

Best Answer

This works.

root /var/www/;

location /p/ {
    alias /var/www/ProjectP/;
    index index.php;

    # First attempt to serve request as file, then
    # as directory, then fall back to displaying a 404.
    try_files $uri $uri/ =404;

    # Pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;

        # With php7.0-fpm:
        fastcgi_pass unix:/run/php/php7.0-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $request_filename;
    }
}