nginx: use environment variables

103,612

Solution 1

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 2

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 3

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 4

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

Share:
103,612
schickling
Author by

schickling

Updated on July 09, 2022

Comments

  • schickling
    schickling almost 2 years

    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

  • schickling
    schickling about 10 years
    Thanks! But is there no option to use variables defined in nginx.conf in server blocks?
  • Ben Whaley
    Ben Whaley about 10 years
    In a server block you an use the syntax set $var "value"; and then refer to $var throughout your configuration. But you cannot use env vars.
  • lsl
    lsl about 7 years
    Saving people some time (the above requires a custom build), you can use a template and a tool called envsubst serverfault.com/a/755541/116508 did this for docker and it works, just specify the env vars or you might wipe out vars in nginx unintentionally e.g.$host
  • HermanTheGermanHesse
    HermanTheGermanHesse over 4 years
    The link seems not to lead to where you probably wanted it to lead :)
  • Kajsa
    Kajsa about 4 years
    Is there a way to check the output when launching this config through a helm install?
  • kikito
    kikito about 4 years
    @Kajsa you might want to make that comment into a SO question (with proper tags like helm etc). It will get more visibility and more chances of being answered by someone with Helm knowledge (which I am not).
  • Hunter_71
    Hunter_71 over 3 years
    It's worth to mention, that: 1) it uses a template files 2) template files should be created inside /etc/nginx/templates/ with defined suffix 3) after replacing env vars it automatically creates target configuration file inside conf.d without suffix (conf.d/default.conf for this example) 4) default template extension is .template 5) more can be found inside original answer :)
  • Ilya Kolesnikov
    Ilya Kolesnikov about 3 years
    It is not a feature of nginx itself but of it's official docker container, description is here hub.docker.com/_/nginx in paragraph "Using environment variables in nginx configuration (new in 1.19)"
  • Marc
    Marc almost 3 years
    What is this _from_env suffix??
  • Tobias
    Tobias over 2 years
    I like that solution, however it didn't work at the beginning, although I followed @Hunter_71's tips. That's because the Docker container has to start the docker-entrypoint.sh script in order to run envsubst which does the actual replacement. I had a CMD command defined in my Dockerfile, which makes the default ENTRYPOINT obsolete. Removing my CMD and placing it in a script which I copied to the /docker-entrypoint.d/ directory resolved the issue. Scripts in that directory are automatically executed by the default docker-entrypoint.sh.
  • lance-java
    lance-java over 2 years
    Unfortunately my nginx.conf contained some dollar signs which I didn't want replaced so had to pass an explicit list to envsubst . Would be nice if envsubst was smart enough to only replace values which are set in the environment
  • protocod
    protocod about 2 years
    Not a good idea, envsubst will substitute default env used by nginx.