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 trying to write an Nginx config with the following semantics, expressed in hopefully-readable psuedo-config:

location /dir1/ /dir2/ {
  if (matches a .php file) {
    serve with php
  } else if (matches a non-.php file) {
    serve as static content
  } else {
    404
  }
} else {
  serve with /index.php
}

How do I do this? I have a decent sense of Apache configuration, but I don't have a good enough grasp on Nginx to sort out the semantics of try_files and location matching and internal redirects and stuff. Any tips on how I should structure this?

For reference, the mod_rewrite-based configuration I'm currently using with Apache is

# Any URL not corresponding to a directory gets rewritten to index.php
RewriteCond $1 !^dir1/
RewriteCond $1 !^dir2/
RewriteRule ^(.*)$ ./index.php/$1 [L,QSA]

# Allow access to files in any of the directories
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^(.*)$ - [L]

# If either step above resulted in a php file, process it
<FilesMatch "\.php$">
    SetHandler application/x-httpd-php
</FilesMatch>
share|improve this question

2 Answers 2

You could simplify this (NGINX is all about being simple) by using the try_files directive. This allows you to cascade scenarios in one statement.

In your case since you want to redirect any directory call to index.php, you can have it try the specific file first, and then index.php:

  try_files $uri index.php;

Also I would adjust your location detection for php:

  location ~ ^(.+\.php)(.*)$ {

     [your fastcgi block here]

  }

Doing this, you don't need a "location /" entry. Your complete config for this site would be something like this (I am using php-fpm, your php location may vary):

server {

     server_name www.example.com;
     root /path/to/docroot;

     access_log /path/to/logfile;
     error_log /path/to/errorlog;

     index index.php;

     try_files $uri index.php;

     location ~ ^(.+\.php)(.*)$ {

            include fastcgi_params;
            fastcgi_index index.php;
            fastcgi_buffers 8 16k; 
            fastcgi_buffer_size 32k;                                         
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;   
            fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;                    

      }

}
share|improve this answer
    
How do I extend that to handle restricting static files to /{dir1,dir2} and restricting php to /{dir1,dir2}/ and index.php? I think it's the last part I'm having particular trouble with. I guess I could do it with two php/fastcgi blocks, but that seems suboptimal. –  jon May 19 '12 at 16:25
    
Oh sorry I misread your question then. You wouldn't need separate php blocks but you would have to break out each location including the root: location ^ /dir1/ { try_files $uri /index.php; } location ^ /dir2/ { try_files $uri /index.php; } location / { error_page 404 /index.php; try_files index.php; } –  Brian P May 19 '12 at 18:20
    
@BrianP Welcome to ServerFault and thanks for the answer. You should rather edit your answer so that it fully answers the question instead of continuing it in a comment, so that future readers can easily find the solution. –  mgorven May 19 '12 at 19:08

It's better to get a basic understanding of how nginx works before writing a config for it. Read howtos and examples from http://wiki.nginx.org/Configuration

Nginx config is not about if-then-else. There's distinct stages of processing each request, and you just define what are parameters of each stage.

You can make use of this template:

location ~ \.php$ {
  fastcgi_pass    unix:/var/run/php/fcgi;
  fastcgi_index   index.php;
  fastcgi_param  SCRIPT_FILENAME  /var/www/localhost/htdocs$fastcgi_script_name;
  include /etc/nginx/fastcgi_params;
}

location / {
   root /some/folder;
   error_page 404 /index.php
}
share|improve this answer
    
I've read most of the pages linked to in the first two sections of that page, the reference documentation for both CoreModule and HttpCoreModule, and a number of other s-f questions. I think I could translate the psuedo-config (if-then-elses) in my question to nginx trivially by using if, but IfIsEvil advises against it; hence my question. If you could point me to definitive documentation on what Nginx's processing stages are, I'd be much obliged. –  jon May 19 '12 at 6:10

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.