Serving Multiple Domains on One Apache Server Using Virtual Hosts
Learn how to use Apache Virtual Hosts to serve multiple domain names from a single server IP, including configuration examples and verification steps.
15 Feb 2026, 03:27 UTC

The Solution: Name-Based Virtual Hosting
When you need to host multiple websites (e.g., site-a.com and site-b.com) on a single server with one IP address, Apache uses Name-Based Virtual Hosting. Instead of assigning a unique IP to every domain, Apache inspects the HTTP Host header sent by the browser to determine which directory (DocumentRoot) should handle the request.
Implementing Virtual Host Configurations
To enable multiple domains, you must define separate <VirtualHost> blocks. In modern Debian or Ubuntu installations, these are typically placed in separate files within /etc/apache2/sites-available/ and enabled via the a2ensite command. On RHEL/CentOS, they are often added to httpd.conf or a dedicated conf.d directory.
Below is a configuration for two distinct domains serving content from separate directories:
# Configuration for Site A
<VirtualHost *:80>
ServerName site-a.com
ServerAlias www.site-a.com
DocumentRoot /var/www/site-a
ErrorLog ${APACHE_LOG_DIR}/site-a_error.log
CustomLog ${APACHE_LOG_DIR}/site-a_access.log combined
</VirtualHost>
# Configuration for Site B
<VirtualHost *:80>
ServerName site-b.com
ServerAlias www.site-b.com
DocumentRoot /var/www/site-b
ErrorLog ${APACHE_LOG_DIR}/site-b_error.log
CustomLog ${APACHE_LOG_DIR}/site-b_access.log combined
</VirtualHost>
Key Directive Definitions
- ServerName: The primary domain name the server uses to identify the virtual host. This must match the domain the user types in their browser.
- ServerAlias: Additional names that should map to this same host (e.g., mapping both the root domain and the
wwwsubdomain to the same folder). - DocumentRoot: The absolute path to the folder containing the website's HTML and assets.
Verification and Deployment
Before restarting the server, you must verify that there are no syntax errors in your configuration files. Run the following command as a user with sudo privileges:
# Check configuration syntax
sudo apachectl configtest
If the output returns Syntax OK, reload the service to apply changes:
# Reload Apache to apply changes without dropping current connections
sudo systemctl reload apache2
To verify that the routing is working correctly without relying on external DNS, use curl to simulate a request for a specific host:
# Test Site A routing
curl -H "Host: site-a.com" http://localhost/
# Test Site B routing
curl -H "Host: site-b.com" http://localhost/
Operational Limits and Common Pitfalls
While Virtual Hosting is scalable, there are engineering constraints to consider:
- The Default Host: If a request arrives for a domain that is not defined in any
ServerNameorServerAlias, Apache serves the first virtual host loaded in the configuration. To prevent this, define a "catch-all" virtual host at the top of your config to return a 403 Forbidden or 404 Not Found. - File Descriptor Limits: Each virtual host may open multiple log files and directory handles. If hosting hundreds of domains, you may hit the system's open file limit (
ulimit -n), leading to "Too many open files" errors in the logs. - Memory Overhead: While the memory cost per vhost is low, complex configurations with many
.htaccessfiles across different DocumentRoots can increase memory consumption and slow down request processing.
Common Mistakes
| Mistake | Result | Fix |
|---|---|---|
| Omitting ServerName | Request maps to the first loaded vhost regardless of domain. | Ensure every <VirtualHost> block has a unique ServerName. |
| Overlapping IP/Port | Apache may fail to start or route traffic unpredictably. | Use *:80 for all name-based hosts on the same port. |
| Incorrect Permissions | 403 Forbidden errors. | Ensure the www-data or apache user has read/execute permissions on the DocumentRoot. |
Rollback Procedure
If the new configuration causes instability or routing errors, remove the newly created configuration files from the enabled sites directory and reload the service:
# Disable the problematic site (Debian/Ubuntu)
sudo a2dissite site-a.conf
sudo systemctl reload apache20 replies
A thoughtful contribution can make all the difference. Be the first to share one.