Nginx doesn't natively support reading file contents into variables during configuration parsing. The example you provided:
server {
set $serverNames /www/test.txt;
server_name $serverNames;
...
}
simply assigns the file path string to the variable rather than reading its content. This is a common pain point when trying to implement dynamic configuration.
Using include Directives
For static configurations that change infrequently:
# /etc/nginx/server_names.conf
server_name example.com test.example.com;
# main config
server {
include /etc/nginx/server_names.conf;
...
}
Lua Module Approach
For dynamic content loading with OpenResty or nginx+lua:
http {
lua_shared_dict server_names 1m;
init_by_lua_block {
local file = io.open("/www/test.txt", "r")
ngx.shared.server_names:set("names", file:read("*a"))
file:close()
}
}
server {
server_name $server_names;
set_by_lua_block $server_names {
return ngx.shared.server_names:get("names")
}
}
Using Environment Variables
For containerized deployments:
server {
server_name $SERVER_NAMES;
...
}
Then start nginx with:
SERVER_NAMES=$(cat /www/test.txt) nginx
Whichever method you choose, remember:
- File read operations should be cached when possible
- Implement proper error handling for missing files
- Consider performance impact during reloads
- For clustered environments, ensure synchronization
Many developers need to dynamically configure Nginx server names or other variables from external files, whether for multi-environment deployments or centralized configuration management. While Nginx doesn't natively support direct file reading in variable assignment, several effective workarounds exist.
The code snippet:
server {
set $serverNames /www/test.txt;
server_name $serverNames;
...
}
fails because Nginx treats the file path as a literal string value rather than reading its contents. The set
directive doesn't have file reading capability.
1. Using include + map Combo
http {
map $host $dynamic_server_name {
include /www/test.map;
}
server {
server_name $dynamic_server_name;
...
}
}
Where test.map contains key-value pairs:
example.com example.com;
*.test.dev test.dev;
2. Lua Module Approach
For OpenResty or Nginx with Lua module:
server {
access_by_lua_block {
local file = io.open("/www/test.txt", "r")
ngx.var.server_name = file:read("*a")
file:close()
}
...
}
3. Environment Variables via OS
env SERVER_NAMES_FILE=/www/test.txt;
http {
server {
server_name $SERVER_NAMES_FILE;
...
}
}
Then populate via shell script:
export SERVER_NAMES=$(cat /www/test.txt)
For enterprise deployments:
- Implement file change monitoring to reload Nginx when the source file updates
- Add proper file permission controls
- Consider using consul-template for distributed systems
- Benchmark performance impact for high-traffic sites
For complex scenarios, consider:
# Docker-compose example
version: '3'
services:
nginx:
image: nginx
volumes:
- ./config:/dynamic_config
command: /bin/bash -c "envsubst < /dynamic_config/template.conf > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'"