When working with Nginx configurations, one common limitation is the inability to set environment variables at the server block level. This becomes particularly problematic when you need different environment values for different virtual hosts.
Many modern applications rely on environment variables for configuration, especially in containerized environments. The inability to set these variables per-server in Nginx can force awkward workarounds like maintaining separate configuration files for each environment.
Nginx only allows environment variables to be set in the main context, outside of http, server, or location blocks:
# This works
env DB_HOST=production-db;
http {
server {
listen 80;
# Can't set env vars here
}
}
Here are several approaches to achieve server-specific environment configuration:
Option 1: Multiple Configuration Files
Create separate Nginx config files for each environment:
# production.conf
env DB_HOST=production-db;
include shared-config.conf;
# staging.conf
env DB_HOST=staging-db;
include shared-config.conf;
Option 2: Use Lua Scripts with OpenResty
For more flexibility, consider using OpenResty's Lua module:
server {
listen 80;
location / {
access_by_lua_block {
os.setenv("DB_HOST", "production-db")
-- Rest of your logic
}
}
}
Option 3: Environment-Specific Includes
Use a wrapper script to generate the appropriate configuration:
#!/bin/bash
# Generate nginx.conf
cat > /etc/nginx/nginx.conf <
- Consider whether environment variables are truly necessary - sometimes config files are more maintainable
- Document your approach clearly for other team members
- Test thoroughly as environment variable behavior can vary between Nginx versions
Nginx's env
directive operates at the global configuration level, which creates significant limitations when you need server-specific environment variables. The documentation clearly states these variables must be declared outside any configuration blocks:
# This works (global scope)
env DB_HOST=production-db.example.com;
http {
server {
listen 80;
# Cannot declare env vars here
}
}
Method 1: Using Include Directives with Separate Files
Create individual configuration files for each server block that needs unique environment variables:
# main nginx.conf
http {
include /etc/nginx/sites-enabled/*.conf;
}
# /etc/nginx/sites-enabled/site1.conf
env DB_HOST=site1-db.example.com;
server {
listen 80;
server_name site1.example.com;
# Server configuration
}
Method 2: Variable Substitution During Configuration Generation
For dynamic environments, use a template system like envsubst:
# template.conf
server {
listen 80;
server_name ${NGINX_HOST};
set $db_host "${DB_HOST}";
}
# Generation command
envsubst < template.conf > output.conf
Method 3: Lua Scripting with OpenResty
For advanced cases, leverage Nginx's Lua module:
server {
listen 80;
server_name dynamic.example.com;
location / {
set_by_lua $db_host 'return os.getenv("DB_HOST") or "default-db"';
# Use $db_host in your configuration
}
}
When implementing these solutions, remember:
- Environment variables may be visible in process listings
- Never store sensitive credentials in config files
- Consider using secret management systems for production
The various approaches have different performance characteristics:
Method | Memory Impact | Startup Time |
---|---|---|
Include Files | Low | Low |
Template Generation | Medium | Medium |
Lua Scripting | High | Low |