nginx-confgen 1.0 Manual
Version: latest / 2.1 / 2.0 / 1.2 / 1.1 / 1.0
NAME
nginx-confgen - A preprocessor and macro system for nginx(-like) configuration files.
SYNOPSIS
nginx-confgen <input.conf >output.conf
DESCRIPTION
nginx-confgen can be used to do pre-processing for nginx configuration files (and other configuration files with a similar syntax). It has support for "compile-time" macro expansion and variable interpolation, which should make it less tedious to maintain large and complex configurations.
nginx-confgen does not currently support any command-line arguments. It simply reads the configuration from standard input, and writes the processed configuration to standard output.
nginx-confgen works by parsing the input into a syntax tree, modifying this tree, and then formatting the tree to generate the output. It is completely oblivious to nginx contexts and directives, so it is possible to do nonsensical transformations and generate incorrect configuration files. Comments in the input file will not be present in the output. See also the “BUGS & WARTS” below.
WARNING: Do NOT use nginx-confgen with untrusted
input, the pre_exec
directive allows, by design, arbitrary
code execution.
DIRECTIVES
nginx-confgen recognizes and interprets the following directives:
pre_include
Similar to the include
directive in nginx, except that
the file is included during preprocessing. The included file may contain
any preprocessing directives supported by nginx-confgen. Variables and
macros defined in the included file will be available in the parent
file.
Beware that relative paths are resolved from the working directory that nginx-confgen is run from.
pre_set
Similar to the set
directive in nginx, except that
variables defined with pre_set
are resolved during
preprocessing. Note that variables defined with pre_set
are
only available in the same scope as they are defined, for example:
pre_set $var outer;
location / {
pre_set $var inner;
# $var is now "inner" within this location block.
}
# $var is "outer" again after the location block.
(This may change in the future)
pre_exec
Run a shell command, and store the output in a variable. For example,
nginx will not use your system's DNS resolution methods to resolve
domain names. Instead you need to manually set a resolver
address. With the following hack you can fetch the nameserver from
/etc/resolv.conf
and use that as the
resolver
:
pre_exec $nameserver "grep nameserver /etc/resolv.conf \\
| head -n 1 | sed 's/^nameserver //'";
resolver $nameserver;
(The \\
is necessary, otherwise your shell will consider
the newline as a new command).
pre_if
Similar to the if
directive in nginx, except that this
is evaluated during preprocessing. nginx-confgen has a few warts with
regards to parenthesis, things usually work better without:
pre_if -f $certdir/ocsp.der {
ssl_stapling on;
ssl_stapling_file $certdir/ocsp.der;
}
pre_if !-f $certdir/ocsp.der {
ssl_stapling off;
}
# You can have different configuration depending on the name of
# the system on which nginx-confgen runs. Like... yeah.
pre_exec $hostname 'hostname';
pre_if $hostname ~* ^proxy_for_(.+) {
proxy_pass http://$1/;
}
macro
Define a macro, which is a configuration block that you can later refer to. The general syntax is as follows:
macro macro_name $var1 $var2 @remaining_vars &block_var {
# contents
}
The optional @remaining_vars
argument will capture any
number of variables, and can be passed to another directive inside the
macro contents. The optional &block_var
allows the
macro to be invoked with a block argument, which will expand to any
number of directives. Some examples:
macro le {
location /.well-known/acme-challenge {
alias /etc/letsencrypt/challenge;
}
}
# Usage:
le;
macro redir $path $to {
location $path {
return 301 $to;
}
}
# Usage:
redir / http://blicky.net/;
macro vhost $primary_name @aliases &block {
server {
listen [::]:443 ssl;
server_name $primary_name @aliases;
ssl_certificate $crtdir/$primary_name/fullchain.pem;
ssl_certificate_key $crtdir/$primary_name/privkey.pem;
█
}
}
# Usage:
vhost example.com {
root /var/www/example.com;
}
vhost example.org alias.example.org {
root /var/www/example.org;
}
Note that these are hygienic macros, so variable capture is predictable (but not necessarily the most useful):
pre_var $dest /a;
macro redir {
# This will be /a, regardless of the context in which this macro is called.
return 301 $dest;
}
# $dest is still '/a' inside the macro after this new variable definition.
pre_var $dest /b;
redir;
Similarly, macro arguments will not be available inside
&block
expansion or nested macro expansion.
BUGS & WARTS
nginx-confgen is a quickly written hack to solve a particular use case, it is quite likely to have some weird behavior and bugs. Here's a few I am aware of:
Be careful with parenthesis around if statements, e.g.:
if ($a == $b) { }
Will get converted into:
if "(${a}" == "${b})" { }
Which is unlikely what you want. As a workaround, add some spaces:
if ( $a == $b ) { }
Arguments to directives may get reformatted, especially if they contain a variable. This should not matter in most cases, but in some particular scenarios it does. Here's a few examples of reformatting:
return 301 http://blicky.net$request_uri; # becomes: return 301 "http://blicky.net${request_uri}"; add_header Something "${header}"; # becomes: add_header Something $header;
This reformatting may cause different behavior for nginx directives that do not support variable interpolation, such as
error_log
.pre_if
does not like empty strings, e.g.pre_if $x == "" { }
Will throw an error, use the following instead:
pre_if $x { }
The error messages aren't always useful.
AUTHOR
nginx-confgen is written by Yoran Heling <projects@yorhel.nl>