57

I am trying to optimize my nginx configs, so it would be possible to set one variable, and all location paths would update automatically. I have four lines in question:

server_name php.domain.com;
root /srv/web/vhosts/php/web;
error_log /srv/web/vhosts/php/logs/error.log;
access_log /srv/web/vhosts/php/logs/access.log;

What I would like to achieve is to set one variable (in this case 'php') and include it to config.

set $variable "php";
server_name $variable.domain.com;
root /srv/web/vhosts/$variable/web;
error_log /srv/web/vhosts/$variable/logs/error.log;
access_log /srv/web/vhosts/$variable/logs/access.log;

However it seams that nginx ignores variables in this config. Am I doing something wrong or it is not possible to use variable in location paths?

masegaloeh
  • 17,978
  • 9
  • 56
  • 104
Bogdan Kuštan
  • 673
  • 1
  • 5
  • 6

2 Answers2

88

Variables can't be declared anywhere nor be used in any directive.

As the documentation of set directive is :

Syntax:   set $variable value;
Default:  —
Context:  server, location, if

The immediate consequence is that you can't use custom variables in an http block.

Update : after a discussion and experiments with AlexeyTen in this chatroom.

  • access_log can contain variables with restrictions. Among them, the lack of buffering and the fact that the leading slash must not be declared in a variable.
  • error_log won't work with variables at all.
  • root directive can contains variables.
  • server_name directive only allows strict $hostname value as a variable-like notation.
Xavier Lucas
  • 12,815
  • 2
  • 44
  • 50
  • 2
    `access_log`/`error_log` work with variables, but with some limitations. `server_name` can't contain variables. – Alexey Ten Nov 17 '14 at 11:38
  • 1
    @AlexeyTen Re-read my answer. It doesn't work with **custom** variables. Server name can contain **built-in** variable like `$hostname`. Updated the answer to clarify that behaviour. – Xavier Lucas Nov 17 '14 at 12:10
  • 6
    Well, `$hostname` is the only allowed variable. https://github.com/nginx/nginx/blob/bb8c0683da773566e09797ef8a4ee00ad1e0f956/src/http/ngx_http_core_module.c#L4370 Actually, it's more like a magic constant, not a real variable – Alexey Ten Nov 17 '14 at 12:12
  • @AlexeyTen Good point, updated the answer this way. – Xavier Lucas Nov 17 '14 at 12:16
  • 1
    And still, `*_log`s work with variables, but nginx's worker should have permissions to create resulted filename. In particular that means all previous directories must exist. – Alexey Ten Nov 17 '14 at 12:17
  • 1
    @AlexeyTen No it doesn't. – Xavier Lucas Nov 17 '14 at 12:18
  • 2
    Let us [continue this discussion in chat](http://chat.stackexchange.com/rooms/18730/discussion-between-alexey-ten-and-xavier-lucas). – Alexey Ten Nov 17 '14 at 12:18
  • 4
    This is maybe _the_ best researched SF answer ever. Thanks to both of you /Cc @AlexeyTen – kaiser Feb 15 '16 at 16:58
  • 1
    Thanks for the confirmation that error_log won't work with variables---I thought I was crazy. For anyone wanting to rotate their error logs, I'd recommend the "Manual Log Rotation" or "Log Rotation with logrotate" sections here: https://www.digitalocean.com/community/tutorials/how-to-configure-logging-and-log-rotation-in-nginx-on-an-ubuntu-vps – kevinmicke Feb 28 '18 at 17:46
  • Whereas you can set a custom variable in an `http.server` block and use it in the `proxy_pass` you cannot set a custom variable in a `stream.server` block. – Jesse Chisholm Sep 18 '20 at 02:45
2

You can use variables declared via map as described in this SO question, which discusses using custom variables in the expression part of location blocks:

https://stackoverflow.com/a/61513351/1604622

gruentee
  • 121
  • 3