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.

After following the Pitfalls guide I am trying to cleanup my URL rewrites using the try_files directive. However, when using this on my install of Nginx 0.8.54-4 (from dotdeb) I get a prompt to download a BIN file when trying to access the site (which contains the source of the index.php PHP script). So are any of these directives not compatible with my version of nginx or what is wrong with this vhost?

server {
    listen 80;
    server_name site.loc;
    root /home/user/www/site.loc/docroot;
    index index.html index.php;

    location / {
        try_files $uri $uri/ @runphp;
    }

    # Pass all .php files to PHP-FastCGI
    location @runphp {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass 127.0.0.1:9000;
    }
}

Also, is this even the best way to do this? My original (working) config looked like this:

server {
    listen 80;
    server_name site.loc;
    root /home/user/www/site.loc/docroot;
    index index.html index.php;

    # Route all requests for non-existent files to index.php
    if (!-e $request_filename) {
        rewrite ^ /index.php last;
    }

    # Pass PHP scripts to php-fastcgi listening on port 9000
    location ~ \.php {
        include fastcgi_params;
        fastcgi_pass 127.0.0.1:9000;
    }
}

Update: The following rewrite works fine - I had to test with wget though since the browser caches responses. I also updated to Nginx 1.0.5 (default in Ubuntu 11.10).

server {
    listen 80;
    server_name site.loc;
    root /home/user/www/site.loc;
    index index.html index.php;

    # Directives to send expires headers and turn off 404 error logging.
    location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
        expires 24h;
        log_not_found off;
    }

    # Route all requests for non-existent files to index.php
    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }

    # Pass PHP scripts to php-fastcgi listening on port 9000
    location ~ \.php$ {

        # Zero-day exploit defense.
        # http://forum.nginx.org/read.php?2,88845,page=3
        # Won't work properly (404 error) if the file is not stored on 
        # this server,  which is entirely possible with php-fpm/php-fcgi.
        # Comment the 'try_files' line out if you set up php-fpm/php-fcgi
        # on another machine.  And then cross your fingers that you won't get hacked.
        try_files $uri =404;

        include fastcgi_params;
        fastcgi_pass 127.0.0.1:9000;
    }

}
share|improve this question
add comment

1 Answer 1

up vote 2 down vote accepted

Your config is wrong. Because PHP cannot parsed the non-existent fallback URI @runphp, so, you got a download prompt.

Try something like this:

location / {
    try_files $uri $uri/ /index.php;
}

location ~ \.php$ {
    include fastcgi.conf;
    fastcgi_pass 127.0.0.1:9000;
}
share|improve this answer
1  
There's one subtle difference between the original rewrite and a try_files fallback. The rewrite preserves query args by default and try_files fallbacks don't, so the fallback should be /index.php$is_args$args to behave exactly the same as the original if/rewrite. –  kolbyjack Oct 14 '11 at 18:13
    
@quanta I tried what you just posted but it doesn't work. I updated my question with the new block. –  Xeoncross Oct 17 '11 at 16:28
    
Notice that I used include fastcgi.conf instead of include fastcgi_params. If you didn't define SCRIPT_FILENAME in fastcgi_params, you must do it in PHP location. –  quanta Oct 17 '11 at 16:34
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.