Use environment variables in Nginx configuration
Render configuration templates before startup, preserve Nginx variables, and understand what the env directive actually does.
Nginx does not generally interpolate shell environment variables in its configuration. listen $PORT; does not turn an environment value into a port. Render a configuration template before starting Nginx, or use a module explicitly designed to read the process environment.
Render a template with the official container image
Create default.conf.template:
server {
listen ${PORT};
server_name ${SERVER_NAME};
location / {
proxy_pass ${UPSTREAM_URL};
proxy_set_header Host $host;
}
}
Mount it in the official image's template directory and supply values:
docker run --rm -p 8080:8080 \
-e PORT=8080 \
-e SERVER_NAME=example.com \
-e UPSTREAM_URL=http://backend:9000 \
-v "$PWD/default.conf.template:/etc/nginx/templates/default.conf.template:ro" \
nginx
The backend name must be reachable and resolvable from the container, for example through the intended Docker network. Pin an approved image version or digest in a real deployment.
The official entrypoint renders .template files from /etc/nginx/templates into /etc/nginx/conf.d by default. Running a custom command or replacing the entrypoint can change whether that processing occurs. The output directory must be writable.
Use ${PORT}, not ${PORT:-80}: envsubst does not implement shell default-value expressions. Set defaults in the environment or entrypoint before rendering.
Render your own configuration explicitly
For an existing template and writable output directory:
export PORT="${PORT:-80}"
: "${SERVER_NAME:?Set SERVER_NAME}"
: "${UPSTREAM_URL:?Set UPSTREAM_URL}"
envsubst '$PORT $SERVER_NAME $UPSTREAM_URL' \
< default.conf.template > /etc/nginx/conf.d/default.conf
nginx -t || exit 1
exec nginx -g 'daemon off;'
The quoted variable list limits substitution so Nginx variables such as $host, $uri, and $request_uri remain intact. Validate values before putting them into configuration: substitution does not escape arbitrary text for Nginx syntax. For changes to an already running service, render to a temporary file, validate the assembled configuration, and replace/reload through the normal deployment process.
Understand the env directive's boundary
# Main context
env UPSTREAM_URL;
This preserves the value in worker process environments. It does not create an Nginx variable named $UPSTREAM_URL, and it cannot make listen accept an arbitrary dynamic expression.
Modules such as OpenResty's Lua module can read the environment. This optional example declares the target variable before assigning it:
# Main context
env UPSTREAM_URL;
http {
server {
listen 80;
resolver 10.0.0.53;
location / {
set $upstream "";
access_by_lua_block {
local target = os.getenv("UPSTREAM_URL")
if not target or target == "" then
return ngx.exit(503)
end
ngx.var.upstream = target
}
proxy_pass $upstream;
}
}
}
This requires the Lua module and a trusted resolver appropriate to the environment. The upstream value must be controlled deployment configuration, not client input. Variable-based proxy_pass has its own URI and DNS rules; rendering a literal upstream at startup is usually simpler when values do not change per request.
Use a configuration generator when values come from several systems
Ansible/Jinja2, Consul Template, and similar tools can generate the final file. They still need syntax validation, a clear reload process, and protection for any secrets in the rendered output.
FAQ
Why does $HOSTNAME not resolve in nginx.conf?
Shell environment names and Nginx request variables are different namespaces. Use template rendering when a deployment environment value is required.
Will envsubst erase $uri?
Unrestricted envsubst substitutes shell-style names, including ones meant for Nginx. Use an explicit allowlist. The official image's entrypoint constructs a variable list from the environment; avoid environment-name collisions and use its filter option when appropriate.
Can I export a new value and reload?
Changing a separate shell's environment does not update an existing Nginx master's environment. Regenerate rendered configuration and reload it, or recreate/restart the service with its updated environment as required by the deployment model.
References: official image template processing, Nginx env, OpenResty Lua module.
Contact us
Join the community
to join the community
Try Guance
Start online and pay only for what you use.
Get startedChoose a Guance plan