Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using variables in Nginx location rules

In Nginx, I'm trying to define a variable which allows me to configure a sub-folder for all my location blocks. I did this:

set $folder '/test';  location $folder/ {    [...] }  location $folder/something {    [...] } 

Unfortunately, this doesn't seem to work. While Nginx doesn't complain about the syntax, it returns a 404 when requesting /test/. If I write the folder in explicitly, it works. So how can I use variables in location blocks?

like image 221
tomka Avatar asked Mar 14 '13 18:03

tomka


People also ask

Can NGINX use environment variables?

Out-of-the-box, nginx doesn't support environment variables inside most configuration blocks. But envsubst may be used as a workaround if you need to generate your nginx configuration dynamically before nginx starts.

How does NGINX match location?

To find a location match for an URI, NGINX first scans the locations that is defined using the prefix strings (without regular expression). Thereafter, the location with regular expressions are checked in order of their declaration in the configuration file.

Does NGINX config order matter?

Yes, it does and totally depends on different directives specified within the different context supported by Nginx.

What is NGINX location?

Every NGINX configuration file will be found in the /etc/nginx/ directory, with the main configuration file located in /etc/nginx/nginx. conf . NGINX configuration options are known as “directives”: these are arranged into groups, known interchangeably as blocks or contexts .


1 Answers

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 
like image 144
Danack Avatar answered Oct 20 '22 19:10

Danack