3

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.

7
  • serverfault.com/a/417424/59925
    – quanta
    Aug 17, 2012 at 14:52
  • Thanks, @quanta. Seems kind of ugly and repetitive, but at this point I'll pretty much take anything that works. :-) Aug 17, 2012 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, 2012 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? Aug 17, 2012 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. Aug 17, 2012 at 15:25

2 Answers 2

2

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.

0

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;
  }
2
  • 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. Aug 17, 2012 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. Aug 17, 2012 at 13:54

You must log in to answer this question.

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