Configure Apache virtual hosts

Apache virtual hosts

Objectives

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

Prerequisites

  • 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.

Our setup

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: <my_site>.home.local.

Apache configuration

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.

httpd.conf

The location of the apache configuration file may vary depending on your linux distribution, we're going to assume it is located at /etc/httpd/conf/httpd.conf.

$ 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.

The Require directive only works on versions above 2.3.
Older versions use Order allow,deny and Allow from all

The 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 <Location> directive.

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

		

Apache authentication

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 /etc/httpd/htpasswd/.htpasswd. The Authname parameter will be shown to users in the password dialog box.

Authentication window screenshot

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.

Hosts file

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).

Server restart

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.

Further reading