When setting up reverse proxies for development environments, we often encounter situations where multiple backend servers run identical copies of an application but require different host headers. The classic case is when you need to proxy:
app-dev.proxy.domain -> app.internal.domain (10.0.1.2)
app.proxy.domain -> app.internal.domain (10.0.1.1)
Both backends expect requests with app.internal.domain
as the Host header, but we need to route them to different IPs.
The key is to combine ProxyPreserveHost
with explicit IP routing in your VirtualHost configuration:
<VirtualHost *:80>
ServerName app-dev.proxy.domain
ProxyPreserveHost On
ProxyPass / http://10.0.1.2/
ProxyPassReverse / http://10.0.1.2/
# Force the Host header
RequestHeader set Host "app.internal.domain"
</VirtualHost>
<VirtualHost *:80>
ServerName app.proxy.domain
ProxyPreserveHost On
ProxyPass / http://10.0.1.1/
ProxyPassReverse / http://10.0.1.1/
# Force the Host header
RequestHeader set Host "app.internal.domain"
</VirtualHost>
For more complex scenarios, you might want to use mod_proxy
with explicit host headers:
<Location />
ProxyPass http://10.0.1.2/ connectiontimeout=5 timeout=30
ProxySet enablereuse=on
RequestHeader set Host "app.internal.domain"
</Location>
- Always enable
ProxyPreserveHost
when overriding host headers - Use
ProxyPassReverse
to handle redirects properly - Consider adding timeout parameters for production environments
After implementing these changes, verify with:
curl -v -H "Host: app-dev.proxy.domain" http://your-proxy-server/
Check that the request reaches the correct backend while maintaining the required host header.
When setting up reverse proxies with Apache mod_proxy
, a common challenge emerges when backend applications require specific host headers but need to be accessed through multiple proxy endpoints. Here's a deep dive into solving this with minimal configuration changes.
# Standard proxy configuration that WON'T work in this case
<VirtualHost *:80>
ServerName app-dev.proxy.domain
ProxyPass / http://10.0.1.2/
ProxyPassReverse / http://10.0.1.2/
</VirtualHost>
The above would route traffic correctly but sends the wrong Host header (10.0.1.2
instead of app.internal.domain
).
Apache's ProxyPreserveHost
combined with ProxyPass
solves this elegantly:
<VirtualHost *:80>
ServerName app-dev.proxy.domain
ProxyPreserveHost On
ProxyPass / http://10.0.1.2/
ProxyPassReverse / http://10.0.1.2/
RequestHeader set Host "app.internal.domain"
</VirtualHost>
For production and development environments coexisting:
# Production config
<VirtualHost *:80>
ServerName app.proxy.domain
ProxyPass / http://app.internal.domain/
ProxyPassReverse / http://app.internal.domain/
</VirtualHost>
# Dev config with IP override
<VirtualHost *:80>
ServerName app-dev.proxy.domain
ProxyPreserveHost On
ProxyPass / http://10.0.1.2/
ProxyPassReverse / http://10.0.1.2/
RequestHeader set Host "app.internal.domain"
</VirtualHost>
For more complex routing scenarios:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^app-dev\.proxy\.domain$
RewriteRule ^(.*)$ http://10.0.1.2/$1 [P,L]
ProxyPreserveHost On
RequestHeader set Host "app.internal.domain"
Verify your configuration works with:
curl -v -H "Host: app-dev.proxy.domain" http://your-proxy-server/
Check Apache logs for header modifications and routing decisions.