Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
nginx userdir + PHP-FPM
server {
listen 80;
server_name localhost;
# ... other default site stuff, document root, etc. ...
location ~ ^/~(?<userdir_user>.+?)(?<userdir_uri>/.*)?$ {
alias /home/$userdir_user/public_html$userdir_uri;
index index.html index.htm index.php;
autoindex on;
include php5_generic;
}
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $request_filename;
fastcgi_pass unix:/var/run/php5-fpm.sock;
}

Used to setup user directories on my personal server. Works brilliantly. Saved me a lot of time and stress. Thanks.

bagage commented Jul 18, 2013

Thank you guy!

Really helpful. Thanks.

This was very good example.

However, I think this example doesn't set PATH_INFO correctly as in http://wiki.nginx.org/PHPFcgiExample.

I did modifications for the regexp to match https://server.com/user/username/ userdirs:

default.conf

        location ~^/user/(?<userdir_user>.+?)(?<userdir_uri>/.*)?$ {
                alias /home/$userdir_user/www$userdir_uri;
                index index.html index.htm index.php;
                autoindex on;

                include php5_userdirs;
        }

(This has to be before the location / rule)

Now for example

http://example.com/user/joe/test.php/foo/bar.php?v=1

saves

$userdir_user = joe
$userdir_uri = /test.php/foo/bar.php?v=1

and

php5_userdirs

location ~ \.php$ {
        include fastcgi_params;
        fastcgi_param DOCUMENT_ROOT /home/$userdir_user/www;
        fastcgi_split_path_info ^(.+?\.php)(/.*)$;
        fastcgi_param SCRIPT_FILENAME $request_filename;
        fastcgi_pass unix:/var/run/php5-fpm.sock;
}

and now SCRIPT_FILENAME, SCRIPT_NAME, PATH_INFO, REQUEST_URI, DOCUMENT_URI and DOCUMENT_ROOT variables seem to be like in nginx documentation example.

I have no idea if this is correct and I need to run more tests.

It's still missing one part of the NGINX guide:

              if (!-f $document_root$fastcgi_script_name) {
                        return 404;
                }

Can someone confirm if my findings are correct?

Here's what I'm doing for PHP + userdirs in ~user:

Amend default.conf:

    index index.php index.html index.htm;
    autoindex on;

    # user directories
    location ~ ^/~(?<userdir_user>[\w-]+)(?<userdir_uri>/.*)?$ {
        alias /home/$userdir_user/public_html$userdir_uri;

        location ~ [^/]\.php(/|$) {
            include php5_common;
        }   
    }   

    # php support
    location ~ [^/]\.php(/|$) {
        include php5_common;
    }   

Add php5_common:

include fastcgi_params;

fastcgi_index index.php;

# check if requested PHP file really exists
if (!-f $request_filename) {
    return 404;
}

#NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_param SCRIPT_FILENAME $request_filename;

fastcgi_pass unix:/var/run/php-fpm-www.sock;

Some notes:

  • using one common include for php5 stuff
  • using if to test for existence of PHP script file on disk before passing it to php-fpm (try_files doesn't work after the alias in the userdir context because alias overrides the document root, and this is a valid use of if)
  • uses $request_filename instead of $fastcgi_script_name as it works better when you are using aliases, and provides the translated disk path for the script
  • Doesn't bother with PATH_INFO or DOCUMENT_ROOT fastcgi parameters because I'm not sure I need them yet...

@alanorth Thanks! I added that to my nginx config (with a minor adjustment; the socket on Debian is /var/run/php5-fpm.sock) and it works perfectly.

frewie commented Jan 17, 2017

The php5_generic cannot be included directly, it should be in a separate file. Otherwise it won't work.

Could this be modified to work with Gunicorn does anyone know?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment