In this scenario, we have two Apache servers sharing a single public IP address:
- Server 1: 192.168.1.101 (handles example.com)
- Server 2: 192.168.1.102 (should handle beta.example.com exclusively)
Here's how to configure the reverse proxy on Server 1 to properly route only the beta subdomain:
<VirtualHost *:80>
ServerName example.com
# Your regular configuration for example.com
DocumentRoot /var/www/example.com
</VirtualHost>
<VirtualHost *:80>
ServerName beta.example.com
ServerAlias beta.example.com
ProxyPreserveHost On
ProxyPass / http://192.168.1.102/
ProxyPassReverse / http://192.168.1.102/
# Logging configuration
ErrorLog ${APACHE_LOG_DIR}/beta-error.log
CustomLog ${APACHE_LOG_DIR}/beta-access.log combined
</VirtualHost>
To ensure ONLY beta.example.com traffic gets proxied to Server 2, we'll add additional security measures:
<VirtualHost *:80>
ServerName beta.example.com
<Location />
Order allow,deny
Allow from all
# Prevent direct IP access
Deny from 192.168.1.102
</Location>
ProxyRequests Off
ProxyPreserveHost On
ProxyPass / http://192.168.1.102/
ProxyPassReverse / http://192.168.1.102/
</VirtualHost>
For HTTPS support with Let's Encrypt:
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerName beta.example.com
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/beta.example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/beta.example.com/privkey.pem
ProxyPreserveHost On
ProxyPass / http://192.168.1.102/
ProxyPassReverse / http://192.168.1.102/
</VirtualHost>
</IfModule>
After making these changes:
- Run
sudo apache2ctl configtest
to check for syntax errors - Reload Apache:
sudo systemctl reload apache2
- Test with:
curl -v http://beta.example.com
curl -v http://example.com
(should NOT proxy)
Here's a common scenario many sysadmins face when working with multiple servers behind a single public IP:
Public IP (example.com) ├── Server 1 (192.168.1.101) - Handles main domain traffic └── Server 2 (192.168.1.102) - Should only handle beta subdomain
The key is to set up proper VirtualHost blocks with conditional proxying. Here's how to implement this on Server 1:
<VirtualHost *:80> ServerName example.com ServerAlias www.example.com DocumentRoot /var/www/html/main # Other main domain configurations </VirtualHost> <VirtualHost *:80> ServerName beta.example.com ProxyPreserveHost On ProxyPass / http://192.168.1.102/ ProxyPassReverse / http://192.168.1.102/ # Optional: Add security restrictions <Location "/"> Require all granted </Location> </VirtualHost>
For more complex scenarios where you need additional conditions, consider using mod_rewrite:
<VirtualHost *:80> ServerName example.com ServerAlias *.example.com RewriteEngine On RewriteCond %{HTTP_HOST} ^beta\.example\.com$ [NC] RewriteRule ^(.*)$ http://192.168.1.102/$1 [P,L] DocumentRoot /var/www/html/main </VirtualHost>
When implementing reverse proxies, always consider these security measures:
- Configure proper ServerName and ServerAlias to prevent host header attacks
- Consider implementing SSL/TLS for all proxied connections
- Set appropriate timeouts: ProxyTimeout 300
- Restrict proxy to only necessary paths
If things don't work as expected, check these aspects:
# Verify Apache modules are loaded apachectl -M | grep -E 'proxy|rewrite' # Check syntax before restarting apachectl configtest # Examine access logs tail -f /var/log/apache2/access.log
Here's a complete configuration with SSL and optimized settings:
<VirtualHost *:443> ServerName beta.example.com SSLEngine on SSLCertificateFile /etc/ssl/certs/example.com.crt SSLCertificateKeyFile /etc/ssl/private/example.com.key ProxyRequests Off ProxyPreserveHost On ProxyPass / http://192.168.1.102/ connectiontimeout=5 timeout=300 ProxyPassReverse / http://192.168.1.102/ <Proxy *> Require all granted </Proxy> ErrorLog ${APACHE_LOG_DIR}/beta-error.log CustomLog ${APACHE_LOG_DIR}/beta-access.log combined </VirtualHost>