Optimizing Apache VirtualHost Config: Auto-Redirecting ServerAlias to ServerName with 301


2 views

When managing multiple domain variations, the standard approach of creating separate VirtualHost blocks for redirects becomes cumbersome:

<VirtualHost 192.0.2.123:80>
        ServerName      example.org
        RedirectPermanent       /               http://www.example.org/
</VirtualHost>
<VirtualHost 192.0.2.123:80>
        ServerName      www.example.org
        DocumentRoot    /usr/local/www/example
</VirtualHost>

We can significantly simplify the configuration using Apache's mod_rewrite while maintaining the same functionality:

<VirtualHost 192.0.2.123:80>
    ServerName www.example.org
    ServerAlias example.org *.example.org
    
    RewriteEngine On
    RewriteCond %{HTTP_HOST} !^www\.example\.org$ [NC]
    RewriteRule ^(.*)$ http://www.example.org$1 [L,R=301]
    
    DocumentRoot /usr/local/www/example
</VirtualHost>

This configuration works by:

  • Listing all domain variations under ServerAlias
  • Using mod_rewrite to check if the requested host doesn't match our canonical domain (www.example.org)
  • Redirecting all non-canonical requests with a 301 permanent redirect

While the mod_rewrite solution is more maintainable, it's worth noting that using RedirectPermanent might have slightly better performance as it's handled earlier in Apache's request processing pipeline. However, the difference is negligible for most use cases.

For those who prefer not to use mod_rewrite, here's an alternative solution:

<VirtualHost 192.0.2.123:80>
    ServerName www.example.org
    ServerAlias example.org
    
    RedirectMatch permanent ^/(.*)$ http://www.example.org/$1
    
    DocumentRoot /usr/local/www/example
</VirtualHost>

When implementing SSL, the redirect should happen before the SSL handshake. Here's how to modify the solution:

<VirtualHost *:80>
    ServerName www.example.org
    ServerAlias example.org
    
    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule ^(.*)$ https://www.example.org$1 [L,R=301]
</VirtualHost>

<VirtualHost *:443>
    ServerName www.example.org
    ServerAlias example.org
    
    # SSL configuration here...
    
    RewriteEngine On
    RewriteCond %{HTTP_HOST} !^www\.example\.org$ [NC]
    RewriteRule ^(.*)$ https://www.example.org$1 [L,R=301]
    
    DocumentRoot /usr/local/www/example
</VirtualHost>

After implementing these changes, always test with:

apachectl configtest
curl -I http://example.org
curl -I http://www.example.org

When configuring Apache web servers, a common requirement is to redirect all alias domains to the primary domain (typically the www version). The traditional method involves creating separate VirtualHost blocks for each alias:


        ServerName      example.org
        RedirectPermanent       /               http://www.example.org


        ServerName      www.example.org
        DocumentRoot    /usr/local/www/example

While this works perfectly, it becomes cumbersome when managing multiple domains or when domains frequently change. Each new alias requires a new VirtualHost block, leading to configuration bloat.

We can achieve the same result with a cleaner configuration using mod_rewrite within a single VirtualHost:


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

This configuration:

  • Handles all requests for www.example.org normally
  • 301 redirects any other matching domain (example.org, sub.example.org) to www.example.org
  • Maintains the original request path
  • Keeps all configuration in one place

For more complex scenarios, you might want to consider these enhancements:

Multiple primary domains:

RewriteCond %{HTTP_HOST} !^(www\.example\.org|example\.com)$ [NC]
RewriteRule ^(.*)$ http://www.example.org$1 [L,R=301]

SSL/TLS enforcement:

RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} !^www\.example\.org$ [NC]
RewriteRule ^(.*)$ https://www.example.org$1 [L,R=301]

While mod_rewrite is more flexible, the original RedirectPermanent method might be slightly more efficient for simple cases. However, the difference is negligible for most applications, and the maintenance benefits of the mod_rewrite approach usually outweigh any minor performance impact.

Always test your redirects thoroughly. Useful commands:

apachectl configtest  # Check syntax
curl -I http://example.org  # Verify response headers
curl -I http://sub.example.org  # Test all aliases