233 lines
6.7 KiB
Text
233 lines
6.7 KiB
Text
=pod
|
|
|
|
=head1 NAME
|
|
|
|
nginx-confgen - A preprocessor and macro system for nginx(-like) configuration
|
|
files.
|
|
|
|
=head1 SYNOPSIS
|
|
|
|
nginx-confgen -i input.conf -o output.conf
|
|
|
|
=head1 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 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 L</BUGS & WARTS>
|
|
below.
|
|
|
|
B<WARNING:> Do NOT use nginx-confgen with untrusted input, the C<pre_exec>
|
|
directive allows, by design, arbitrary code execution.
|
|
|
|
=head1 OPTIONS
|
|
|
|
The following command-line options are supported:
|
|
|
|
=over
|
|
|
|
=item -h
|
|
|
|
Show help text.
|
|
|
|
=item -V, --version
|
|
|
|
Show program version.
|
|
|
|
=item -i I<FILE>
|
|
|
|
Use the given file name as input file. If this option is not given or set to
|
|
C<->, then the file will be read from standard input.
|
|
|
|
=item -o I<FILE>
|
|
|
|
Write the output to the given file. If this option is not given or set to C<->,
|
|
then the file will be written to standard output.
|
|
|
|
=item -I I<DIR>
|
|
|
|
Set the search path for I<pre_include> directives. This option can be given
|
|
multiple times to search several directories in order. If this option is not
|
|
given, then include files are resolved relative to the directory that
|
|
nginx-confgen is run from (i.e. C<-I .>).
|
|
|
|
=back
|
|
|
|
|
|
=head1 DIRECTIVES
|
|
|
|
nginx-confgen recognizes and interprets the following directives:
|
|
|
|
=head2 pre_include
|
|
|
|
Similar to the C<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.
|
|
|
|
Relative paths are searched for in the directories given with the C<-I> flag.
|
|
|
|
=head2 pre_set
|
|
|
|
Similar to the C<set> directive in nginx, except that variables defined with
|
|
C<pre_set> are resolved during preprocessing. Note that variables defined with
|
|
C<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)
|
|
|
|
=head2 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 C<resolver> address. With the following hack
|
|
you can fetch the nameserver from C</etc/resolv.conf> and use that as the
|
|
C<resolver>:
|
|
|
|
pre_exec $nameserver "grep nameserver /etc/resolv.conf \\
|
|
| head -n 1 | sed 's/^nameserver //'";
|
|
resolver $nameserver;
|
|
|
|
(The C<\\> is necessary, otherwise your shell will consider the newline as a
|
|
new command).
|
|
|
|
=head2 pre_if
|
|
|
|
Similar to the C<if> directive in nginx, except that this is evaluated during
|
|
preprocessing. Also unlike C<if>, parenthesis around the arguments are not
|
|
supported. Some examples:
|
|
|
|
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/;
|
|
}
|
|
|
|
=head2 pre_warn
|
|
|
|
This directive, when interpreted, will generate a warning to the standard error
|
|
of nginx-confgen. Can be used to signal that a special configuration is being
|
|
used:
|
|
|
|
pre_if -e /etc/offline-mode {
|
|
pre_warn "Putting website in offline mode!";
|
|
}
|
|
|
|
Or to warn about certain directives:
|
|
|
|
pre_macro proxy_cache $var {
|
|
pre_warn "Using proxy_cache with $var violates company policy!";
|
|
|
|
# But we can output it anyway.
|
|
proxy_cache $var;
|
|
}
|
|
|
|
=head2 macro
|
|
|
|
Define a I<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 C<@remaining_vars> argument will capture any number of variables,
|
|
and can be passed to another directive inside the macro contents. The optional
|
|
C<&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 I<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 C<&block> expansion or
|
|
nested macro expansion.
|
|
|
|
|
|
=head1 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.
|
|
|
|
Comments and whitespace in the input files are thrown away and ignored. The
|
|
generated output is completely reformatted.
|
|
|
|
The nginx configuration syntax is not as regular as I had hoped. It's possible
|
|
for nginx modules to extend the syntax somewhat. A good example is the I<types>
|
|
directive in I<ngx_http_core_module>. While nginx-confgen should be able to
|
|
handle the I<types> directive just fine, other extensions may cause syntax
|
|
errors or will not survive a round-trip through nginx-confgen.
|
|
This applies to all I<*_by_lua_block> directives in the I<ngx_http_lua_module>.
|
|
The I<_by_lua> directives that accept a string should work just fine.
|
|
|
|
The error messages given by C<nginx-confgen> aren't always helpful.
|
|
|
|
|
|
=head1 AUTHOR
|
|
|
|
nginx-confgen is written by Yoran Heling <projects@yorhel.nl>
|
|
|
|
Web: L<https://dev.yorhel.nl/nginx-confgen>
|