Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

I'm working on a migration of several sites from Apache to Nginx and I've bumped into a snag on one that has a virtual directory (alias). The alias itself works fine and the proper file gets served, but PHP isn't proxied properly.

server {
  listen      443 default_server ssl;
  server_name dev.myproject.mydomain.net;
  root        /opt/dev/project-root;
  index       index.php;

  ssl_certificate      /etc/ssl/certs/server.crt;
  ssl_certificate_key  /etc/ssl/certs/server.pem;

  access_log /var/log/nginx/vh.project.access.log;
  error_log  /var/log/nginx/vh.project.error.log;

  location ~ ^/alias_name/(.*) {
    alias /opt/dev/project-root/www/$1;

    location ~ ^/alias_name/(.+\.php)$ {
      alias /opt/dev/project-root/www/$1;
      include /etc/nginx/conf/php;
    }
  }

  location ~ \.php$ {
    include /etc/nginx/conf/php;
  }
}

I haven't tried this yet, but I suspect that if I copied the content of the \.php$ location block into the alias block things would work fine, but the engineer in me loathes replication. Is there any way to avoid that (assuming it would work at all)? Intuitively, it seems like both location blocks would be evaluated.

I could also move the php block out to a separate file and include it, I'm sure.

Any advice on the best (read: most nginx-y) way to handle this would be much appreciated.

UPDATE

Based on Kyle's answer, I've moved the PHP proxy out to a separate conf/ directory. The conf/php file has this code:

location ~ \.php$ {
  fastcgi_split_path_info ^(.+\.php)(/.+)$;
  fastcgi_pass 127.0.0.1:9000;
  fastcgi_index index.php;
  include fastcgi_params;
}

My alias location block now looks like this:

location ~ ^/alias_name/(.*) {
  alias /opt/dev/path/to/aliased/$1;
  include /etc/nginx/conf/php;
}

If I drop a static HTML file at that alias, it renders fine. A PHP file returns a 404.

UPDATE

With @quanta's help in the comments, I've managed to get PHP serving properly and I've updated the alias location block with the config. Unfortunately, not static content isn't rendering if the URL includes the alias. Today isn't my day.

share|improve this question
    
serverfault.com/a/417424/59925 –  quanta Aug 17 '12 at 14:52
    
Thanks, @quanta. Seems kind of ugly and repetitive, but at this point I'll pretty much take anything that works. :-) –  Rob Wilkerson Aug 17 '12 at 15:00
    
Just put common directives into a separate file: fastcgi_split_path_info, fastcgi_pass, fastcgi_index. Don't put the whole location block because 1. the nested location must begins with ^/alias_name and 2. fastcgi_param SCRIPT_FILENAME must be different. –  quanta Aug 17 '12 at 15:06
    
Damn, I hadn't even noticed the different SCRIPT_FILENAME. Using fastcgi_param SCRIPT_FILENAME $request_filename; won't take the alias in to account? –  Rob Wilkerson Aug 17 '12 at 15:12
    
@quanta - Looks like all is well (without having to specify a different SCRIPT_FILENAME. If you'll move your comment to an answer I'll mark it. Thanks for your help. –  Rob Wilkerson Aug 17 '12 at 15:25
show 2 more comments

2 Answers

Okay, so I may have found my own answer by brute force trial and error once I incorporated @quanta's info (see comments above). This virtual host server block seems to serve PHP and static content properly:

server {
  listen      443 default_server ssl;
  server_name dev.myproject.mydomain.net;
  root        /opt/dev/project-root;
  index       index.php;

  ssl_certificate      /etc/ssl/certs/server.crt;
  ssl_certificate_key  /etc/ssl/certs/server.pem;

  access_log /var/log/nginx/myproject.dev.access.log;
  error_log  /var/log/nginx/myproject.dev.error.log;

  location ~ ^/alias_name/(.+\.php)$ {
    alias /opt/dev/project-root/www/$1;
    include /etc/nginx/conf/php;
  }
  location ~ ^/alias_name/(.*) {
    alias /opt/dev/project-root/www/$1;
  }

  location ~ \.php$ {
    include /etc/nginx/conf/php;
  }
}

I don't know whether I'll bump into problems and I can't say that I fully understand the difference, but simply removing the nested location blocks seems to have done the trick.

share|improve this answer
add comment

You could put the php block in an external include and then do this, i am not 100% on the include command but this should work.

server {
  listen      443 default_server ssl;
  server_name dev.myproject.mydomain.net;
  root        /opt/dev/project-root;
  index       index.php;

  ssl_certificate      /etc/ssl/certs/server.crt;
  ssl_certificate_key  /etc/ssl/certs/server.pem;

  access_log /var/log/nginx/vh.project.access.log;
  error_log  /var/log/nginx/vh.project.error.log;

  location ~ ^/alias_name/(.*) {
    alias /opt/dev/path/to/aliased/$1;
    include php.inc
  }

  # include defualt location
include php.inc
}

php.inc

  # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
  #
  location ~ \.php$ {
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_pass 127.0.0.1:9000;
    fastcgi_index index.php;
    include fastcgi_params;
  }
share|improve this answer
    
Thanks, Kyle. Here's what I don't get: I've made this change and, with the include, I get a 404. If I just comment out the include, the page renders (found), but with the PHP unevaluated as before. –  Rob Wilkerson Aug 17 '12 at 13:44
    
This has to be a problem with my alias location. If I point my root to the alias location (/opt/dev/path/to/aliased) and load the same url without the alias component, I get evaluated PHP. Argh. –  Rob Wilkerson Aug 17 '12 at 13:54
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.