2

Problem

I'm trying to configure my nginx server. I've been building from the default rather than jumping straight into Perusio's because I don't understand a lot of it.

I'm trying to deny access or require authentication to access update.php, install.php and apc.php.

I think they're locked down but on navigating to the file it's downloaded instead of being run.

For example after entering my authentication for apc.php it downloads to my computer. The same thing happens for update.php.

I've taken a lot of the configuration from another excellent post on here: Is there a common nginx conf for Drupal 7 sites?

My Server Config

server {
      listen 8080;
        server_name website website.com;
        access_log /srv/www/website/logs/access.log;
        error_log /srv/www/website/logs/error.log;
        root /srv/www/website/public;


        location / {
           index index.php index.html index.htm;
           error_page 404 = @drupal;
        }

        ##drupal rewrite rules
        location @drupal {
            rewrite ^(.*)$ /index.php?q=$1 last;
        }

        ##secure private file directory
        location ~* /privatefiles {
             internal;
        }

        ##Add headers to advagg
        location ~* files/advagg_(?:css|js)/ {
            access_log off;
            expires    max;
            add_header ETag "";
            add_header Cache-Control "max-age=290304000, no-transform, public";
            add_header Last-Modified "Wed, 20 Jan 1988 04:20:42 GMT";
            try_files  $uri @drupal;
        }

        ## Replicate the Apache <FilesMatch> directive of Drupal standard
        ## .htaccess. Disable access to any code files. Return a 404 to curtail
        ## information disclosure. Hide also the text files.
        location ~* ^(?:.+\.(?:htaccess|make|txt|log|engine|inc|info|install|module|profile|po|sh|.*sql|theme|tpl(?:\.php)?|xtmpl)|code-style\.pl|/Entries.*|/Repository|/Root|/Tag|/Template)$ {
            return 404;
        }

        location ~ \..*/.*\.php$ {
            return 403;
        }

        ##deny access to update and install for everyone except the server
        location ^~ /update.php {
            allow 127.0.0.1;
            deny all;
        }

        location ^~ /install.php {
            allow 127.0.0.1;
            deny all;
        }


        ##authentication required to access apc.php
        location ^~ /apc.php {
            auth_basic "Restricted access"; #realm
            auth_basic_user_file /srv/www/website/public/.htpasswd-users;
        }

        ##rules for running php
        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;
         }


 }
  • 1
    I just wanted to mention this: wiki.nginx.org/Drupal – Mołot Nov 26 '13 at 15:26
  • I've never seen try_files $uri =404; in the FPM config before, any idea why you're using that? Out of interest what problems are you having with Perusio's config? I had to comment a few lines locally for modules that hadn't been compiled with nginx (the audio filter, upload progress, etc), but it works like a dream – Clive Nov 26 '13 at 16:05
  • 1
    @Clive It's a fix for a nginx security hole explained here. I couldn't actually get it to serve anything, but I decided to give it another go now and I'm currently stuck with the error [emerg] no port in upstream "www0". I used the Perusio FPM config as well and I can't work out what's broken. – Dominic Woodman Nov 26 '13 at 18:31
  • Interesting, thanks for that link. Any chance you've got xdebug listening on 9000? I know that one threw me for a while – Clive Nov 26 '13 at 18:41
  • @Clive Nope unfortunately not. A couple months ago I spent ages getting xhprof to work, then realized I wasn't experienced enough to use it... so I've left the profilers be for a bit. – Dominic Woodman Nov 26 '13 at 19:23
2
+100

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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