I want to:
- Access my different sites by name rather than by IP, i.e my_awesome_site.local instead of 192.168.0.1/my/local/site
- A linux distribution with Apache installed
What is a virtual host?
In the simplest of cases, you're running one website on your machine. You type in an IP address on your browser, the browser queries the server at that address, which delivers the content. One site running on one server. But what happens if I want my server to host multiple sites? That's where virtual hosts come in.
Virtual hosts are merely a way for Apache to route requests to the proper machine or folder depending on the defined naming scheme. From the user's point of view, the websites look like they're hosted on the same server.
In this tutorial, we're going to assume that we want to run a blog, a forum and a general website on the same machine. The server location for our files and folders is
/var/www, with one folder per project, as so:
- /var/www/wordpress for our blog,
- /var/www/phpbb for our forum,
- /var/www/slim for our website
We want to have access to those sites using hostnames, following the convention:
First, we're going to make sure that our configuration is clean by only modifying the main Apache config if we absolutely have to. Apache will be instructed to look for our virtual host configuration in a separate file.
The location of the apache configuration file may vary depending on your linux distribution, we're going to assume it is located at
$ vi /etc/httpd/conf/httpd.conf
We can jump directly to the end of the file by pressing "G". Lines marked with "#" are comments, so feel free to add a sentence or two about why changes are made. We're going to go with:
# Supplemental configuration # # Load config files in the “/etc/httpd/conf.d” directory, if any. IncludeOptional conf.d/*.conf
That line will instruct Apache to load any file with the conf extension located in the
conf.d folder. We save this file and edit our vhosts configuration file:
$ vi /etc/httpd/conf.d/vhosts.conf
Our file will look something like this:
# Configuration for the main website # Available at home.local <VirtualHost *:80> # The server name you want to use for this project ServerName home.local # Where files are located DocumentRoot /var/www/slim # Where Apache can write error logs ErrorLog /var/www/slim/logs/error.log # Permissions on the main directory <Directory /var/www/slim> # The permissions can be overridden by a .htaccess file for example AllowOverride All # Allow access to resources Require all granted </Directory> </VirtualHost> # Configuration for the forum # Available at forum.home.local <VirtualHost *:80> ServerName forum.home.local DocumentRoot /var/www/phbb ErrorLog /var/www/phbb/logs/error.log <Directory /var/www/phbb> AllowOverride All Require all granted </Directory> </VirtualHost> # Configuration for the blog # Available at blog.home.local <VirtualHost *:80> ServerName blog.home.local DocumentRoot /var/www/wordpress ErrorLog /var/www/wordpress/error.log <Directory /var/www/wordpress> AllowOverride All Require all granted </Directory> </VirtualHost>
Apache versions below 2.3.11 will require a
NameVirtualHost directive to handle host name based requests.
Require directive only works on versions above 2.3.
Older versions use
Order allow,deny and
Allow from all
VirtualHost *:80 instructs Apache to listen on all IP addresses defined in the main configuration file on port 80. Permissions can be defined for a location on the file system using the
<Directory> directive or to a relative url using the
The location directive
Using the location directive, we can specify specific access rights for URLs as opposed to locations in the file system.
For example, if a location on your site should only be accessible to a specific IP, the following section can be added to the virtual host:
Deny from all Allow from 10.25.100.254
In the following example, we want Apache to ask the user for a username and password before they can access the content. Our virtualhost configuration would look like this:
<VirtualHost *:80> ServerName auth.home.local DocumentRoot /var/www/secure <Directory /var/www/secure> AllowOverride None AuthType Digest AuthName "private area" AuthUserFile "/etc/httpd/htpasswd/.htpasswd" Require valid-user </Directory> </VirtualHost>
In this example, Apache will expect passwords to be stored into a file, so we'll create a directory and store the file at
Authname parameter will be shown to users in the password dialog box.
Apache uses it to define the authentication realm, which can be useful to admins to categorize their different types of access. Apache provides the htdigest tool for creating password files.
$ htdigest -c /etc/httpd/htpasswd/.htpasswd "private area" admin New password: mypassword Re-type new password: mypassword Adding password for user admin
We took the digest authentication route in this example, but Apache supports many other authentication methods.
At the server level, we instruct Apache to resolve all these virtual hostnames to the local IP address on which it is listening for incoming connections.
At the client level, you need to make sure those hostnames get resolved into IP addresses by filling in your hosts file.
On the machine you use as a client, the browser will be looking for entries in the hosts file that match the hostnames you're providing, which would look something like this:
192.168.0.100 home.local 192.168.0.100 forum.home.local 192.168.0.100 blog.home.local
If those entries can't be found, the browser will do a DNS lookup for those hostnames and prefix the hostname with www. Since we have a local setup, there's no way this lookup is going to succeed (unless the hostname you chose actually matches a DNS record).
Once the vhosts.conf file has been saved, you can test your Apache configuration:
$ apachectl configtest
Provided Apache gives you the thumbs up, you can then restart the Apache server:
$ /sbin/service httpd restart
$ /etc/init.d/httpd graceful
would be the preferred way of restarting the Apache server as it instructs the main httpd process to tell every child process to exit after they're done, as opposed to just killing all sub-processes immediately.
You should then be able to access your sites using the newly defined virtual hostnames.