How to Configure Apache Wildcard ServerName for Name-Based Virtual Hosting with Multiple TLDs


1 views

When setting up name-based virtual hosting with wildcard ServerName directives in Apache, many administrators encounter unexpected behavior where requests always default to the first defined VirtualHost. This occurs particularly when using multiple custom TLDs (like *.test and *.dev) with VirtualDocumentRoot.

Contrary to common assumption, Apache doesn't perform pattern matching when selecting among multiple wildcard ServerName entries. The selection follows this order:

  1. Exact ServerName match
  2. Exact ServerAlias match
  3. First defined VirtualHost if no exact matches

In your configuration:

NameVirtualHost 10.10.0.205

<VirtualHost 10.10.0.205>
   ServerName *.test
   VirtualDocumentRoot /var/www/%-3.0.%-2/test/%1/
</VirtualHost>

<VirtualHost 10.10.0.205>
   ServerName *.dev
   VirtualDocumentRoot /var/www/%-3.0.%-2/dev/%1/
</VirtualHost>

Apache treats *.test and *.dev as literal strings, not as patterns to match against. This explains why requests to www.domain.com.dev always hit the first VirtualHost.

Option 1: Use Separate IP Addresses

The most straightforward solution is to assign different IPs to each TLD:

NameVirtualHost 10.10.0.205
NameVirtualHost 10.10.0.206

<VirtualHost 10.10.0.205>
   ServerName test
   VirtualDocumentRoot /var/www/%-3.0.%-2/test/%1/
</VirtualHost>

<VirtualHost 10.10.0.206>
   ServerName dev
   VirtualDocumentRoot /var/www/%-3.0.%-2/dev/%1/
</VirtualHost>

Option 2: Use mod_rewrite for TLD Routing

More flexible solution using rewrite rules:

NameVirtualHost 10.10.0.205

<VirtualHost 10.10.0.205>
   ServerName vhost-router
   
   RewriteEngine On
   
   # Capture the TLD part
   RewriteCond %{HTTP_HOST} \.([a-z]+)$
   RewriteCond %1 ^(test|dev)$
   
   # Route to appropriate directory structure
   RewriteRule ^(.*)$ /var/www/%-3.0.%-2/%1/%1/ [L]
   
   VirtualDocumentRoot /var/www/%-3.0.%-2/%1/%1/
</VirtualHost>

Option 3: Use mod_vhost_alias with ServerAlias

Alternative approach with explicit ServerAlias entries:

NameVirtualHost 10.10.0.205

<VirtualHost 10.10.0.205>
   ServerName test
   ServerAlias *.test
   VirtualDocumentRoot /var/www/%-3.0.%-2/test/%1/
</VirtualHost>

<VirtualHost 10.10.0.205>
   ServerName dev
   ServerAlias *.dev
   VirtualDocumentRoot /var/www/%-3.0.%-2/dev/%1/
</VirtualHost>

For production environments, consider these approaches:

  • Use dedicated IP addresses when possible
  • Combine with mod_macro for maintainability
  • Implement proper DNS wildcard records
  • Use consistent directory naming conventions

Always verify your setup with:

apachectl -S
curl -v http://test.example.dev
tail -f /var/log/apache2/access.log

Remember that DNS resolution must be properly configured for your custom TLDs to work correctly.


When dealing with name-based virtual hosts in Apache, many developers assume that wildcard ServerName directives (*.test, *.dev) will follow intuitive pattern matching rules. However, the actual behavior is more nuanced:

# Problematic configuration example:
NameVirtualHost 10.10.0.205


   ServerName *.test
   VirtualDocumentRoot /var/www/%-3.0.%-2/test/%1/



   ServerName *.dev
   VirtualDocumentRoot /var/www/%-3.0.%-2/dev/%1/

Apache's vhost selection algorithm doesn't perform wildcard pattern matching the way you might expect. Instead:

  1. It first looks for an exact ServerName match
  2. Then checks ServerAlias for exact matches
  3. If no match found, uses the first defined VirtualHost for that IP:port combination

Here are three proven approaches to achieve your goal:

Option 1: Use Separate IP Addresses

NameVirtualHost 10.10.0.205
NameVirtualHost 10.10.0.206


   ServerName whatever.test
   VirtualDocumentRoot /var/www/%-3.0.%-2/test/%1/



   ServerName whatever.dev
   VirtualDocumentRoot /var/www/%-3.0.%-2/dev/%1/

Option 2: Use mod_rewrite in Fallback VHost


   ServerName fallback.example.com
   
   RewriteEngine On
   RewriteCond %{HTTP_HOST} ^(.*)\.dev$
   RewriteRule ^(.*)$ http://%1.dev$1 [L]
   
   # Similar rule for .test domains

Option 3: Use mod_vhost_alias with ServerPath


   ServerName catch-all
   ServerPath "/dev/"
   VirtualDocumentRoot /var/www/%-3.0.%-2/dev/%1/
   
   
      RewriteEngine On
      RewriteCond %{REQUEST_URI} !^/dev/
      RewriteRule ^(.*)$ /dev/$1
   

  • Always place your most specific VirtualHost definitions first
  • Use ServerAlias for additional domain patterns
  • Consider using mod_macro to reduce configuration duplication
  • Test with apachectl -S to verify your vhost matching order

Add these directives to your vhosts for better debugging:

LogLevel debug
CustomLog /var/log/apache2/vhost-access.log "%v %h %l %u %t \"%r\" %>s %b"