nginx + php in a user's public_html

I have nginx configured to load from /home/user/publichtml when someone goes to mysite.com/~user. The problem is that this only works for html files, it wants to download php files as a BIN file. PHP works fine for the main site using php-fpm. Here's the configuration for my user's publichtml:

location ~ ^/~(.+?)(/.*)?$ {
alias /home/$1/public_html/$2;
autoindex on;
}

Here is for the main site's php:

location ~ \.php$ {
include /etc/nginx/fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /srv/www/youdolinux.com/html$fastcgi_script_name;
}

I have tried doing a copy of the publichtml config and including ".php" and ".php$" in every conceivable part of the location line, but nothing works when I restart nginx. There's no error when restarting nginx, but it still thinks php files loaded from my user's publichtml are BIN files.

(BTW, I'm the only user on my Linode who actually uses php in my public_html dir, though I trust the other two users enough to let them if they want to)

8 Replies

Tried an absolute path and not a tilde, in the second code block?

The second code block isn't the problem. That one is for the main site, and works fine as is. I'm having issues with php in the user's public_html. I only included the second code block so that nobody could say that I wasn't providing all needed info (or at least, the info that my simple mind could conceive of as being needed for this situation)..

Check what user php-fpm is running as and can that user read files in the users public_html.

When there are multiple "location" directives with regular expressions in them, nginx will stop looking after it finds the first match. This probably means that your PHP-specific "location" directive is never being evaluated in the first place.

You can use PHP with arbitrary subdomains: see here. But I don't think it will work with your tilde-is-userdir scheme.

@Eamonn:

Check what user php-fpm is running as and can that user read files in the users public_html.

I didn't think of permissions :-)

I'm going to set the group instead, though: since /home/piki/public_html rightfully belongs to user piki and need to be read by php-fpm, it makes more sense to leave user ownership to piki so he can still modify the files and set group ownership to www-data for reading by php-fpm :-)

When there are multiple "location" directives with regular expressions in them, nginx will stop looking after it finds the first match. This probably means that your PHP-specific "location" directive is never being evaluated in the first place. 

You can use PHP with arbitrary subdomains: see here. But I don't think it will work with your tilde-is-userdir scheme.

Just at a quick glance, that looks more like it's for configuring several subdomains under the same server block. Just to avoid being redundant, I don't want the userdir load for each subdomain, just for the main one.

That does give me an idea on what to do with my location drectives to make it work.

I'd hate to resurrect an old thread, but I have the same issue. The tilde location string takes precedence over the .php one, and I was wondering what a clean solution would be…

Wow. I should learn to search, better. I just posted the same problem: http://forum.linode.com/viewtopic.php?t=8717

Seems like a common enough problem, but no one has the answer. Hmm.

I'm not much for narco'ing threads, but I finally got around to figuring out the solution after all this time, so I decided to post the solution for those who are searching for it. Here is the config (make sure you edit according to your needs, or copy the sections you need):

server {
    listen 80;
    server_name yoursite.com;
    root /srv/http/yoursite.com/public_html;
    index index.php index.html index.htm;
    # Not really needed, but in my experience it seems to help performance
    try_files $uri $uri/ /;

    # server-side includes
    # Allows the HTML include statements, set off if you don't need this
    ssi on;

    # Don't allow access to dotfiles (such as .htaccess)
    location ~ /\. {
        deny all;
    }

    # This MUST appear above both the normal userdir and php location blocks
    #     else it will either attempt to load from your main (non-user) site
    #          or ask vistors to download PHP files (which can be bad for security)
    location ~ ^/~(.+?)(/.+\.php)$ {
        alias /home/$1/public_html$2;
        autoindex on;

        # default fastcgi settings
        include fastcgi_params;

        # A bit of added security -- not full proof, but can help
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini

        fastcgi_pass unix:/run/php-fpm.sock;
        fastcgi_index index.php;
    }

    # These next two location blocks can be switched without issue, as long
    #     as you keep them both BELOW the location block above!!!

    location ~ ^/~(.+?)(/.*)?$ {
        alias /home/$1/public_html$2;
        autoindex on;
    }

    location ~* \.php$ {
        # default fastcgi settings
        include fastcgi_params;

        # A bit of added security -- not full proof, but can help
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini

        fastcgi_pass unix:/run/php-fpm.sock;
        fastcgi_index index.php;
    }
}

My issue was that I had placed the userdir, userdir php, and normal php in the wrong order. I had my normal php location above my userdir and userdir php locations. Visiting mysite.com/~myuser would first match my non-php userdir location and then see index.php, causing it to search the location blocks again and re-match it against the normal php location. Since the normal php location looks in my main site (not my userdir), it would try to load the file from my main site.

With the order in the config above, mysite.com/~myuser will first match the userdir location (the one without the php), then if it sees index.php it will re-search the location blocks and re-match against the userdir php file.

The reason the order is important is because, as hybinet points it, it stop as soon as it finds a location block that matches the URL. This didn't immediately ocur to me as being a problem – I was thinking that the userdir location would take precedence over the php location by virtue of the fact that it has ~myser in the URL (regardless of whether I'm using .html or .php), but nginx seems not to see it that way. It seems not to care the order that the elements of the URL are in, only the those elements are there (in other words, it doesn't care that ~myuser comes before index.php, it cares only that both ~myuser and index.php are in the URL, and matches whichever comes first in the vhost config).

Reply

Please enter an answer
Tips:

You can mention users to notify them: @username

You can use Markdown to format your question. For more examples see the Markdown Cheatsheet.

> I’m a blockquote.

I’m a blockquote.

[I'm a link] (https://www.google.com)

I'm a link

**I am bold** I am bold

*I am italicized* I am italicized

Community Code of Conduct