When implementing a frontend-backend server architecture with Apache, the key challenge is ensuring proper host header propagation. Your current setup shows a common pitfall where the backend server isn't correctly identifying virtual hosts despite proper frontend proxy configuration.
The problem stems from missing ProxyPreserveHost directive in your frontend configuration. Without this, the backend server receives requests without the original Host header, causing it to default to the first VirtualHost block.
# Corrected frontend configuration example
ServerName dev.example.com
ProxyPreserveHost On
ProxyPass / http://192.168.144.100:80/
ProxyPassReverse / http://192.168.144.100:80/
Here's the full working configuration for both servers:
# Frontend server (proxy) - /etc/apache2/sites-available/000-default.conf
ServerName dev.example.com
ProxyPreserveHost On
ProxyPass / http://192.168.144.100:80/
ProxyPassReverse / http://192.168.144.100:80/
ErrorLog ${APACHE_LOG_DIR}/dev_error.log
CustomLog ${APACHE_LOG_DIR}/dev_access.log combined
ServerName sandbox.example.com
ProxyPreserveHost On
ProxyPass / http://192.168.144.100:80/
ProxyPassReverse / http://192.168.144.100:80/
ErrorLog ${APACHE_LOG_DIR}/sandbox_error.log
CustomLog ${APACHE_LOG_DIR}/sandbox_access.log combined
The backend server needs proper NameVirtualHost declaration and should listen for the specific hostnames:
# Backend server - /etc/apache2/sites-available/000-default.conf
NameVirtualHost *:80
ServerName default.example.com
DocumentRoot /var/www/html
# Default catch-all configuration
ServerName dev.example.com
DocumentRoot /var/www/example.com/dev
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
ServerName sandbox.example.com
DocumentRoot /var/www/example.com/sandbox
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
After making these changes, run these commands:
sudo a2enmod proxy proxy_http
sudo systemctl restart apache2
Verify the Host header propagation using curl:
curl -v -H "Host: dev.example.com" http://frontend-server-ip/
For better performance and security, consider adding:
ProxyRequests Off
ProxyVia Off
Require all granted
I recently set up a two-server web architecture with:
- Frontend server handling incoming requests on port 80
- Backend server receiving proxied requests from the frontend
The challenge emerged when trying to route multiple domains (dev.example.com and sandbox.example.com) to different document roots on the backend server through Apache's reverse proxy.
Here's what my frontend Apache configuration looks like:
<VirtualHost *:80>
ServerName dev.example.com
ProxyPass / http://192.168.144.100:80/
ProxyPassReverse / http://192.168.144.100:80/
</VirtualHost>
<VirtualHost *:80>
ServerName sandbox.example.com
ProxyPass / http://192.168.144.100:80/
ProxyPassReverse / http://192.168.144.100:80/
</VirtualHost>
And the backend configuration:
<VirtualHost *:80>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/
<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>
<Directory /var/www/>
Options Indexes FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
allow from all
</Directory>
</VirtualHost>
<VirtualHost *:80>
ServerName dev.example.com
DocumentRoot /var/www/example.com/dev/
<Directory /var/www/example.com/dev/>
Options Indexes FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
allow from all
</Directory>
</VirtualHost>
<VirtualHost *:80>
ServerName sandbox.example.com
DocumentRoot /var/www/example.com/sandbox/
<Directory /var/www/example.com/sandbox/>
Options Indexes FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
allow from all
</Directory>
</VirtualHost>
The key issue was that the frontend server wasn't passing the original Host header to the backend. Adding ProxyPreserveHost On
to the frontend configuration solved this:
<VirtualHost *:80>
ServerName dev.example.com
ProxyPreserveHost On
ProxyPass / http://192.168.144.100:80/
ProxyPassReverse / http://192.168.144.100:80/
</VirtualHost>
<VirtualHost *:80>
ServerName sandbox.example.com
ProxyPreserveHost On
ProxyPass / http://192.168.144.100:80/
ProxyPassReverse / http://192.168.144.100:80/
</VirtualHost>
After making these changes and restarting Apache, you can verify the setup with:
curl -I http://dev.example.com
curl -I http://sandbox.example.com
Check that the responses show the correct document roots from the backend server.
For more complex setups, you might want to:
- Use
ProxyRequests Off
for security - Implement SSL termination on the frontend
- Set up proper logging for debugging
Here's an enhanced version with these improvements:
<VirtualHost *:80>
ServerName dev.example.com
ProxyPreserveHost On
ProxyRequests Off
ProxyPass / http://192.168.144.100:80/
ProxyPassReverse / http://192.168.144.100:80/
ErrorLog ${APACHE_LOG_DIR}/dev-error.log
CustomLog ${APACHE_LOG_DIR}/dev-access.log combined
</VirtualHost>