nginx 的 env 指令仅用于传递环境变量给 worker 进程,不支持配置中直接引用如 $api_url;可用 $env{var}(日志/响应头)、envsubst 模板替换或 lua 动态读取实现变量使用。

Nginx 的 env 指令不能用来在配置中“引用”或“展开”环境变量值,它只控制 worker 进程是否继承某个系统环境变量。你无法写 proxy_pass http://$API_URL; 或 root /var/www/$ENV_NAME; 让 Nginx 自动替换——这种写法会报错或被当作字面量处理。
真正能用上系统环境变量,得靠明确区分两个层面:传递(让 worker 进程拿到变量)和使用(在配置里读取并生效)。下面分三类讲清楚怎么做、为什么这么设计、以及常见踩坑点。
env 指令只做“传递”,不提供“引用语法”
-
env必须写在nginx.conf最外层(main 上下文),比如:env APP_ENV; env API_HOST; # env LD_*; # 支持通配符
- 它的作用是告诉 Nginx:启动 worker 进程时,请把启动时 Master 进程已有的
APP_ENV和API_HOST值一并传过去。 - 它不会让你在
server或location块里写$APP_ENV——Nginx 配置语言本身不支持这种变量插值。 - 如果你写了
set $stage $APP_ENV;,Nginx 会直接报错:“unknown variable”。
能安全“使用”环境变量的三种方式
-
日志和响应头中用
$ENV{VAR}(Nginx ≥1.19.0)
这是唯一原生支持的引用方式,仅限于log_format、add_header、return等少数指令:log_format main '$remote_addr - "$request" status=$status env=$ENV{APP_ENV}'; server { location /health { add_header X-App-Env $ENV{APP_ENV}; return 200 "OK (env: $ENV{APP_ENV})\n"; } }⚠️ 注意:不能用于
proxy_pass、root、include等需要路径/地址解析的指令。 -
启动前用
envsubst替换模板配置(推荐,最通用)
把nginx.conf.template里的${API_HOST}替换成真实值,再启动 Nginx:envsubst /etc/nginx/nginx.conf nginx -g "daemon off;"
配置模板示例:
upstream api { server ${API_HOST}:8000; } location /api/ { proxy_pass http://${API_HOST}:8000/; } -
用 Lua 动态读取(需启用
ngx_http_lua_module)
在配置中嵌入 Lua 逻辑,调用os.getenv():set_by_lua_block $api_host { return os.getenv("API_HOST") or "localhost" }; proxy_pass http://$api_host:8000;需提前安装
lua-resty-env或确保基础 Lua 支持。
容器与 systemd 环境下特别注意
- Docker 中用
-e API_HOST=xxx启动容器,Nginx 不会自动获得该变量,除非:-
nginx.conf顶层有env API_HOST; - 且该变量在容器启动时已存在于 shell 环境中(Docker 的
-e确保这点)
-
- systemd 启动 Nginx 时,必须在 service 文件里显式声明:
[Service] Environment="API_HOST=api.example.com" EnvironmentFile=-/etc/nginx/env.conf
然后
nginx.conf中仍要写env API_HOST;才能让 worker 继承。
不复杂但容易忽略











