NGINX - invalid number of arguments in "location" directive - nginx

I am creating an NGINX global config file to be added to a website vhost file.
The code I put in the file /etc/nginx/global.d/wordpresscache.conf is:
set $cache_uri $request_uri;
# POST requests and URLs with a query string should always go to PHP
if ($request_method = POST) {
set $cache_uri 'null cache';
}
if ($query_string != "") {
set $cache_uri 'null cache';
}
# Don't cache URIs containing the following segments
if ($request_uri ~* "(/wp-admin/|/xmlrpc.php|/wp-(app|cron|login|register|mail).php
|wp-.*.php|/feed/|index.php|wp-comments-popup.php
|wp-links-opml.php|wp-locations.php |sitemap(_index)?.xml
|[a-z0-9_-]+-sitemap([0-9]+)?.xml)") {
set $cache_uri 'null cache';
}
# Don't use the cache for logged-in users or recent commenters
if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+
|wp-postpass|wordpress_logged_in") {
set $cache_uri 'null cache';
}
# Use cached or actual file if it exists, otherwise pass request to WordPress
location / {
try_files /wp-content/cache/supercache/$http_host/$cache_uri/index.html
$uri $uri/ /index.php;
}
# Cache static files for as long as possible
location ~*.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|css|rss|atom|js|jpg
|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid
|midi|wav|bmp|rtf)$ {
expires max;
log_not_found off;
access_log off;
}
The problem is that when I reload the configuration I get this error message:
nginx: [emerg] invalid number of arguments in "location" directive in
/etc/nginx/global.d/wordpresscache.conf:35
However the structure of that location directive seem to be good to me. Here is where I got the code from (Tip 7)
Can anyone point me out to what I am doing wrong?
Edit:
I have tried the following:
location ~*. (ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|css|rss|atom|js|jpg
|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid
|midi|wav|bmp|rtf)$ {
expires max;
log_not_found off;
access_log off;
}
location ~*. (ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|css|rss|atom|js|jpg
|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid
|midi|wav|bmp|rtf)$ {
expires max;
log_not_found off;
access_log off;
}
location ~* \.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|css|rss|atom|js|jpg
|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid
|midi|wav|bmp|rtf)$ {
expires max;
log_not_found off;
access_log off;
}
location ~*\. (ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|css|rss|atom|js|jpg
|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid
|midi|wav|bmp|rtf)$ {
expires max;
log_not_found off;
access_log off;
}
But they all give me the same error :(
New Edit. I tried to remove some extensions... and it works. Now I have for testing purposes only:
location ~* \.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf)$ {
expires max;
log_not_found off;
access_log off;
}
and it works. Does anybody know what is the maximum number of arguments in parentheses?

