How to Redirect Multiple Hostnames to a Single Domain in Apache Using Mod_Rewrite


2 views

When configuring Apache to handle multiple domain aliases pointing to the same content, we encounter an interesting behavior where all requests are internally served using the ServerName value. This becomes problematic when you need to:

  • Properly detect the original requested hostname
  • Implement conditional redirects based on the request URL
  • Maintain SEO-friendly redirects

Here's the typical configuration that doesn't work for our purposes:

<VirtualHost *:80>
    ServerName www.example.com
    ServerAlias foo.example.com bar.example.com example.com
    DocumentRoot /var/www/html
    
    # This won't work as expected
    RewriteEngine On
    RewriteCond %{HTTP_HOST} !^www\.example\.com$ [NC]
    RewriteRule ^(.*)$ http://www.example.com$1 [L,R=301]
</VirtualHost>

The key is to capture the original host header before Apache normalizes it:

<VirtualHost *:80>
    ServerName www.example.com
    ServerAlias foo.example.com bar.example.com example.com
    DocumentRoot /var/www/html
    
    RewriteEngine On
    
    # Capture original host before Apache processes it
    RewriteCond %{HTTP:X-Forwarded-Host} !^www\.example\.com$ [NC,OR]
    RewriteCond %{HTTP:X-Forwarded-Host} ^$
    RewriteCond %{HTTP_HOST} !^www\.example\.com$ [NC]
    RewriteRule ^(.*)$ http://www.example.com$1 [L,R=301]
</VirtualHost>

For more complex scenarios, consider this pattern:

# Catch-all for non-www domains
<VirtualHost *:80>
    ServerName example.com
    ServerAlias foo.example.com bar.example.com
    
    RewriteEngine On
    RewriteRule ^(.*)$ http://www.example.com$1 [L,R=301]
</VirtualHost>

# Primary domain configuration
<VirtualHost *:80>
    ServerName www.example.com
    DocumentRoot /var/www/html
    
    # Your main configuration here
</VirtualHost>
  • Always use 301 (permanent) redirects for SEO purposes
  • Test with curl -I to verify response headers
  • Consider SSL/TLS configurations if using HTTPS
  • Monitor your .htaccess for conflicts if used
<VirtualHost *:80>
    ServerName www.example.com
    ServerAlias example.com *.example.com
    
    # Log formats
    LogFormat "%{Host}i %h %l %u %t \"%r\" %>s %b" vhost_combined
    CustomLog ${APACHE_LOG_DIR}/access.log vhost_combined
    
    RewriteEngine On
    
    # Handle naked domain
    RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
    RewriteRule ^(.*)$ http://www.example.com$1 [L,R=301]
    
    # Handle subdomains
    RewriteCond %{HTTP_HOST} !^www\.example\.com$ [NC]
    RewriteCond %{HTTP_HOST} ^([a-z0-9-]+)\.example\.com$ [NC]
    RewriteRule ^(.*)$ http://www.example.com$1 [L,R=301]
</VirtualHost>

When implementing domain consolidation in Apache2, many developers encounter a fundamental behavior: VirtualHosts always serve content using the primary ServerName, even when accessed via ServerAlias entries. This makes it impossible to perform conditional redirects based on the requested hostname without additional configuration.

Apache's documented behavior states that requests matching any ServerAlias pattern will be processed by the VirtualHost but will inherit the ServerName in server variables. This explains why mod_rewrite always sees the primary domain:

# Typical problematic configuration

    ServerName www.example.com
    ServerAlias example.com *.example.com foo.example.com
    DocumentRoot /var/www/html
    
    RewriteEngine On
    RewriteCond %{HTTP_HOST} !^www\.example\.com$ [NC]
    RewriteRule ^(.*)$ http://www.example.com$1 [R=301,L]

The most reliable approach involves creating a dedicated VirtualHost that captures all non-canonical domains before they reach your primary host:

# Catch-all redirect VirtualHost (must appear FIRST in config)

    ServerName example.com
    ServerAlias *.example.com
    
    RewriteEngine On
    RewriteRule ^(.*)$ http://www.example.com$1 [R=301,L]


# Primary VirtualHost (must appear SECOND)

    ServerName www.example.com
    DocumentRoot /var/www/html
    # Normal configuration here

For simpler cases where you control all domains, you can use this more concise approach:


    ServerName www.example.com
    ServerAlias example.com *.example.com
    
    RewriteEngine On
    RewriteCond %{HTTP_HOST} !^www\.example\.com$ [NC]
    RewriteRule ^(.*)$ http://www.example.com$1 [R=301,L]
    
    DocumentRoot /var/www/html

  • Order Matters: VirtualHosts are processed in configuration file order
  • SSL Certificates: For HTTPS, ensure your certificate covers all aliases
  • Performance: Redirects add extra HTTP requests - minimize their use

Always verify your setup with curl:

curl -I http://example.com
curl -I http://foo.example.com
curl -I http://www.example.com

Look for 301 Moved Permanently responses from non-canonical domains and direct serving from your primary domain.

For complete solutions, duplicate your redirect logic in both protocol blocks:

# HTTP redirect

    ServerName example.com
    ServerAlias *.example.com
    Redirect permanent / https://www.example.com/


# HTTPS canonical host

    ServerName www.example.com
    SSLEngine on
    # SSL certificate configuration...
    
    # Optional: Secondary HTTPS redirect
    RewriteEngine On
    RewriteCond %{HTTP_HOST} !^www\.example\.com$ [NC]
    RewriteRule ^(.*)$ https://www.example.com$1 [R=301,L]