`if` or `include` for mode-specific `server` directives?

Francis Daly francis at daoine.org
Sat May 16 12:49:55 UTC 2020


On Sat, May 16, 2020 at 05:24:42AM -0400, petecooper wrote:

Hi there,

> At present, each site is managed by a monolithic
> `subdomain.example.com.conf` file with its own `server` block and associated
> directives. I manually change the `root` for each state when a site changes
> mode.

> Each site has a unique variable namespace and its own mode (live, holding,
> maintenance), like this:
> 
> server {
>     set $fqdn_abcd1234 'subdomain.example.com';
>     set $status_abcd1234 'live';
>     ...
> }

Your current system is that you edit the conf file to change some "set"
variable values, and reload nginx.

I suggest that you'll be happier in the long run using a templating
language, or macro-substituting language, external to nginx; along with
"source" conf files that are to have the substitutions applied; and
change the value there and regenerate the nginx conf parts, and then
reload nginx.

That language (your own shell scripts; m4; or whatever you like the
look of) will be able to write exactly the "root/return/add_header"
or whatever statements that you want based on the variable values that
you set.

It is a significant change to your setup right now; but it means that
your running nginx config will have exactly what you want, without needing
to worry about levels of indirection of run-time variable substitution.


"set" to a static string is using nginx-conf like a macro language.

"When all you have is a hammer, everything looks like a thumb."

I suspect you'll be better off using a real macro language -- you can
do more things with it, and the running nginx will have less work to do
on every request.

> == `if` in the `server` block ==
> 
> I will readily admit I have never used `if`, having been scared away by If
> Is Evil.

"If Is Evil" is limited to "when used in location context"; so you're
ok to do what you suggest here.

It just is not as efficient as it could be.

> == Stub `server` excerpts for each mode ==
> 
> Rather than include `root` and `if` checks in the monolithic `server` block
> file, I am considering outboarding each mode to its own stub file as a
> sidecar to the main `server` block file, like this:

This is better -- presumably you will edit the "include" line and reload
nginx (or may use symlinks; and change where the symlink points and
reload nginx) when you want to change mode.

If you can avoid the run-time variable substitution altogether, this
is good.

If your "mode"-conf files have lots of parts that are very similar apart
from a mode-related word, then you may be ok with manually updating all
of them when you want to add something else; an external thing that just
generates the three "mode" files could avoid that manual-duplication step.

> Given the above routes, which is (subjectively / objectively) better from an
> Nginx point of view?

Objectively, using run-time variable substitution means that nginx does
more work on every request than it would do without that.

And nginx testing one or two extra "if" statements on every request
means that nginx does more work than it would do without that.

It's not a lot of extra work; and the machine-time saved over a year
may not make up for the person-time taken in changing to a system that
avoids those things.

Good luck with it,

	f
-- 
Francis Daly        francis at daoine.org


More information about the nginx mailing list