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:
- No matching ServerName is found
- The IP address doesn't match
- 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:
- Explicit IP:port match
- First defined VirtualHost for the IP:port (when no match found)
- _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>