Kristian Glass - Do I Smell Burning?

Environment variables in nginx config

It turns out nginx doesn’t exactly support reading configuration from the environment.

Fortunately the nice folk over at APITools have found a nice work-around.

What nginx does have is:

  • A default filter that strips all environment variables inherited from the parent process
  • The env directive which allows pass-through of environment variables
  • set_by_lua which executes some Lua code and stores the output in a given variable

Then all the Lua you need is return os.getenv("MYVAR"), and then you can, for example:

env PROXIED_CONTENT;

# Snip

http {
    # Snip

    server {
        # Snip

        location ~ ^/assets/(.*)$ {
            set_by_lua $assets_root 'return os.getenv("PROXIED_CONTENT")';

            # If you use a variable for proxy_pass, nginx uses its internal resolver which requires explicit config :(

            resolver 8.8.8.8;
            proxy_pass $assets_root$1;
        }
    }
}

Slightly convoluted, but as hacky workarounds go, I’ve definitely seen and implemented far worse!

But why?

In this particular case, I have SVGs served by S3. I have a static site that would like to use those SVGs.

Alas, “Right now, all browsers block <use> from loading anything cross-origin” (2015/03/27).

Easiest way to fix that was to have the webserver serving the static HTML just proxy the requests.

Now, the actual location of the SVGs is essentially config - it’s likely to vary between deploys (or at least during local development) - and so I want to get it from the environment (as per 12factor), and so here I am.

There’s certainly plenty more uses though - redirection targets, API keys, et cetera - it’s not just about browser-based hackery!

Comments