Question

I'm struggling to understand how to control rewrites to PHP scripts when the location blocks that do the rewrites require different roots.

Here's the simplified example. My catch-all front controller must be in the web root, but the firewall.php script must not be.

The purpose of this is to provide gated access to download files not under the root.

server {

    # Requests for media forced through firewall script outside web root
    # /path/to/secure-area/firewall.php
    #
    location ^~ /downloads/ {
       root /path/to/secure-area;
       rewrite ^/.+$ /firewall.php last;
    }

    # Regular requests bootstrap front controller under web-root
    # /path/to/web-root/index.php;
    #
    location / {
        root /path/to/web-root;
        index index.php
        if ( -e $request_filename ) {
            break;
        }
        rewrite ^.+$ /index.php last;
    }

    # Execute PHP via php-fpm
    # rewrites hitting this are not mapping request_filename properly
    #
    location ~ \.php$ {
       if ( !-f $request_filename ) {
         return 404;
       }
       include /usr/local/nginx/conf/fastcgi_params;
       fastcgi_pass   unix:/tmp/php.sock;
       fastcgi_index  index.php;
    }
}

The obvious solution is having a common root, but this is not possible in my situation. I cannot place the secure location under the web root and the web root must stay as-is.

It looks as if the root directive is only effective within the location block that defines it. The rewrites are individually working fine, but when the ~ \.php block is hit, the root is lost.

I'm obviously doing it wrong, so how should I achieve this?

No correct solution

OTHER TIPS

Untested, but something like this ought to help you. It uses the http://wiki.nginx.org/XSendfile to serve the protected content from a different root. Also uses try_files which is a much better pattern for Front Controllers.

    server {

    # More here: http://wiki.nginx.org/XSendfile
    #
    # To serve /downloads/some.zip
    # get php to set the http header:
    #
    # X-Accel-Redirect: /downloads/some.zip
    #
    # and then the file /path/to/secure-area/downloads/some.zip
    # will be sent by nginx
    location /downloads/ {
      internal;
      root   /path/to/secure-area;
    }        

    location / {
        root /path/to/web-root;
        index index.php
        try_files $uri $uri/ /index.php;
    }

    # make sure you read http://wiki.nginx.org/Pitfalls
    location ~* \.php$ {
      try_files $uri =404;
      fastcgi_pass   unix:/tmp/php.sock;
      fastcgi_index  index.php;
      include /usr/local/nginx/conf/fastcgi_params;
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top