3

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;
    }
}
4
  • You should use an alias statement. Something like this answer Oct 12, 2017 at 9:12
  • @RichardSmith Thanks, I think that's the right approach. And after some reading and fiddling, it yields progress, but not quite success. I've amended the question to show what I've tried.
    – jma
    Oct 12, 2017 at 18:45
  • @RichardSmith Now that I got it working, I see that you were 100% right and I had mistyped (mis-copied) the solution presented in that link. Sigh.
    – jma
    Oct 12, 2017 at 19:23
  • My only suggestion is to remove your try_files statement which is default nginx behaviour anyway. try_files and alias can be a troublesome together, see this issue. Oct 12, 2017 at 19:24

2 Answers 2

1

There is at least one issue with your location block.

If you request http://www.example.com/p/test.php, the contents of $1 variable will be test.php.

This means your

alias /var/www/ProjectP/$1;

will make the document root directory to /var/www/ProjectP/test.php.

Then, the

fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

defines the actual filepath sent to PHP process to locate the file. $document_root contains the alias path in this cast, and $fastcgi_script_name contains the filename from the request.

So, the end result in your case, that the request to http://www.example.com/p/test.php ends up to a filename /var/www/ProjectP/test.phptest.php for PHP process. Therefore there will be a 404 returned.

The fix is to just use:

alias /var/www/ProjectP

in the PHP location block.

3
  • That makes sense, but doesn't fix the problem. I'm not sure why. I also tried specifying $document_root and $request_filename. But this sorted the problem. I'm not 100% sure why they are different. Here the php location block is nested in the outer block.
    – jma
    Oct 12, 2017 at 19:12
  • Cf. update 2, above, for what the successful block looks like.
    – jma
    Oct 12, 2017 at 19:17
  • Please post the solution as an answer yourself and accept it and remove the update from the question. Oct 13, 2017 at 4:36
1

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;
    }
}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .