Denying folder in Nginx causing PHP-FPM to not take precedence
The title says it all, but I have a very interesting problem that I am quite confused on. Basically, I have a simple WordPress installation, and I wish to deny a folder (along with all files in the folder), let's say /wp-content/themes/default/scripts but to allow certain IPs.
I can deny this folder with location ^~/wp-content/themes/default/scripts {deny all;}
like any Nginx guru will tell you.
But from my understanding, the "^" takes higher precedence and will stop searching for other location blocks once it finds the regex match. As I do not want to deny the folder for everyone (of course, using allow (IP Address);
, my ^~/wp-content/...
location block entirely whipes out my PHP-FPM location block to pass the file over to the FastCGI server. And of course, when I try to view any file in the folder, the PHP file is directly downloaded as PHP is not parsing it.
Does anyone have an idea? I want to block the folder, but for PHP to work at the same time for the users I decide to allow. It is quite the tricky question; I cannot find any answer to the problem.
Thanks guys! Really appreciate your help!
For anyone wondering, my current Nginx vhost config looks like the following:
server {
#..all of the common stuff you would expect
include /folder/nginx.conf; #including some WordPress rewrites for W3 Total Cache
# pass the PHP scripts to FastCGI server listening on UNIX socket
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include /etc/nginx/fastcgi_params;
fastcgi_read_timeout 1900;
}
location / {
#allowing some IPs...
#deny everyone else
deny all;
#WordPress rewrite for slugs
index index.php;
if (!-e $request_filename) {
rewrite ^(.*)$ /index.php last;
}
#rewrite for sitemaps
rewrite ^(.*/)?sitemap.xml /wp-content/sitemap.php last;
}
# denying access to .htaccess files
location ~ /\.ht {
deny all;
}
}
Finally found the answer. When you're doing something like this, you need to redeclare the PHP-FPM settings (all the stuff that was in the location ~ \.php$ { (this code) }
block.
So to avoid redundancy, I put those values in another file, and was left with something like this:
server {
# pass the PHP scripts to FastCGI server listening on UNIX socket
location ~ \.php$ {
include /etc/nginx/fastcgi_php_text;
}
location / {
index index.php;
}
location ^~/folder/ {
deny all;
allow ...;
include /etc/nginx/fastcgi_php_text;
}
}
No idea if this is the best way to do such, but this is the only way that I have figured out.
You could also try defining a location block by @name and referencing it. From nginx Pitfalls page
server {
location ~ \.php$ {
try_files @fascgi;
}
location ^~ /folder {
deny all;
allow 127.0.0.1;
location ~ \.php$ {
try_files @fascgi;
}
}
location @fascgi {
fastcgi_pass 127.0.0.1:9000;
include fastcgi_params;
}
}