4

I am converting a legacy Apache server to Nginx and do not have the luxury of changing URL's or rearranging the filesystem.

Is it possible to use nested location{} blocks in the Nginx configuration to tell it to feed the .php files in an aliased directory to fastcgi while serving static content normally?

Similar configuration to what fails me:

server {
  listen 80;

  location / {
    index  index.html;
  }

  location /foosite/ {
    alias  /var/aliases/foo;
    location ~ \.php$ {
      include fastcgi_params;
      fastcgi_param   SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
  }
}

Requests for /foosite/static.jpg are served fine, but nginx appears to garble the path to any .php files when attempting to dispatch them to fastcgi.

allaryin
  • 323
  • 4
  • 10

3 Answers3

6

The solution provided here is not a solution. And it's not correct anymore. Using Lucid (10.4) I was able to use this solution. The problem with womble's solution is that it doesn't set the DOCUMENT_ROOT parameter properly; rather, it includes the script name in the document_root.

This seems to work OK.

location /foosite {
    alias /home/foosite/www/;
    index index.php index.html index.htm;

    location ~ /foosite/(.*\.php)$ {
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$1;
        include /etc/nginx/fastcgi_params;            
    }                                                 
}

Using nginx/0.7.65

dcurtis
  • 176
  • 1
  • 3
  • Thanks. I'm not having this problem any more, but I am in the middle of a new deployment this week so I'l give it a whirl just to confirm ;) – allaryin May 24 '12 at 15:59
1

The "garbling" you talk about is, as far as I can tell, a bug in nginx relating to nested location blocks (or maybe aliases in location blocks that do regex-based matching without a capture... I'm not sure). What I was able to do, however, was fairly straightforward.
First, you can put all your fastcgi parameters, including the fastcgi_pass line and fastcgi_param SCRIPT_FILENAME $request_filename into a separate file for inclusion in the relevant parts of the site. I put mine in /etc/nginx/fragments/php.

Then, for /foosite, you need two location blocks, like so:

location /foosite {
    alias /var/aliases/foo;
}

location /foosite(.*\.php)$ {
    alias /var/aliases/foo$1;
    include /etc/nginx/fragments/php;
}

One thing to be wary of here -- unlike "regular" location blocks, it appears that regex-based matching runs in the order specified in the config file (not longest-match-first, as appears to be the case for non-regex location blocks). So, if you're doing a site-specific PHP location, as well as a generic "all-site" PHP handler (location ~ \.php$) then you'll need to put the generic "all-site" handler last in the server block, or all hell will break loose.

Yeah, this sucks, and if I get the motivation up I might try and work out exactly what's going wrong with the nested case (the config parser doesn't barf on it, so I suspect it's supposed to work but nobody actually uses it, so it's buggy).

womble
  • 96,255
  • 29
  • 175
  • 230
0

AFAIK, you cannot use nested blocks.

Try something like the following instead.

location / {
  root /var/www;
  access_log off;

  index index.php index.html;
  expires 1d;

  try_files $uri $uri/ /index.php?q=$uri;
}

location ~ \.php$ {
  fastcgi_pass   127.0.0.1:9000;
  fastcgi_index  index.php;
  fastcgi_buffer_size 128k;
  fastcgi_buffers 4 256k;
  fastcgi_param  SCRIPT_FILENAME  /var/www$fastcgi_script_name;
  include        /usr/local/nginx/conf/fastcgi_params;
}

You can modify the second block to be something like

location ~ /foosite/.*php$

(needs testing)

Jauder Ho
  • 5,507
  • 2
  • 19
  • 17