Apache VirtualHost Configuration: Why Requests Are Served by Default Host Despite Matching ServerName


1 views

When dealing with multiple VirtualHosts in Apache, it's frustrating to see requests being served by the default host instead of the intended VirtualHost, even when the ServerName matches perfectly. Let's dive into why this happens and how to fix it.

In the described scenario, we have two VirtualHost configurations:

# First VirtualHost (default)
<VirtualHost _default_:80>
    ServerName radiofreebrighton.org.uk
    # ... other configs ...
</VirtualHost>

# Second VirtualHost
<VirtualHost *:80>
    ServerName trafalgararches.co.uk
    # ... other configs ...
</VirtualHost>

The key issue lies in using _default_:80 in the first VirtualHost definition. This makes it the default catch-all host for port 80. Apache will use this VirtualHost when:

  1. No matching ServerName is found
  2. The IP address doesn't match
  3. The request comes on a non-standard port

Apache matches VirtualHosts in this order:

1. IP address and port
2. ServerName
3. ServerAlias
4. First defined VirtualHost (if none match)

Change both VirtualHosts to use the same format:

# First VirtualHost
<VirtualHost *:80>
    ServerName radiofreebrighton.org.uk
    ServerAlias www.radiofreebrighton.org.uk
    DocumentRoot /home/tom/www
    # ... other configs ...
</VirtualHost>

# Second VirtualHost
<VirtualHost *:80>
    ServerName trafalgararches.co.uk
    ServerAlias www.trafalgararches.co.uk
    DocumentRoot /home/tom/tata-www
    # ... other configs ...
</VirtualHost>

After making changes, verify with:

sudo apache2ctl configtest
sudo apache2ctl -S
sudo systemctl restart apache2

For more reliable VirtualHost matching:

# Always include the port
NameVirtualHost *:80

# Consider adding IP-based VirtualHosts if needed
<VirtualHost 192.168.1.1:80>
    # ...
</VirtualHost>

# Use separate error logs for debugging
ErrorLog /var/log/apache2/trafalgararches_error.log

If issues persist, check:

# Check which VirtualHost is being matched
curl -v http://trafalgararches.co.uk

# Verify DNS resolution
dig trafalgararches.co.uk

# Check for cached configurations
sudo apache2ctl stop
sudo apache2ctl start

Here's a complete working example:

NameVirtualHost *:80

<VirtualHost *:80>
    ServerName primary.example.com
    DocumentRoot /var/www/primary
    # ... other directives ...
</VirtualHost>

<VirtualHost *:80>
    ServerName secondary.example.com
    DocumentRoot /var/www/secondary
    # ... other directives ...
</VirtualHost>

When Apache receives a request, it selects the VirtualHost in this order:

  1. Explicit IP:port match
  2. First defined VirtualHost for the IP:port (when no match found)
  3. _default_ VirtualHost (if defined)

In your case, the issue stems from using _default_:80 in your first VirtualHost while the second uses *:80.

Your primary VirtualHost is defined as:

<VirtualHost _default_:80>
    # ... radiofreebrighton config ...
</VirtualHost>

While the second uses:

<VirtualHost *:80>
    # ... trafalgararches config ...
</VirtualHost>

The _default_ VirtualHost acts as a catch-all for requests that don't match any other VirtualHosts. When combined with NameVirtualHost, this creates unexpected behavior.

Change both VirtualHosts to use the same IP:port format:

<VirtualHost *:80>
    ServerName radiofreebrighton.org.uk
    # ... rest of config ...
</VirtualHost>

<VirtualHost *:80>
    ServerName trafalgararches.co.uk
    # ... rest of config ...
</VirtualHost>

After making changes:

  • Run apache2ctl configtest to check syntax
  • Use apache2ctl -S to verify VirtualHost order
  • Clear browser cache and test with curl: curl -H "Host: trafalgararches.co.uk" http://localhost

For better maintainability, consider using separate files with consistent naming:

# /etc/apache2/sites-available/radiofreebrighton.conf
<VirtualHost *:80>
    # Primary domain should be listed first
    ServerName radiofreebrighton.org.uk
    ServerAlias www.radiofreebrighton.org.uk
    DocumentRoot /var/www/radiofreebrighton
    # ... other directives ...
</VirtualHost>

# /etc/apache2/sites-available/trafalgararches.conf
<VirtualHost *:80>
    ServerName trafalgararches.co.uk
    ServerAlias www.trafalgararches.co.uk
    DocumentRoot /var/www/trafalgararches
    # ... other directives ...
</VirtualHost>