Apache ProxyPass Configuration: Routing Specific Subdomains to Backend Servers


4 views

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:

  1. Run sudo apache2ctl configtest to check for syntax errors
  2. Reload Apache: sudo systemctl reload apache2
  3. 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>