location ~*.(ogg
Missed a space right there, should be:
location ~*. (ogg
The regex in question is a bit off also, because it would match URI /frogg or /blahwav, etc.
The correct is escaping the dot with \:
location ~* \.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|css|rss|atom|js|jpg
|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid
|midi|wav|bmp|rtf)$ {
expires max;
log_not_found off;
access_log off;
}
Same thing applies to
location ~ .php$ {
Should be:
location ~ \.php$ {
All in all, that linked article is not escaping much of regexes, for whatever reason.
I suspect it's due to bad formatting/content sanitizing in whatever custom CMS they use.
Example:
location ~* wp-config.php {
deny all;
}
Would unnecessarily match /wp-configaphp or /wp-configuphp, and even /whateveryouwantmetobewp-configaphp, etc. There is no performance benefit in not escaping stuff in those regex, so yeah - "bad blogging" :-)
Should be:
location ~* /wp-config\.php$ {
deny all;
}
And even better, if you know you're using a single site in webroot directory, use exact matching:
location = /wp-config.php {
deny all;
}
You can also look at secure NGINX WordPress configuration which deals with security-related part of NGINX-Wordpress configuration.

Related

Restricting access by IP address to wp-admin and wp-login.php on Azure Wordpress on Linux

Using Azure Wordpress for Linux Web App, I'm trying to modify the nginx conf.d file to restrict access to wp-login.php and wp-admin directory by IP address. The directives that I'm trying to use either seem to completely allow access or completely deny access, it does not seem to respect allow x.x.x.x; at all.
Here is the code that I've placed in my server block:
location ~ ^(wp-admin|wp-login.php) {
try_files $uri $uri/ /index.php?$args;
index index.html index.htm index.php;
allow x.x.x.x;
deny all;
}
If I only have the deny all; directive, everything returns a 403 forbidden error. If I put in the allow directive, I can access it from any IP address and it never seems to throw an error.
I've noticed in my logs that this is showing up:
278#278: *25 access forbidden by rule, client: 172.19.0.1, server: _, request: "GET /wp-admin HTTP/1.1", host: "myhostname.com"
and that this precedes my server block in the default.conf file:
upstream php {
#server unix:/tmp/php-cgi.socket;
server 127.0.0.1:9000;
}
Is these something going on that basically makes all my inbound traffic appear to nginx as coming from the same IP address? Is there any way to "pass that down" ?
Here is the default.conf file:
upstream php {
server unix:/var/run/php/php7.0-fpm.sock;
#server 127.0.0.1:9000;
}
server {
listen 80;
## Your website name goes here.
server_name _;
## Your only path reference.
root /home/site/wwwroot;
## This should be in your http block and if it is, it's not needed here.
index index.php index.html;
location = /favicon.ico {
log_not_found off;
access_log off;
}
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
# Add locations of phpmyadmin here.
# Disable sendfile as per https://docs.vagrantup.com/v2/synced-folders/virtual
sendfile off;
set $skip_cache 0;
# POST requests and urls with a query string should always go to PHP
if ($request_method = POST) {
set $skip_cache 1;
}
if ($query_string != "") {
set $skip_cache 1;
}
# Don't cache uris containing the following segments
if ($request_uri ~* "/wp-admin/|/xmlrpc.php|wp-.*.php|/feed/|index.php|sitemap(_index)?.xml") {
set $skip_cache 1;
}
# Don't use the cache for logged in users or recent commenters
if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") {
set $skip_cache 1;
}
# Don't cache WooCommerce URLs
# Cart widgets are still a problem: https://github.com/emcniece/docker-wordpress/issues/3
if ($request_uri ~* "/(cart|checkout|my-account)/*$") {
set $skip_cache 1;
}
location / {
# This is cool because no php is touched for static content.
# include the "?$args" part so non-default permalinks doesn't break when using query string
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
#NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
include fastcgi.conf;
fastcgi_intercept_errors on;
fastcgi_pass php;
fastcgi_read_timeout 300;
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
fastcgi_cache WORDPRESS;
fastcgi_cache_valid 60m;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
expires max;
log_not_found off;
}
I started noticing today that I can see the IP address that I want under the PHP variable of $_SERVER['HTTP_X_CLIENT_IP'] --- Is there a way to test that under the allow/deny options, or to override the value that allow/deny looks at to use this other value? For example:
if ($http_x_client_ip != x.x.x.x) {
return 403;
}

Nginx custom uploads rewrite for WordPress Multisite

I have a WordPress multisite setup with subdomains on Nginx.
I'd like upload urls such as this to work...
http://mysub.mydomain.com/files/2017/07/myfile.png
where the location of the file is...
<web root>/wp-content/uploads/sites/xx/2017/07/myfile.png
This is the location rule in the Nginx config:
location ~ ^/files/(.*)$ {
try_files /wp-content/uploads/sites/$blogid/$1;
access_log off; log_not_found off; expires max;
}
It doesn't work and I'm unable to see why.
I have also tried (and numerous variations):
location ^~ /files {
internal;
alias /www/wp-content/uploads/sites/$blogid;
access_log off; log_not_found off; expires max;
}
If either of these can be confirmed as 'should work' then I'll start looking at rules higher up my code that may be taking precedence (although nothing's jumped out at me yet)...
This is what did work:
if (!-e $request_filename) {
rewrite ^/files/(.*) /wp-content/uploads/sites/$blogid/$1 last;
}

Setting cache-control on all folders' assets except one

I need to apply the following location rule for every single folder of my app with the exception of /forum and its children:
location ~* \.(?:jpg|jpeg|gif)$ {
expires 1M;
access_log off;
add_header Cache-Control "public";
}
I tried out setting it to location ~* ^/forum/.*\.(?:jpg|jpeg)$ but it doesn't look like it's working the way I want it to.
This is the solver I came up with:
location /forum {
...
}
location / {
location ~* \.(?:jpg|jpeg|gif)$ {
...
}
...
}
Simply separate the location directives and adjust commands accordingly.

Nginx rewrite url to attain clean url

I have a site with below url structure which i am running on nginx
http://example.com/category.php?page=1&query=latest
Now my aim is to convert it to the below one using nginx rewrite
http://example.com/latest/1/
where 1 is the page number and is dynamic
What will be the exact rule to attain clean url ,
Along with it i also require a rule incase someone gives a negative value for page it will automatically get redirected to positive value of page number.
Right now my existing configuration is as below
server {
server_name example.com;
error_log /data1/nginx/aggri.com.error.log;
root /data1/aggri;
index index.php;
rewrite_log on;
location ~ .php$ {
try_files $uri $uri/ /index.php;
include fastcgi_params;
fastcgi_pass unix:/var/run/php5-fpm.sock;
expires 0;
add_header Cache-Control public;
set $skip_cache 0;
if ($request_uri ~* "^(.*/)index\.php$") {
return 301 $1;
} }
location ~* ^.+\.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf|js|woff|css)$ {
access_log off; log_not_found off; expires max;
}
location = /robots.txt { access_log off; log_not_found off; }
location ~ /\. { deny all; access_log off; log_not_found off; }
}
Example:
location ~ /category.php$ {
if ( $args ~ ^page=[-]*([0-9]+)&query=([\w]+)$ ) {
set $pg $1;
set $q $2;
rewrite (.*) /$q/$pg/? permanent;
}
}

