Server Fault is a question and answer site for system and network administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

How it is possible to deny access to a folder, but except some subfolders in it from "deny"?

I tried something like this (in this order):

#this subfolder shouldn't be denied and php scripts inside should be executable

location ~ /data/public { allow all; }

#this folder contains many subfolders that should be denied from public access

location ~ /data { deny all; return 404; }

... which doesn't work correctly. Files inside the /data/public folder are accessible (all other in /data are denied as it should be), but PHP files are not executed anymore in the /data/public folder (if I don't add these restrictions, the PHP files are executable).

What is wrong? How can it be correct? I think theres a better way to do it.

It would be very nice if anyone can help me with this :).

Thanks, but PHP files are still not executed in the /data/public/ folder, like a simple

<? echo "test"; ?>

It gives you this file as a download (without the "deny"-configuration above, the php files are working well).

My PHP Configuration:

location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;

PHP files in all other directories outside /data/ are working... (other subfolders as well).

share|improve this question
up vote 3 down vote accepted

The reasons php files aren't being processed is that when it hits the /data/public/ location it stops there and doesn't know how to process php files.

Try putting your php location in another file called php.conf and include that file in your server block and in the /data/public/ block. So your config will look something like

server {
    location ^~ /data/public/ {
        allow all;
        try_files $uri $uri/ /index.php?args;
        # include to avoid writing it twice..
        include php.conf

    location ^~ /data/ { 
        deny all; 

    # .....
    # Some other config blocks
    # .....

    # Put this line instead of the php config block to avoid writing the php part twice
    include php.conf

and the php.conf file will look (in your case) like this:

location ~ \.php$ {
     fastcgi_split_path_info ^(.+\.php)(/.+)$;
     fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
     fastcgi_index index.php;
     include fastcgi_params;
share|improve this answer
Thanks! This one is working :). – carrot Nov 20 '12 at 21:49
you're missing a "s" at try_files – peteroak Aug 6 '15 at 6:13
Thanks! Updated it. – jagsler Aug 6 '15 at 7:13

The location rule should look like this.

location ^~ /data/                { deny all; }


location ^~ /data/public/               { allow all; }

nginx location rules are as follows

To find a location matching a given request, nginx first checks locations defined using the prefix strings (prefix locations). Among them, the most specific one is searched. Then regular expressions are checked, in the order of their appearance in a configuration file. A search of regular expressions terminates on the first match, and the corresponding configuration is used. If no match with a regular expression is found then a configuration of the most specific prefix location is used.

nginx access rules are as follow

"Access rules are checked according to the order of their declaration. The first rule that matches a particular address or set of addresses is the one that is obeyed."

so a working configuration should look something like

location ^~ /data/public/               { allow all; }
location ^~ /data/ { deny all; }

By using deny all, it should return a 403 Forbidden rather than a 404.

This should allow the public directory to be accessed and processed and anything else blocked. I had this same issue when I was working on my nginx configuration for Magento but I figured it out by the ^~ trick.

share|improve this answer
While suggested configuration is correct, the "Also remember..." part is completely wrong. Order matters only for regexp locations, for normal locations most specific match is used (and order doesn't matter). For details see – Maxim Dounin Nov 19 '12 at 20:33
Updated answer to include location and access module rules – Vern Burton Nov 19 '12 at 22:27

Your Answer


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.