Nginx & UserDir & PHP

5,400

I would change root dir rather than using alias in location. It could look like this:

listen          8083;                                
server_name     sid0.local;
index           index.php index.html;

# Here is magic
set $root_dir /data/www/sid0.local;
rewrite ^(/~[^/]+)$ $1/ redirect;
rewrite ^/~(?<user>[^/]+)(.+) $2;
if ($user) {
    set $root_dir /home/$user/www;
}
root $root_dir;

# PHP-FPM
location ~ \.php$ {
    try_files $uri =404;
    include         fastcgi_params;
    fastcgi_pass    unix:/var/run/php5-fpm.sock;
    fastcgi_index   index.php;
}

Another version without rewrite:

listen          8083;                                
server_name     sid0.local;
index           index.php index.html;

root /data/www/sid0.local;

location ~ ^/~(?<user>[\w-]+)(?<path>/.*)$ {
    alias /home/lynn/tmp/site/$user/www$path;
    autoindex on;

    # PHP-FPM
    location ~ \.php$ {
        try_files $uri =404;
        include         fastcgi_params;
        fastcgi_pass    unix:/var/run/php5-fpm.sock;
        fastcgi_index   index.php;
    }
}

For some reason alias with named captures working, while with numeric references it fails. My guess, that numeric references are cleared somehow in nested location.

Share:
5,400

Related videos on Youtube

ckujau
Author by

ckujau

Updated on September 18, 2022

Comments

  • ckujau
    ckujau over 1 year

    I have a fairly simple nginx/1.4.7 installation (from Debian/unstable) and I'm trying to get PHP scripts to run inside a UserDir.

    server {
            listen          8083;                                
            server_name     sid0.local;
            index           index.php index.html;
            root            /data/www/sid0.local;
    
            location / {
                    try_files $uri $uri/ =404;
            }
    
            # PHP-FPM
            location ~ \.php$ {
                    include         fastcgi_params;
                    fastcgi_pass    unix:/var/run/php5-fpm.sock;
                    fastcgi_index   index.php;
            }
    
            # UserDir
            location ~ ^/~(.+?)(/.*)?$ {
                    alias           /home/$1/www$2;
                    autoindex       on;
            }
    }
    

    Accessing http://sid0.local/~dummy works, it lists the content of /home/dummy/www/ and I can access files there. Underneath ~dummy/bar is a file called index.php - yet, accessing http://sid0.local/~dummy/bar/ brings the dreaded "File not found." error (not a 404). The error.log has:

    2014/04/30 23:07:44 [error] 4237#0: *9 FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream, client: 192.168.0.103, server: sid0.local, request: "GET /~dummy/bar/ HTTP/1.1", upstream: "fastcgi://unix:/var/run/php5-fpm.sock:", host: "sid0.local:8083"
    

    Now, many people seem to have this problem and some of them are even posting solutions, like making sure that SCRIPT_FILENAME is set to request_filename - but this is already the case (it's set in fastcgi_params).

    However, running strace(1) against the nginx process gives (edited for readability):

    4045  connect(16, {sa_family=AF_FILE, path="/var/run/php5-fpm.sock"}, 110) = 0
    4045  writev(16, [{"\1\1\0\1\0\10\0\0\0\1\0\0\0\0\0\0\1\4\0\1\3T\4\0\f\0
          QUERY_STRING\16\3
          REQUEST_METHODGET\f\0
          CONTENT_TYPE\16\0
          CONTENT_LENGTH\0170
          SCRIPT_FILENAME/data/www/sid0.local/~dummy/bar/index.php\v\25
          SCRIPT_NAME/~dummy/bar/index.php\v\f
          REQUEST_URI/~dummy/bar/\f\25
          DOCUMENT_URI/~dummy/bar/index.php\r\33
          DOCUMENT_ROOT/data/www/sid0.local
    

    As you can see, SCRIPT_FILENAME is NOT request_filename but instead document_root+fastcgi_script_name - hence the 404, of course.

    So, I guess my question is: why is my SCRIPT_FILENAME mangled (I even set it to fastcgi_script_name, no luck) and how do I get PHP scripts inside a UserDir running?

    • Alexey Ten
      Alexey Ten about 10 years
      nginx locations are exclusive. If your request ends up in location for PHP files, nginx does not look for other matching locations therefore nginx does not know anything about alias directive in userDir location.
    • ckujau
      ckujau about 10 years
      Thanks. But when I've put the PHP part inside the UserDir part, it didn't change anything, SCRIPT_FILENAME was still mangled.
  • ckujau
    ckujau about 10 years
    Wow, that's magic indeed. I'd have hoped that this could be done w/o rewrite tricks - it's only a userdir and rewrite rules (and if) always seem so fragile. Also, I cannot set autoindex inside the userdir anymore. But otherwise, this works, thanks!
  • ckujau
    ckujau almost 10 years
    Thanks for the update. Sorry, it took me a while to find time to test this. Unfortunately, this isn't working here, I'm getting 404 errors when trying to access ~dummy/bar/index.php. I shall take this to an nginx mailinglist. Thanks for your input though!