Create a gist now

Instantly share code, notes, and snippets.

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

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

@bagage
bagage commented Jul 18, 2013

Thank you guy!

@brahimmachkouri

Really helpful. Thanks.

@subterfugium

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?

@alanorth

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...
@nyuszika7h

@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
frewie commented Jan 17, 2017

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

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