Ubuntu Intrepid - 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}


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


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:


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.


With virtual hosts, one thing that often confuses people is the NameVirtualHost setting.

For each interface and port on which Apache is set to listen on, we need a NameVirtualHost directive. Something to keep in mind is you can only define it once per port.

In the Apache layout for Ubuntu Intrepid Ibex there is a default NameVirtualHost directive in the 'ports.conf' file. If you've worked through the Apache configuration #1 article for Intrepid, you may remember it being noted previously.

Let's take another look at the contents of 'ports.conf':

cat /etc/apache2/ports.conf

You should get the following output (unless you've previously modified the file):

# If you just change the port or add more ports here, you will likely also
# have to change the VirtualHost statement in
# /etc/apache2/sites-enabled/000-default

NameVirtualHost *:80
Listen 80

<IfModule mod_ssl.c>
    # SSL name based virtual hosts are not yet supported, therefore no
    # NameVirtualHost statement here
    Listen 443

The default NameVirtualHost setting satisfies our requirements at present — Apache will apply named based virtual host logic and settings for HTTP requests made on any available interface (*) at port 80.

NOTE: the placement of the default NameVirtualHost directive in 'ports.conf' is new to Ubuntu Intrepid's Apache layout; prior Ubuntu releases placed a similar setting in the default vhost. If you are working with a pre-Intrepid Ubuntu release (e.g. Hardy or Gutsy), refer to the appropriate "Apache Virtual Hosts" articles listed on the Apache articles pages.

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



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


To test the domain without creating a DNS zone and record(s) on some Internet namserver(s), I've modified the '/etc/hosts' file on my local computer to include some entries mapping 'domain1.com', etc. to the demo Slice's public IP:    localhost

# entries related to the demo slice   domain1.com   www.domain1.com   domain2.com

You can add similar entries in your own 'hosts' file, though it's location will vary depending on what OS is loaded on your local computer (try a Google search).

NOTE: entries in the 'hosts' file will need to be removed prior to testing and using live DNS zones and records created on Internet nameservers. Failure to remove them will likely lead to confusion on your part and inaccurate tests of new or modified public DNS records.

With such changes made for testing purposes, you can navigate to your site in a web browser on your local computer:

Domain1 Home Page

Tada! You now have the contents of public/index.html being shown:


Note that in the vhost file, we set a ServerAlias. Providing you have the DNS set up correctly you can also use that address — for quick testing purposes you can place another entry in your 'hosts' file (I've already done so in the example code given above):

Domain1 Home Page (hostname alias)

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:


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.


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?


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.


Article Comments:

Darren commented Sun Feb 08 04:11:53 UTC 2009:

Your articles are really great!

I tend to read several different "google hits" whenever I am looking for a good how-to... usually I find that I can only find a small piece of the puzzle at each site. After following the instructions, I'm often left thinking "well, it works... but I don't think it's done properly".

After reading though your instructions though, I'm confident that everything is done properly. The fact that you described the differences in Intrepid (with stuff in ports.conf) really saved me time. This was driving me nuts :o)

Thank you!

Yamaplos commented Sat Feb 28 23:28:48 UTC 2009:

I love your articles also, though by now I am on my third day of trying to get RoR to do anything, without success. I have been unable to get beyond this, even following changes on etc/hosts

yama@ybuntu810:~$ sudo /etc/init.d/apache2 restart

  • Restarting web server apache2 Warning: DocumentRoot [/home/demo/public_html/domain1.com/public] does not exist Warning: DocumentRoot [/home/demo/public_html/testapp/public] does not exist Warning: DocumentRoot [/home/demo/public_html/domain1.com/public] does not exist Warning: DocumentRoot [/home/demo/public_html/testapp/public] does not exist

Carlos commented Thu Mar 12 05:13:55 UTC 2009:

Yamaplos... make sure you replace 'demo' with your actual username.

David commented Thu Mar 12 21:37:20 UTC 2009:

Thanks for the info. I was only able to see my domain1.com site in my web browser when in /etc/apache2/sites-available/domain1.com I changed:

<virtualhost> to <virtualhost>

Before I made this change I was pulling up my default site.

I don't know why?

Chuck commented Thu Mar 26 06:36:15 UTC 2009:

How do you add subdomains? Is it an additional ServerAlias in that domains same virtualhost file, or do you create a new virtual host file with sub.domain.com ?

tripdragon commented Wed Apr 01 19:53:50 UTC 2009:

FN RIGHT!! worth the 20 bucks a month.. Rock!!!

jason commented Sun Apr 05 17:04:09 UTC 2009:

Chuck: You'll want a new virtual host file. Here's how I did it (change 'demo' to your server's name):

root@demo [/etc/apache2/sites-available] $ ls
d1.demo.com  d2.demo.com  default  default-ssl

root@demo [/etc/apache2/sites-available] $ cat d1.demo.com
<VirtualHost *:80>

  # Admin email, Server Name (domain name) and any aliases
  ServerAdmin webmaster@d1.demo.com
  ServerName  d1.demo.com
  ServerAlias www.d1.demo.com

  # Index file and Document Root (where the public files are located)
  DirectoryIndex index.html
  DocumentRoot /root/d1.demo.com/public

  # Custom log file locations
  LogLevel warn
  ErrorLog  /root/d1.demo.com/log/error.log
  CustomLog /root/d1.demo.com/log/access.log combined


Eric commented Tue Apr 28 16:18:20 UTC 2009:

After the set up, i run 'sudo a2ensite domain1.com' and get: Enabling site domain1.com. instead of, Site domain1.com installed;

Any help would be greatly appreciated.


justin louie commented Thu Aug 13 23:42:21 UTC 2009:

How do you setup a subdmoain? i.e. I want the phpmyadmin to come from mysql.incolo.com. I've tried:

ServerName incolo.com ServerAlias www.incolo.com


ServerName mysq.*

per a few apache forum threads, but I haven't been able to get it to work.

Geoff commented Fri Oct 23 15:22:16 UTC 2009:

Hi guys,

Noob alert

I have painstakingly followed this excellent tutorial word by word but i cannot for the life of me figure out the problem.

When i reload the url freestyle.rs i get:

"Page load error. Connection Interrupted. The document contains no data."

Before the virtual host setup loading that url brought the "It works!" default apache page.

Any tips? I haven't given you much to go on, i know, but other than quoting the whole tutorial i don't know where to start troubleshooting...

Matthew Roby commented Wed Nov 04 14:32:20 UTC 2009:

I know I am missing something obvious, but whenever I got through the steps of the tutorial, I get the following error when I try to restart Apache after adding a second virtual host:

  • Reloading web server config apache2 httpd not running, trying to start (13)Permission denied: make_sock: could not bind to address no listening sockets available, shutting down Unable to open logs ...fail!

The first virtualhost works fine when added, but the server refuses to start with the second. Now, I am no Apache expert, but it looks like it cannot bind to the same port for some reason. Any suggestions would be appreciated.

Thanks in advance for all you help :)

Amr Tamimi commented Sat Dec 12 10:50:47 UTC 2009:

i think in the /etc/apache2 you have to make some changes

in 'httpd.conf' add: NameVirtualHost *:80 in 'ports.conf' add/edit: NameVirtualHost YOUR_IP_ADDRESS:80

this makes sense for hosting more than a domain!

rayven commented Sun Apr 11 00:49:53 UTC 2010:

Did Yamaplos solve his/her problem? I get the same error:

  • Restarting web server apache2 Warning: DocumentRoot [/home/abudhabi/public_html/brainyboys.info/public] does not exist Warning: DocumentRoot [/home/abudhabi/public_html/edutechreview.info/public] does not exist Warning: DocumentRoot [/home/abudhabi/public_html/heavywoodguitar.info/public] does not exist Warning: DocumentRoot [/home/abudhabi/public_html/brainyboys.info/public] does not exist Warning: DocumentRoot [/home/abudhabi/public_html/edutechreview.info/public] does not exist Warning: DocumentRoot [/home/abudhabi/public_html/heavywoodguitar.info/public] does not exist (13)Permission denied: make_sock: could not bind to address no listening sockets available, shutting down Unable to open logs

rayven commented Mon Apr 12 12:33:51 UTC 2010:

I solved my problem today and it was remarkably simple: although I had received errors relating to my DocumentRoot and (13) Permissions, the problem was actually a spelling mistake! Instead of the subfolder "public," I had typed "pubilc." Haahha.

Want to comment?

(not made public)


(use plain text or Markdown syntax)