Nginx Location Deny by File Extension Syntax

nginx location deny by file extension syntax

The nginx server uses straight pcre as the library for regular expressions; whatever pcre accepts, so should nginx.

Some testing on OpenBSD with egrep(1) reveals:

$ printf '/t.bak\n/t.bakk\n/t.zipp\n/a.zip\n/.ht\n/t.ht\n' |grep -E '\.(bak|zip)$|/\.'
/t.bak
/a.zip
/.ht
$

But OpenBSD's egrep doesn't actually use pcre, but regcomp(3) instead! However, pcre does come with pcregrep, which does produce identical results:

$ printf '/t.bak\n/t.bakk\n/t.zipp\n/a.zip\n/.ht\n/t.ht\n' |pcregrep '\.(bak|zip)$|/\.'
/t.bak
/a.zip
/.ht
$

You could also try pcretest for testing the regular expressions (apparently, you must quote them with something like # there):

$ pcretest
PCRE version 8.30 2012-02-04

re> #\.(bak|zip)$|/\.#
data> /t.bak
0: .bak
1: bak
data> /t.baki
No match
data> /.h
0: /.
data> ^D
$

I.e., to summarise: just concatenating the two expressions with | should work.


location ~* \.(bak|zip)$|/\. {
deny all;
}

However, for the sake of maintenance (and since you've had to ask this question in the first place), you might as well want to keep these expressions apart for a clearer overview of what the config is all about. (The two expressions apart might even be more efficient due to some kind of end-of-line optimisation than when merged together, but that's just a wild guess on my part.)

Nginx location not equal to regex

According to nginx documentation

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

So you could define something like

location ~ (dir1|file2\.php) { 
# empty
}

location / {
rewrite ^/(.*) http://example.com/$1 permanent;
}

How can I have same rule for two locations in NGINX config?

Try

location ~ ^/(first/location|second/location)/ {
...
}

The ~ means to use a regular expression for the url. The ^ means to check from the first character. This will look for a / followed by either of the locations and then another /.

Using variables in Nginx location rules

You can't. Nginx doesn't really support variables in config files, and its developers mock everyone who ask for this feature to be added:

"[Variables] are rather costly compared to plain static configuration. [A] macro expansion and "include" directives should be used [with] e.g. sed + make or any other common template mechanism." http://nginx.org/en/docs/faq/variables_in_config.html

You should either write or download a little tool that will allow you to generate config files from placeholder config files.

Update The code below still works, but I've wrapped it all up into a small PHP program/library called Configurator also on Packagist, which allows easy generation of nginx/php-fpm etc config files, from templates and various forms of config data.

e.g. my nginx source config file looks like this:

location  / {
try_files $uri /routing.php?$args;
fastcgi_pass unix:%phpfpm.socket%/php-fpm-www.sock;
include %mysite.root.directory%/conf/fastcgi.conf;
}

And then I have a config file with the variables defined:

phpfpm.socket=/var/run/php-fpm.socket
mysite.root.directory=/home/mysite

And then I generate the actual config file using that. It looks like you're a Python guy, so a PHP based example may not help you, but for anyone else who does use PHP:

<?php

require_once('path.php');

$filesToGenerate = array(
'conf/nginx.conf' => 'autogen/nginx.conf',
'conf/mysite.nginx.conf' => 'autogen/mysite.nginx.conf',
'conf/mysite.php-fpm.conf' => 'autogen/mysite.php-fpm.conf',
'conf/my.cnf' => 'autogen/my.cnf',
);

$environment = 'amazonec2';

if ($argc >= 2){
$environmentRequired = $argv[1];

$allowedVars = array(
'amazonec2',
'macports',
);

if (in_array($environmentRequired, $allowedVars) == true){
$environment = $environmentRequired;
}
}
else{
echo "Defaulting to [".$environment."] environment";
}

$config = getConfigForEnvironment($environment);

foreach($filesToGenerate as $inputFilename => $outputFilename){
generateConfigFile(PATH_TO_ROOT.$inputFilename, PATH_TO_ROOT.$outputFilename, $config);
}

function getConfigForEnvironment($environment){
$config = parse_ini_file(PATH_TO_ROOT."conf/deployConfig.ini", TRUE);
$configWithMarkers = array();
foreach($config[$environment] as $key => $value){
$configWithMarkers['%'.$key.'%'] = $value;
}

return $configWithMarkers;
}

function generateConfigFile($inputFilename, $outputFilename, $config){

$lines = file($inputFilename);

if($lines === FALSE){
echo "Failed to read [".$inputFilename."] for reading.";
exit(-1);
}

$fileHandle = fopen($outputFilename, "w");

if($fileHandle === FALSE){
echo "Failed to read [".$outputFilename."] for writing.";
exit(-1);
}

$search = array_keys($config);
$replace = array_values($config);

foreach($lines as $line){
$line = str_replace($search, $replace, $line);
fwrite($fileHandle, $line);
}

fclose($fileHandle);
}

?>

And then deployConfig.ini looks something like:

[global]

;global variables go here.

[amazonec2]
nginx.log.directory = /var/log/nginx
nginx.root.directory = /usr/share/nginx
nginx.conf.directory = /etc/nginx
nginx.run.directory = /var/run
nginx.user = nginx

[macports]
nginx.log.directory = /opt/local/var/log/nginx
nginx.root.directory = /opt/local/share/nginx
nginx.conf.directory = /opt/local/etc/nginx
nginx.run.directory = /opt/local/var/run
nginx.user = _www


Related Topics



Leave a reply



Submit