Ubuntu Hardy - Apache Virtual Hosts #1
Now we have Apache installed and running, we can configure it to serve multiple domains using Virtual Hosts.
Do note the layout used in these articles is explained here - feel free to use the directories of your choice.
Create the layout
In this example we'll be using two domains: domain1.com and domain2.com.
In your home directory create a 'public_html' folder:
cd ~
mkdir public_html
Now for each domain we want to host create a folder with a standard set of sub-folders:
mkdir -p public_html/domain1.com/{public,private,log,cgi-bin,backup}
and
mkdir -p public_html/domain2.com/{public,private,log,cgi-bin,backup}
That will create the folders public, private, log, cgi-bin and backup for each of our domains (domain1.com and domain2.com).
index.html
The content of the public folder is, naturally, up to you but for this example I am going to use a very simple html file so we can check the virtual hosts work.
So for each domain create an index.html file:
nano public_html/domain1.com/public/index.html
add the following to the index.html file:
<html>
<head>
<title>domain1.com</title>
</head>
<body>
<h1>domain1.com</h1>
</body>
</html>
Repeat the process so you have a similar file for domain2.com (simply replace all instances of 'domain1.com' with 'domain2.com).
OK. Now we have a basic structure for our two domains we can look at defining two virtual hosts.
NameVirtualHost
With virtual hosts, one thing that often catches people out is the NameVirtualHost setting.
For each port that Apache listens to, we need to define a NameVirtualHost. The issue that can catch people lies in the fact that you can only define it once per port.
In itself, that's no problem but the default vhost has already defined a generic NameVirtualHost - adding another one will cause warnings and errors.
The easiest thing to do is to remove the generic NameVirtualHost from the default vhost file and then add some specific ones to the main apache config file.
That way, if we ever delete or change the default vhost we don't have to worry about where the NameVirtualHost setting is defined and so on.
OK. Let's move into the apache directory and then open the default vhost:
cd /etc/apache2/
...
sudo nano sites-available/default
Delete the 'NameVirtualHost *' line and change the next 'VirtualHost' line so the file begins like this:
<VirtualHost *:80>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/
Once that is done, we can open the main apache2.conf:
sudo nano apache2.conf
Now we can add a specific NameVirtualHost setting for port 80 and a conditional one for port 443 (this conditional setting will only 'work' if we have the SSL module enabled).
So, at the bottom of the apache2.conf the following:
NameVirtualHost *:80
<IfModule mod_ssl.c>
NameVirtualHost *:443
</IfModule>
Let's reload Apache now:
sudo /etc/init.d/apache2 reload
There should be no warnings or errors.
Nice.
Custom Virtual Hosts
We've set up the basics and now we're ready to add our own virtual hosts so we can start to serve our domains.
Let's go ahead and create the vhost file for domain1:
sudo nano /etc/apache2/sites-available/domain1.com
The contents look like this:
# Place any notes or comments you have here
# It will make any customisation easier to understand in the weeks to come
# domain: domain1.com
# public: /home/demo/public_html/domain1.com/
<VirtualHost *:80>
# Admin email, Server Name (domain name) and any aliases
ServerAdmin webmaster@domain1.com
ServerName domain1.com
ServerAlias www.domain1.com
# Index file and Document Root (where the public files are located)
DirectoryIndex index.html
DocumentRoot /home/demo/public_html/domain1.com/public
# Custom log file locations
LogLevel warn
ErrorLog /home/demo/public_html/domain1.com/log/error.log
CustomLog /home/demo/public_html/domain1.com/log/access.log combined
</VirtualHost>
a2ensite
Now we have the site available, we need to enable it:
sudo a2ensite domain1.com
The output of the command is:
Site domain1.com installed; run /etc/init.d/apache2 reload to enable.
Seems like good advice:
sudo /etc/init.d/apache2 reload
Navigate
Now navigate to your site:
http://domain1.com
Tada! You now have the contents of public/index.html being shown:

ServerAlias
Note that in the vhost file, we set a ServerAlias. Providing you have the DNS set up correctly you can also use that address:
http://www.domain1.com
We'll talk about forcing one address or the other in a later article about rewrite rules.
Repeat as necessary
To create and enable domain2.com simply go through the process again:
sudo nano /etc/apache2/sites-available/domain2.com
...
# Enter the details for domain2.com as per the example shown above
Then enable the site and restart Apache:
sudo a2ensite domain2.com
...
sudo /etc/init.d/apache2 reload
Finally navigate to your second domain:
http://domain2.com
or
http://www.domain2.com
All being well, you will see the 'domain2.com' index file.
Log Files
As defined in the vhosts file, each domain has its own log files. Let's take a quick look:
ls /home/demo/public_html/domain1.com/log/
The output is exactly as expected:
access.log error.log
This makes for much easier analysis as each set of logs is self contained.
Default
Remember that although we changed the default virtual host, we did leave it in place.
Now, if someone enters the IP address of the Slice they are served the contents of that default vhosts file (providing, of course, you have not set up a separate vhost for the IP address).
Why are they served from that vhost file?
Apache searches the enabled vhosts in alphabetical order and if it can't find one for the requested IP address or domain name, it serves the first one (alphabetically).
If we had disabled or deleted the default vhost, then the contents of domain1.com would be displayed (being before domain2.com alphabetically).
This is something to keep in mind when planning your websites. Do you want a particular domain to be the default? Do you want the IP address to have completely different content?
Summary
We've gone into some detail here but, overall, setting up a virtual host is relatively easy. Of course, there are many settings and configurations to take into account but you should have your site up and running in no time.
The next virtual host article will look in more detail at some of the settings that are available and what they mean.
PickledOnion.


Article Comments:
Swaroop commented Wed May 21 18:25:21 UTC 2008 ago:
Hey PickledOnion,
Thanks for another great precise article.
Small question though, is it better to use httpd.conf for custom configuration (which is empty in Hardy/Gutsy by default) as opposed to apache2.conf ?
Thanks, Swaroop
Nate commented Thu May 22 17:07:27 UTC 2008 ago:
I'm getting the following error after changing the NameVirtualHost file in "sites-available/default".
Here is what I get: sudo /etc/init.d/apache2 reload apache2: Syntax error on line 298 of /etc/apache2/apache2.conf: Syntax error on line 42 of /etc/apache2/sites-enabled/000-default: Expected </virtualhost> but saw </virtualhost> ...fail!
Changing the end tag isn't recognized and throws another error. Any help?
Nate commented Thu May 22 18:13:51 UTC 2008 ago:
I figured it out. Make sure there is a space between "NameVirtualHost" and "*:80". Correct: NameVirtualHost *:80 Wrong: NameVirtualHost*:80
Ralph commented Tue May 27 22:31:13 UTC 2008 ago:
After adding NameVirtualHost *:80
<ifmodule> NameVirtualHost *:443 </ifmodule>
to apache2.conf and sudo /etc/init.d/apache2 reload I'm getting [warn] NameVirtualHost *:443 has no VirtualHosts Any hints?
Tony Mann commented Tue Jun 03 18:23:02 UTC 2008 ago:
For Apache 2.2.8, the default file contains the following:
If I use the "*:80" syntax per this article, I get errors about missing hosts.
Fritz commented Mon Jun 23 21:44:36 UTC 2008 ago:
I did all the steps, yet when i reload apache2, i get a page that used to exist to "failed to connect" when i load my website
Any ideas?
Xianhang Zhang commented Wed Jun 25 02:20:50 UTC 2008 ago:
I am getting the same error as Fritz
Xianhang Zhang commented Wed Jun 25 21:42:56 UTC 2008 ago:
Figured it out. Apache reload dies silently if there is a syntax error in one of the included files.
try sudo /etc/init.d/apache2 start to see if your apache server is up and running or not.