nginx - serve only images

I'm trying to setup nginx so "static.domain.com" can only serve images. This is what I have come up with, but I know it can be done more efficiently. I want to serve 403.html if someone tries to access any .htm, .php, directory (anything else I'm missing?) files. Of course, with the exception of 403.htm and static.htm files.
Any ideas how I can secure this properly?
server {
listen xx.xx.xx.xx:80;
server_name static.domain.com;
root /www/domain.com/httpdocs;
index static.htm;
access_log off;
error_log /dev/null crit;
error_page 403 /403.html;
# Disable access to .htaccess or any other hidden file
location ~ /\.ht {
deny all;
}
location ~* \.php {
deny all;
}
# Serve static files directly from nginx
location ~* \.(jpg|jpeg|gif|png|bmp|ico|pdf|flv|swf|exe|html|htm|txt|css|js) {
add_header Cache-Control public;
add_header Cache-Control must-revalidate;
expires 7d;
}
}
Why not move the images up and then deny all?
location ~* \.(jpg|jpeg|gif|png|bmp|ico|pdf|flv|swf|exe|html|htm|txt|css|js) {
add_header Cache-Control public;
add_header Cache-Control must-revalidate;
expires 7d;
}
location / {
deny all;
}
there is no syntax for NOT matching a regular expression. Instead, match the target regular expression and assign an empty block, then use location / to match anything else. -From http://wiki.nginx.org/HttpCoreModule#location
Edit: Removed "=" from "location /"
To quote the docs:
location = / {
# matches the query / *only.*
}
location / {
# matches *any query*, since all queries begin with /, but regular
# expressions and any longer conventional blocks will be
# matched first.
}
My bad.

Resources