Drupal nginx configuration. PHP files being downloaded
I created a really long guide on how to set-up Perusio's nginx config. (EDIT: We turned it into a wiki so anyone can add. Also I forgot to link.) The config itself is excellent and well worth a look. If you couldn't get it working before, hopefully my guide will help.

Ok so here we go.

When you use either of the following expressions for a location block in nginx:


= 
^~


Then it will stop searching for more matches immediately after it hits one of them. It checks = with priority then all the other 3 expressions at the same time in the order of the nginx config file.

So in my case it was finding ^~ on update.php and install.php and stopping the search immediately. This means it never runs php processing on the files and so they're downloaded instead of opening. Adding the php logic to the location blocks, means nginx then runs the php as well as blocking them for all bar me.

      location ~ \.php$ {
        try_files $uri =404;
        include /etc/nginx/fastcgi_params;
        if ($uri !~ "^/default/files/") {
            fastcgi_pass 127.0.0.1:9000;
        }
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME /srv/www/website/public$fastcgi_script_name;
      }          

      location = /update.php {
          allow 127.0.0.1;
          deny all;
          fastcgi_param SCRIPT_FILENAME /srv/www/mysite/public$fastcgi_script_name;
          fastcgi_pass 127.0.0.1:9000;
          include /etc/nginx/fastcgi_params;
      }

      location = /install.php {
            allow 127.0.0.1;
            deny all;
            fastcgi_param SCRIPT_FILENAME /srv/www/mysite/public$fastcgi_script_name;
            fastcgi_pass 127.0.0.1:9000;
            include /etc/nginx/fastcgi_params;
      }


You might note that I've also changed to = from ^~. This is because = is always picked with priority and prevents me from accidentally breaking this later. Choose = and avoid the difficulties I'm about to mention below.

Another useful point: I don't think nginx can ever match two location blocks. It'll pick the more specific one.

Stuff that doesn't quite make sense

Lastly I don't quite understand the priority order of the 3 expressions. If I put *~ in the update block in the example above, it chooses the php block (which has ~), apparently case sensitive overrules the more specific match? This seems weird and isn't mentioned in the docs. If I use ^~ it works as expected. 

If anyone has found a great explanation of location I'd love to see it because I'm not sure the docs make perfect sense.