nginx: use environment variables

ShellNginxProxyEnvironment VariablesDocker

Shell Problem Overview


I have the following scenario: I have an env variable $SOME_IP defined and want to use it in a nginx block. Referring to the nginx documentation I use the env directive in the nginx.conf file like the following:

user www-data;
worker_processes 4;
pid /run/nginx.pid;

env SOME_IP;

Now I want to use the variable for a proxy_pass. I tried it like the following:

location / {
    proxy_pass http://$SOME_IP:8000;
}

But I end up with this error message: nginx: [emerg] unknown "some_ip" variable

Shell Solutions


Solution 1 - Shell

With NGINX Docker image

Apply envsubst on template of the configuration file at container start. envsubst is included in official NGINX docker images.

Environment variable is referenced in a form $VARIABLE or ${VARIABLE}.

nginx.conf.template:

user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    server {
        listen       80;
        location / {
            access_log off;
            return 200 '${MESSAGE}';
            add_header Content-Type text/plain;
        }
    }
}

Dockerfile:

FROM nginx:1.17.8-alpine
COPY ./nginx.conf.template /nginx.conf.template
CMD ["/bin/sh" , "-c" , "envsubst < /nginx.conf.template > /etc/nginx/nginx.conf && exec nginx -g 'daemon off;'"]

Build and run docker:

docker build -t foo .
docker run --rm -it --name foo -p 8080:80 -e MESSAGE="Hellou World" foo

NOTE:If config template contains dollar sign $ which should not be substituted then list all used variables as parameter of envsubst so that only those are replaced. E.g.:

CMD ["/bin/sh" , "-c" , "envsubst '$USER_NAME $PASSWORD $KEY' < /nginx.conf.template > /etc/nginx/nginx.conf && exec nginx -g 'daemon off;'"]

Nginx Docker documentation for reference. Look for Using environment variables in nginx configuration.

> Using environment variables in nginx configuration > > Out-of-the-box, nginx doesn’t support environment variables inside > most configuration blocks. But envsubst may be used as a workaround if > you need to generate your nginx configuration dynamically before nginx > starts. > > Here is an example using docker-compose.yml: > > web: > image: nginx > volumes: > - ./mysite.template:/etc/nginx/conf.d/mysite.template > ports: > - "8080:80" > environment: > - NGINX_HOST=foobar.com > - NGINX_PORT=80 > command: /bin/bash -c "envsubst < /etc/nginx/conf.d/mysite.template > /etc/nginx/conf.d/default.conf && exec nginx -g 'daemon off;'" > > The mysite.template file may then contain variable references like > this: > > listen ${NGINX_PORT};

Solution 2 - Shell

You can access the variables via modules - I found options for doing it with Lua and Perl.

Wrote about it on my company's blog:

https://web.archive.org/web/20170712003702/https://docs.apitools.com/blog/2014/07/02/using-environment-variables-in-nginx-conf.html

The TL;DR:

env API_KEY;

And then:

http {
...
  server {
    location / {
      # set var using Lua
      set_by_lua $api_key 'return os.getenv("API_KEY")';
      
      # set var using perl
      perl_set $api_key 'sub { return $ENV{"API_KEY"}; }';
      ...
    }
  }
}

EDIT: original blog is dead, changed link to wayback machine cache

Solution 3 - Shell

The correct usage would be $SOME_IP_from_env, but environment variables set from nginx.conf cannot be used in server, location or http blocks.

You can use environment variables if you use the openresty bundle, which includes Lua.

Solution 4 - Shell

Since nginx 1.19 you can now use environment variables in your configuration with docker-compose. I used the following setup:

# file: docker/nginx/templates/default.conf.conf
upstream api-upstream {
    server ${API_HOST};
}


# file: docker-compose.yml
services:
    nginx:
        image: nginx:1.19-alpine
        environment:
            NGINX_ENVSUBST_TEMPLATE_SUFFIX: ".conf"
            API_HOST: api.example.com

I found this answer on other thread: https://stackoverflow.com/a/62844707/4479861

Solution 5 - Shell

For simple environment variables substitution, can use the envsubst command and template feature since docker Nginx 1.19. Note: envsubst not support fallback default, eg: ${MY_ENV:-DefaultValue}.

For more advanced usage, consider use https://github.com/guyskk/envsub-njs, it's implemented via Nginx NJS, use Javascript template literals, powerful and works well in cross-platform. eg: ${Env('MY_ENV', 'DefaultValue')}

You can also consider https://github.com/kreuzwerker/envplate, it support syntax just like shell variables substitution.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionschicklingView Question on Stackoverflow
Solution 1 - ShellMichal FoksaView Answer on Stackoverflow
Solution 2 - ShellkikitoView Answer on Stackoverflow
Solution 3 - ShellBen WhaleyView Answer on Stackoverflow
Solution 4 - ShellIdo BleicherView Answer on Stackoverflow
Solution 5 - ShellguyskkView Answer on Stackoverflow