Host multiple sites with Apache virtual hosts
Apache calls this name-based virtual hosting. Each site gets its own file in /etc/apache2/sites-available/ that names the domain with ServerName, lists other names with ServerAlias, and points to its own folder. Apache matches the Host header of each request to the right virtual host.
Before you begin
- Apache installed and running. See Install and configure Apache.
- Two domains to host. This guide uses example.com and example.org.
- A sudo user, such as deploy, and the server's IP address, 203.0.113.10.
Step 1: Create a folder for each site
Create a document root for each domain and give your user ownership so you can edit the files without sudo. Then add a test page to the first site.
sudo mkdir -p /var/www/example.com/public_html /var/www/example.org/public_html
sudo chown -R $USER:$USER /var/www/example.com /var/www/example.org
echo "<h1>Welcome to example.com</h1>" > /var/www/example.com/public_html/index.html
Step 2: Create a virtual host file
Open a new file with sudo nano /etc/apache2/sites-available/example.com.conf and enter the following. The Directory block sets permissions for the folder, and Options -Indexes stops Apache from listing files when no index page exists.
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
ServerAdmin webmaster@example.com
DocumentRoot /var/www/example.com/public_html
<Directory /var/www/example.com/public_html>
Options -Indexes +FollowSymLinks
AllowOverride None
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/example.com-error.log
CustomLog ${APACHE_LOG_DIR}/example.com-access.log combined
</VirtualHost>
Step 3: Repeat for the second site
Create /etc/apache2/sites-available/example.org.conf with the same structure. Change the domain names, the DocumentRoot and the log file names to match example.org, and add a test page in its public_html folder.
Step 4: Enable the sites and disable the default
a2ensite links a site into the active configuration, and a2dissite removes that link. Apache ships with a default site called 000-default, which you can disable so it does not answer requests meant for your domains.
sudo a2ensite example.com.conf
sudo a2ensite example.org.conf
sudo a2dissite 000-default.conf
To activate the new configuration, you need to run:
systemctl reload apache2
ServerName, every request may land on the wrong site.Step 5: Test and reload
Check the configuration, then reload Apache so the changes take effect.
sudo apache2ctl configtest
sudo systemctl reload apache2
Syntax OK
Step 6: Test each site by name
Send requests with the Host header set to each domain. This works before DNS points at your server.
curl -H "Host: example.com" http://203.0.113.10/
curl -H "Host: example.org" http://203.0.113.10/
<h1>Welcome to example.com</h1>
<h1>Welcome to example.org</h1>
Step 7: Review the virtual host map
To see how Apache has interpreted your files, list every virtual host with its port and names:
sudo apache2ctl -S
Each site should appear with its ServerName and DocumentRoot. If a site is missing, it is probably not enabled.
Troubleshooting
- The wrong site appears for a domain. Check the output of
sudo apache2ctl -S. Make sure each file has its ownServerNameand that no two files claim the same name. - 403 Forbidden. The
Require all grantedline may be missing, or the folder is not readable. Confirm theDirectoryblock matches yourDocumentRoot. - A warning about the fully qualified domain name. Apache could not determine a server name. Silence it with
echo "ServerName localhost" | sudo tee /etc/apache2/conf-available/servername.conf, then runsudo a2enconf servernameand reload Apache. - configtest fails. The message names the file and line. Fix it and run configtest again before reloading.
Next steps
Once both domains respond, add HTTPS with Enable HTTPS with free TLS certificates. Then use Redirect HTTP to HTTPS and www to non-www so every visitor reaches one secure address.
Something not working? Chat or email our support team and we will help you get unstuck.
Contact support