Quick Links

Apache Virtual Hosts are a feature which let you host multiple independent websites from one Apache installation. Each site has its own filesystem directory and domain name. You can serve different sites to different visitors based on the domain they're using.

Virtual Hosts are created using the

        <VirtualHost>
    

directive in Apache configuration files. They're normally stored in the sites-available directory within Apache's installation location. On Debian systems, this is usually

        /etc/apache2
    

; other distributions may use

        /etc/httpd
    

.

We'll assume you've already got Apache up-and-running. We'll create two separate Virtual Hosts, a.example.com and b.example.com. There's no limit to the number of Virtual Hosts you can use - if you need a dozen sites on one server, Apache will oblige.

Configuring the Sites

Each site needs its own filesystem directory. You'll place the website's files, such as HTML, CSS and JavaScript, within this directory. It's termed the DocumentRoot by Apache, as it's the root from which documents are served.

You can locate your sites anywhere on your system. You'll often see Virtual Hosts stored within /var/www, with each site getting its own folder:

sudo mkdir -p /var/www/a.example.com

sudo mkdir -p /var/www/b.example.com

/var/www is normally owned by root, so we're using sudo to create the sub-directories. Next, change the ownership of the document roots to your own user and set appropriate permissions. This will allow Apache to read files while giving you write access so you can add your content.

sudo chown -R $USER:$USER /var/www/a.example.com

sudo chown -R $USER:$USER /var/www/b.example.com

sudo chmod -R 755 /var/www

Copy your website files into the directories. We'll use two simple index.html files:

a.example.com/index.html

<html>

<body>

<h1>a.example.com</h1>

</body>

</html>

b.example.com/index.html

<html>

<body>

<h1>b.example.com</h1>

</body>

</html>

Configuring Apache

Now you're ready to configure your Virtual Hosts. Create a new Virtual Host file for each of the sites. It doesn't matter what you name the file; by convention, it usually matches your site's hostname.

At minimum, each Virtual Host needs to declare two properties:

  • ServerName - The hostname (domain) that the site is going to be served from.
  • DocumentRoot - The filesystem location to serve for this Virtual Host.

Here's an example configuration for our two sites:

/etc/apache2/sites-available/a.example.com.conf

<VirtualHost *:80>

ServerName a.example.com

DocumentRoot /var/www/a.example.com

</VirtualHost>

/etc/apache2/sites-available/b.example.com.conf

<VirtualHost *:80>

ServerName b.example.com

DocumentRoot /var/www/b.example.com

</VirtualHost>

This basic setup is enough to get the two sites live! The *:80 means Apache will consider using this Virtual Host for any request arriving on port 80. They'll be disambiguated later on by the ServerName declarations.

Enabling Virtual Hosts

Adding a Virtual Host to sites-available makes it available but not active. You need to manually enable each site you want to use. Virtual Host configs to enable should be symlinked into /etc/apache2/sites-enabled (or /etc/httpd/sites-enabled).

On Debian systems, you can use the a2ensite command to simplify this step:

a2ensite a.example.com

a2ensite b.example.com

On other distributions, use the ln command to create a symlink manually.

sudo ln -s /etc/httpd/sites-available/a.example.com.conf /etc/httpd/sites-enabled/a.example.com.conf

sudo ln -s /etc/httpd/sites-available/a.example.com.conf /etc/httpd/sites-enabled/b.example.com.conf

Finally, restart Apache to apply your new configuration. Virtual Host changes require a server restart after you've added them to sites-enabled.

sudo apache2ctl restart

You should now be able to see Apache serving your two different sites. If you've not got DNS resolving to your server, you can modify your system's /etc/hosts file to test your setup.

Add the following lines to /etc/hosts:

127.0.0.1 a.example.com

127.0.0.1 b.example.com

This will force both domains to resolve back to your own system. You'll now be able to visit them in your browser to see the two different Virtual Host pages.

Site Aliases

If you want to serve the same site on multiple domains, use the ServerAlias directive in your Virtual Host. Each alias will be considered when Apache matches your Virtual Host against incoming requests. The Virtual Host will be used if the request's Host header matches a ServerAlias or the ServerName.

<VirtualHost *:80>

ServerName a.example.com

ServerAlias example.com

ServerAlias www.example.com

DocumentRoot /var/www/a.example.com

</VirtualHost>

This example would serve the a site on three domains, without having to repeat any configuration details. You must use ServerAlias to define multiple domains - repeating ServerName is possible but it will override the earlier uses.

Other Configuration Options

Many of Apache's server configuration options can be used with Virtual Hosts. They'll override the global server settings when Apache handles a request using the Virtual Host.

<VirtualHost *:80>

ServerName a.example.com

DocumentRoot /var/www/a.example.com

DirectoryIndex my-index.html

<Directory /var/www/a.example.com>

AllowOverride All

Options -Indexes

Require all granted

</Directory>

ErrorLog ${APACHE_LOG_DIR}/error.log

CustomLog ${APACHE_LOG_DIR}/access.log combined

</VirtualHost>

This Virtual Host applies many more settings. my-index.html is served by default, instead of index.html, and custom logging locations are used. In addition, extra settings are applied to the document root itself, using the Directory block. .htaccess overrides are permitted (AllowOverride All) and Apache's default directory listing pages are disabled (Options -Indexes).

IP Address Hosts

Apache also supports IP-based hosts besides the name-based hosts we've seen so far. IP-based hosts are ideal when your server has multiple network interfaces, such as an internal company network and the public internet. You can serve a different site depending on the network interface used.

<VirtualHost 172.17.0.1>

ServerName a.example.com

DocumentRoot /var/www/a

</VirtualHost>

<VirtualHost 172.17.0.1>

ServerName b.example.com

DocumentRoot /var/www/b

</VirtualHost>

<VirtualHost 192.168.0.1>

ServerName a.example.com

DocumentRoot /var/www/a2

</VirtualHost

In this example, requests made to a.example.com via the interface with IP 192.168.0.1 would receive different content to those sent via 172.17.0.1. In addition, users of the latter IP would be able to access b.example.com. This site isn't exposed to users connecting via 192.168.0.1.

This approach lets you use one server for your corporate intranet and public website. Bind the internal sites to your server's LAN IP; run the public hosts against its WAN address.

Virtual Host Matching

Apache's Virtual Host resolution routine is well-documented and quite straightforward.

In general, Apache tries to match the Host request header against a ServerName or ServerAlias field in a Virtual Host configuration. If there's multiple matches, Apache will use the first matching Virtual Host it found.

Virtual Hosts are sorted in order of filename. If you need a site to match before another, rename its configuration file so it'll sort before the target site. You can add a numerical prefix such as 000-a.example.com.conf. Most of the time this will be unnecessary - if all your sites have unique domains, you should never encounter a conflict.

Conclusion

Apache Virtual Hosts let you break down multi-site configuration into self-contained definition files. You can independently enable and disable each site by linking it into sites-enabled.

Many configuration options are available for Virtual Hosts. You can override some Apache server settings on a per-host basis, so you have full control over each virtualised site setup.