Apache Virtual Hosts on Debian - part 1

Now that apache is running and configured on your Debian server we can add virtual hosts to let it serve more than one domain.

Virtual Hosts

Your apache server should be set up now, and you should have a handle on your basic configuration options. Apache may be answering requests, but if you want to be able to handle more than one domain with one web server, you'll need to set up a virtual host for each. We'll go through setting up a couple sample domains via virtual hosts.

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.

Set the permissions

In order for apache to serve your web pages, the apache process will need to have read permissions for the various files that comprise your sites. We won't go into detail here (you can refer to this series on permissions if you want the details later), but to make sure the permissions are the way we need them run the following two commands:

sudo chmod -R a+rX ~/public_html
sudo chmod a+rx ~

The first command sets everything in your public_html directory to be readable and accessible by all users on the system. The second command sets your home directory to be the same way (though not all the files in it, like we did with public_html). Note that the "X" in the first command is capitalized.

If you add more directories for additional virtual domains later, run that first command again to make sure the new directories are accessible as well.


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

For each interface and port 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 config layout there is a default NameVirtualHost directive in the "ports.conf" file. If you've worked through the first apache configuration article article, you may remember it.

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

NameVirtualHost *:80
Listen 80

<IfModule mod_ssl.c>
    # If you add NameVirtualHost *:443 here, you will also have to change
    # the VirtualHost statement in /etc/apache2/sites-available/default-ssl
    # to <VirtualHost *:443>
    # Server Name Indication for SSL named virtual hosts is currently not
    # supported by MSIE on Windows XP.
    Listen 443

<IfModule mod_gnutls.c>
    Listen 443

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

Custom Virtual Hosts

We've set up the basics and now we're ready to add our own virtual hosts.

Let's go ahead and create the vhost file for domain1:

sudo nano /etc/apache2/sites-available/domain1.com

You'll want to tailor this for your own domain, of course, changing the username, directory, and domain name involved. Make sure all the settings relevant to this particular virtual host are inside the "VirtualHost" config block, or those settings will be treated like they're applying to apache's main configuration (because of the way the Include directive we discussed back in the configuration files article works).

As a general template use the following:

# Place any notes or comments you have here
# It will make any customization 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  www.domain1.com
  ServerAlias 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 /usr/sbin/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 nameserver(s), I've modified the "/etc/hosts" file on my local computer to include some entries mapping "domain1.com", etc. to the demo server'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 its location will vary depending on what OS is loaded on your local computer (try a Google search).

NOTE: Remember to remove those hosts entries when you're done with testing. It can get confusing down the line if you forget they're there, and find yourself directed to someplace other than what you've set in the public DNS records for your domain.

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

Domain1 Home Page

Tada! You should now see the index.html file you set up for your virtual host instead of apache's default page.


Note that in the vhost file we set a ServerAlias. Providing you have the DNS set up correctly you can also use that address to reach your site. For quick testing purposes you can place another entry in your "hosts" file (like I did in the example code given above):

Domain1 Home Page (hostname alias)

It is possible to force a browser that came into a site using a ServerAlias to switch to your main domain, but that involves the use of the "rewrite" module. For now we'll let it slide, but if it's important to switch someone to a main domain from an old one (that you would have set as a ServerAlias), you would need to look into using mod_rewrite to do it.

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 add a hosts entry to your local machine and navigate to your second domain:


All being well, you will see the "domain2.com" index file.

Log Files

As defined in the vhosts files, each domain has its own log files. Let's take a quick look:

ls /home/demo/public_html/domain1.com/log/

The output should reflect what you set up in the virtual host's config:

access.log  error.log

Keeping the logs for each domain separate means you won't have as many log entries to dig through if you have a problem with just one particular domain.


Remember that the default virtual host is still in place.

Now, if someone enters the IP address of your server they will see the site defined by 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 that applies specifically to the requested IP address or domain name, it just serves up the first vhost it saw.

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

  • -- Jered

Article Comments:

Mathias commented Thu Feb 17 16:59:46 UTC 2011:

Hi, great articles! You have basically learned me all I know about setting up a server :)

I've got a problem: In the ports.conf file it says "

NameVirtualHost *:80 Listen 80

<ifmodule> # SSL name based virtual hosts are not yet supported, therefore no # NameVirtualHost statement here Listen 443 </ifmodule> "

What should I do?

Jered commented Fri Feb 18 17:17:56 UTC 2011:

What's the problem being caused? That section means that it set up NameVirtualHosts to handle connections to port 80, but that SSL connections require IP address-based virtual hosts instead of name-based virtual hosts. Basically, if you're setting up multiple domains and want them all to use SSL, you would need to get a separate IP address for each. You'd change from using "NameVirtualHost" to identify those config blocks to just "VirtualHost". It technically is possible to use name-based virtual hosting with a feature called SNI, but several older web browsers still in use don't support the feature (like IE on Windows XP).

Want to comment?

(not made public)


(use plain text or Markdown syntax)