4

I have a fresh install of Ubuntu 14.04 server. I have installed nginx, php, etc....

server {
  listen 80;
  listen [::]:80;

  server_name testone.local;

  root /var/www/htmlone;
  index index.html;

  # pass the PHP scripts to FastCGI server listening on the php-fpm socket
  location ~ \.php$ {
    try_files $uri =404;
    fastcgi_pass unix:/var/run/php5-fpm.sock;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;
  }

  location /alias {
    alias  /var/www/htmlalias;
    location ~ \.php$ {
      try_files $uri =404;
      fastcgi_pass unix:/var/run/php5-fpm.sock;
      fastcgi_index index.php;
      fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
      include fastcgi_params;
    }
  }
}

If I use a simple php script in /var/www/htmlone php executes as expected. If I use the same script in /var/www/htmlalias it does not execute as expected. If I put an HTML script in /var/www/htmlalias it does however display as expected, so the alias acts as an alias, but does not execute php files, but php works in the primary root directory.

I have found on many serverfault questions that this general setup should work yet it is not. Does anyone see anything that I may be doing wrong? I see no messages in the error log.

I should add this is for nginx version: nginx/1.8.0

3 Answers 3

6
+50

The issue you're having is actually a long-standing bug that was filed 3 years ago which causes alias and try_files to not really work together.

On the bug page there is a workaround by Luke Howell, which goes as follows:

location /api { ## URL string to use for api ##
    alias /home/api/site_files/; ## Site root for api code ##

    ## Check for file existing and if there, stop ##
    if (-f $request_filename) {
        break;
    }

    ## Check for file existing and if there, stop ##
    if (-d $request_filename) {
        break;
    }

    ## If we get here then there is no file or directory matching request_filename ##
    rewrite (.*) /api/index.php?$query_string;

    ## Normal php block for processing ##
    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
    }
}

Do note though that as far as nginx is concerned, IF is evil and should be avoided if possible.

1
  • awesome, I had to add an api directory within the alias root, which is annoying, but fixes the overall issue. Now just to get it to work with Symfony, thanks.
    – thenetimp
    Jun 14, 2015 at 13:11
2

From my testing of the above configuration it is the presence of

try_files $uri =404;

inside the nested alias php location that causes the problem. With it, nginx checks for "/var/www/htmlalias/alias/index.php" (note the addition of the 'alias' plus the uri), finds it doesn't exist, and then returns a 404. Removing that try_files stops it looking for this file on disk first, and passes the request directly to fastcgi, which then finds the correct file from SCRIPT_FILENAME.

If you want non-existent PHP files to give a 404 rather than a PHP error, then the following works:

  location /alias {
    alias  /var/www/htmlalias;
    location ~ /([^/]+\.php)$ {
      try_files /$1 =404;
      fastcgi_pass unix:/var/run/php5-fpm.sock;
      fastcgi_index index.php;
      include fastcgi_params;
      fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
  }

First the regex captures the fill filename of the php file (e.g. foo.php) as $1. try_files then checks, relative to the current alias, if that file exists, returning a 404 if it doesn't.

We then have to override the default SCRIPT_FILENAME as defined in fastcgi_params by redefining it after the include, because $request_filename will, for some reason I don't understand, be entirely the wrong thing (literally /index.php).

0

This is the way I solved it:

default server configuration (without alias), in your example:

server {
  listen 80;
  listen [::]:80;

  server_name testone.local;

  root /var/www/htmlone;
  index index.html;

  # pass the PHP scripts to FastCGI server listening on the php-fpm socket
  location ~ \.php$ {
    try_files $uri =404;
    fastcgi_pass unix:/var/run/php5-fpm.sock;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;
  }
}

and from the command line, create a symbolic link under /var/www/htmlone:

ln -s /var/www/htmlalias /var/www/htmlone/alias

You must log in to answer this question.

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