When configuring Nginx as a reverse proxy, one common requirement is preserving or modifying the Host header that gets forwarded to backend servers. This becomes particularly important when proxying requests to virtual hosts or applications that rely on the Host header for routing.
Unlike Apache's ProxyPreserveHost
directive which maintains the original Host header from client requests, Nginx takes a different approach. By default, Nginx sets the Host header to the $proxy_host
variable (the domain name or IP specified in proxy_pass).
To achieve similar functionality to Apache's ProxyPreserveHost, you need to manually configure the Host header in your location block:
location / {
proxy_pass http://backend_server;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
Different scenarios might require different Host header configurations:
# Preserve original client Host header
proxy_set_header Host $http_host;
# Use custom domain for backend
proxy_set_header Host backend.example.com;
# Include port if non-standard
proxy_set_header Host $host:$server_port;
When troubleshooting, these techniques can help:
# Log original and modified Host headers
log_format proxy_log '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_host" "$proxy_host"';
For complex setups with multiple virtual hosts:
server {
listen 80;
server_name *.example.com;
location / {
set $backend_host $1.example.internal;
proxy_pass http://$backend_host;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Host $host;
}
}
When configuring Nginx as a reverse proxy, one common requirement is controlling how the Host header gets passed to backend servers. Unlike Apache's straightforward ProxyPreserveHost
directive, Nginx requires explicit configuration to handle this properly.
By default, Nginx replaces the incoming Host header with the value defined in the proxy_pass
directive:
location / {
proxy_pass http://backend-server;
# Host header becomes "backend-server"
}
To mimic Apache's ProxyPreserveHost On
behavior:
location / {
proxy_pass http://backend-server;
proxy_set_header Host $host;
# Passes the original client's Host header
}
For virtual hosting scenarios, you might need to set a specific Host value:
location / {
proxy_pass http://backend-server;
proxy_set_header Host virtual-host.example.com;
# Forces this specific Host header
}
For maximum compatibility with backend applications:
location / {
proxy_pass http://backend-server;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
To verify headers are being passed correctly:
curl -v http://your-nginx-server
# Check the request headers in the backend application logs
When dealing with HTTPS backends or WebSocket connections:
location /ws/ {
proxy_pass https://websocket-backend;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}