Ubuntu Gutsy - Apache Virtual Hosts

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

Let's create the basic layout for each domain. In your home directory create a 'public_html' folder:

cd ~
mkdir public_html

Now for each domain we will host (I use the examples of domain1.com and domain2.com) create a folder with a standard set of sub-folders:

mkdir -p public_html/domain1.com/{public,private,logs,cgi-bin,backup}

and

mkdir -p public_html/domain2.com/{public,private,logs,cgi-bin,backup}

That will create the folders public, private, logs, 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:

nano public_html/domain1.com/public/index.html

The content index.html:

<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 (don't forget to change the index.html content so it shows domain2.com and not domain1.com).

Virtual Hosts

OK. Now we have a basic structure for our two domains we can look at defining two virtual hosts.

Let's start off by defining the NameVirtualHost for port 80 (the standard HTTP port) and add a conditional setting so that if we have the SSL module enabled, it will also listen on port 443 (the standard HTTPS port).

We'll add these to the main apache2.conf file so they are in a central location:

sudo nano /etc/apache2/apache2.conf

At the bottom of the file add the following:

NameVirtualHost *:80

<IfModule mod_ssl.c>
    NameVirtualHost *:443
</IfModule>

The eagle eyed amongst you may have noticed that the default virtual host file also has a NameVirtualHost defined in the very first line.

As we just placed our settings in the main apache2 configuration file we can get rid of that entry by opening the default vhosts file:

sudo nano /etc/apache2/sites-available/default

Now delete the NameVirtualHost line and change <VirtualHost> to listen to port 80.

Once done, the beginning of the default vhost file should look like:

<VirtualHost *:80>
        ServerAdmin webmaster@localhost

        DocumentRoot /var/www/

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/logs/error.log
  CustomLog /home/demo/public_html/domain1.com/logs/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:

Domain1 Home Page

ServerAlias

Note that in the vhost file, we set a ServerAlias. Providing you have the DNS setup 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

Logs

As defined in the vhosts file, each domain has its own log files:

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

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 then 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 articles will look in more detail at the settings that are available and what they mean.

PickledOnion.

Article Comments:

Craig commented Fri Nov 30 22:42:39 UTC 2007:

Your articles have been more than helpful. This is my first time setting up a production linux server and i couldn't have done it with out these articles. Cheers! Craig

Shawn McBride commented Sun Jan 13 14:57:19 UTC 2008:

Hi. For some reason, using /etc/init.d/apache2 reload causes my slice to stop responding to http requests, even after reverting to the original default setup. I discovered that I need to use /etc/init.d/apache2 stop /etc/init.d/apache2 start to make the virtual hosts take effect.

Kenneth commented Wed Jan 16 00:19:28 UTC 2008:

I've been getting errors about Apache not being able to write to the log files. This is crashing Apache/keeping Apache from launching successfully. Any ideas?

PickledOnion commented Wed Jan 16 12:59:10 UTC 2008:

Kenneth,

Sounds like the path to the log directory is incorrect (check for log vs logs, etc) or the permissions are not correct and Apache (as the www-data user) does not have permission to write to that directory.

PickledOnion

Carl Karsten commented Fri Jan 18 01:38:10 UTC 2008:

reads odd:

"As we just placed our settings in the main apache2 configuration file we can get rid of by opening the default vhosts file:"

it's missing the rest of the preposition "we can get rid of _" by opening the default...

PickledOnion commented Fri Jan 18 10:32:41 UTC 2008:

Carl,

Thanks for the typo errors - I'll fix those up.

I deleted your second post as the formatting went a little mad with the Markdown.

You were basically asking if it would be possible to link to .patch files for stuff like this.

Although an interesting idea (and not one I had thought of) I do not think it would work as so many people have different things in their config files.

It would possibly work for a brand new install but as soon as someone added something else, or commented out a line, then it would most likely fail.

I will keep it in mind though as it is interesting.

PickledOnion

Sip commented Sun Jan 20 16:22:25 UTC 2008:

Do you create the public_html folder as root user?

PickledOnion commented Sun Jan 20 16:27:05 UTC 2008:

Sip,

No, create it as your user. Root commands have a 'sudo' in front of them.

PickledOnion

Sip commented Sun Jan 20 23:26:28 UTC 2008:

Many thanks for your reply, your tutorials have really helped me for which I thank you for.

I am experiencing a slight problem however. My virtualhosts are set up similar to yours but I have left in some of the default lines in the virtualhost file, such as Options Indexes FollowSymLinks MultiViews etc - god knows what it all does - but when I try and restart apache, I get a warning:

[Sun Jan 20 23:15:40 2008] [warn] NameVirtualHost *:80 has no VirtualHosts [Sun Jan 20 23:15:50 2008] [warn] NameVirtualHost *:80 has no VirtualHosts

I suspect I'm receiving two of these because I have two sites enabled.

Any ideas?

Robert commented Wed Feb 13 02:51:59 UTC 2008:

The Apache config reload doesn't restart the server. Make sure to do

"sudo /etc/init.d/apache2 restart"

after enabling your site.

Dave commented Tue Feb 26 19:29:33 UTC 2008:

I just ran through the tutorial and the server could not find my site content (it was looking in /var/www instead of /home/myusername/public_html/mydomain.com/public).

Turned out that in /etc/apache2/sites-available/default I somehow had the line:

<virtualhost>

instead of:

<virtualhost>

Fixed that and everything's cool.

Thanks for the great tutorials!

Dave commented Tue Feb 26 19:31:36 UTC 2008:

Hmmm, let's strike the angle brackets:

I somehow had the line:

VirtualHost *

instead of:

VirtualHost *:80

Fixed that and everything's cool.

Brad commented Thu Feb 28 20:46:55 UTC 2008:

HELP! My /apache2/sites-available/default file has gone missing! (because I accidentally deleted it on purpose :-P ) how do I recreate it? I kept getting this error when trying to reload apache.. Syntax error on line 295 of /etc/apache2/apache2.conf: Syntax error on line 45 of /etc/apache2/sites-enabled/000-default: Expected </VirtualHost*:80> but saw </VirtualHost> tried things a few different ways to various syntax errors. help!

wiiaboo commented Sun Mar 02 07:36:00 UTC 2008:

Brad: Try disabling the default vhost.

Refer to this article.

Guillermo commented Wed Apr 02 21:02:10 UTC 2008:

Hi, as far as I know I followed all the steps. However when I run "apache2 reload" it answers:

[error] (EAI 2)Name or service not known: Failed to resolve server name for 200.20.65.32 (check DNS) -- or specify an explicit ServerName

I do have a "ServerName radicalgolem". I tried changing /etc/hosts. I tried with other domain. None work. I don't get why it asks for 200.20.65.32, that's not my IP. Google doesn't help.

Do you have any idea what could I be missing?

Tim Fletcher commented Sat Apr 19 07:45:29 UTC 2008:

Thanks Shaun (comment no.2). I had the problem of Apache stopping serving while I was playing with virtual hosts too. Your answer worked for me. Cheers!

Paul Hammant commented Mon Apr 21 16:00:13 UTC 2008:

apache2.conf's ServerName shouldn't be the same name as one of the virtual host domains, as it'll intercept and show the default pages, instead of routing thru to the intended vhost page.

Maybe that's worth reminding people.

Chris Finch commented Fri Apr 25 14:35:16 UTC 2008:

Yes, Paul, I was confused as to why it was not routing through to the vhost page. Thanks for posting that.

Arup commented Sun Apr 27 12:06:04 UTC 2008:

If the virtual host is run on a different port on the same domain we need to enable the port in /etc/apache2/ports.conf, So lets say we run the virtual host on port 81, we need to add the following line in port.conf

Listen 81

t3i commented Mon Apr 28 18:23:59 UTC 2008:

Hi

You guys are the best! We all know it.

I've found that i get an error when using the custom virtual hosts example file. A typo for rails app layout is the logs/ instead of log/. Then i get an internal server error?

t3i commented Tue Apr 29 03:17:53 UTC 2008:

I found that after using log/ instead of logs/ and adding a standard <directory /> command, with the normal innards, just after the document root command made it work.

AlexS commented Tue Sep 02 15:54:18 UTC 2008:

PickledOnion,

Thanks for such a great tutorial. I'm converting from RedHat to Ubuntu, and this tutorial was the best I found.

Great work!

smcnally commented Wed Sep 24 19:33:06 UTC 2008:

This has been a great tutorial, thanks, Mr. Onion.

I am having a h*ckuva time getting a Wordpress MultiUser vhost config to work as designed (or intended):

WordpressMu (wpmu) requires a wildcard Alias to enable subdomain blogs. i.e.

ServerAlias *.mydomain.com

On its own, this works a treat: each wpmu blog gets its own [subdomain].mydomian.com.

But I'm also running other services: SugarCRM for support, e.g.. I want support.mydomain.com and svn.mydomain.com to work, as well. But the wildcard (ServerAlias *.mydomain.com) is precluding that for me.

Can anyone see fault in my logic or execution?

I appreciate your time and assistance.

my vhost conf files in /sites-enabled are as follows:

000-support

NameVirtualHost * <virtualhost> ServerAdmin smcnally@example.com ServerName support.mydomain.com DocumentRoot /var/www/sugar <directory /> Options FollowSymLinks AllowOverride FileInfo Options </directory> ErrorLog /var/log/apache2/error.log # Possible values include: debug, info, notice, warn, error, crit, # alert, emerg. LogLevel warn CustomLog /var/log/apache2/access.log combined ServerSignature On </virtualhost>


blogs

<virtualhost> ServerAdmin smcnally@example.com ServerName mydomain.com ServerAlias *.mydomain.com

DocumentRoot /var/www/wordpress
<Directory />
    Options FollowSymLinks
    AllowOverride FileInfo Options
</Directory>
<Directory /var/www/>
    Options Indexes FollowSymLinks MultiViews
    AllowOverride None
    Order allow,deny
    allow from all
    # This directive allows us to have apache2's default start page
            # in /apache2-default/, but still have / go to the right place
            #RedirectMatch ^/$ /apache2-default/
</Directory>

</virtualhost>


zzz-default

<virtualhost> ServerAdmin smcnally@example.com DocumentRoot /var/www/ <directory /> Options FollowSymLinks AllowOverride None </directory> <directory /> Options Indexes FollowSymLinks MultiViews AllowOverride None Order allow,deny allow from all # This directive allows us to have apache2's default start page # in /apache2-default/, but still have / go to the right place RedirectMatch ^/$ /apache2-default/ </directory>

ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
<Directory "/usr/lib/cgi-bin">
    AllowOverride None
    Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
    Order allow,deny
    Allow from all
</Directory>

ErrorLog /var/log/apache2/error.log

# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
LogLevel warn

CustomLog /var/log/apache2/access.log combined
ServerSignature On

Alias /doc/ "/usr/share/doc/"
<Directory "/usr/share/doc/">
    Options Indexes MultiViews FollowSymLinks
    AllowOverride None
    Order deny,allow
    Deny from all
    Allow from 127.0.0.0/255.0.0.0 ::1/128
</Directory>

</virtualhost>

Bill Snapper commented Fri Sep 26 01:16:20 UTC 2008:

I am slightly confused. The apache2.conf file had my main domain as the ServerName directive. I setup the default as per this tutorial which maps to /var/www. I then setup MY domain and it was the same as specified in ServerName. When I prefixed it with "www." it mapped properly. When I referred to just domain.com it mapped to the default. I then changed ServerName to another domain I had that has a ".net" suffix which I own, mapped but do not use, and now the domain.com and www.domain.com work as expected.

My question is, if I didn't have the ".net" what would be the correct way to map "domain.com"? Would my default vhost file just map to the exact same file as my domain.com?

Bill Snapper commented Fri Sep 26 01:24:45 UTC 2008:

The answer to my own question after thinking about this was to:
1) unlink default in the sites-enabled dir. 2) change ServerName back to domain.com from domain.net 3) Reload the server.

Voila. Now domain.com and www.domain.com map correctly.

Was this how it should have been done?

Eisenbroiler commented Wed Nov 19 09:08:37 UTC 2008:

Thanx for the help, and just if necessary:

If you want to load a index.php as directory index just type:

DirectoryIndex index.html, index.php

web designer tom commented Sat Dec 20 17:57:16 UTC 2008:

Thanks for this post. I found it very clear and easy to follow. I'm going to look at some others now.

Shaun commented Mon Apr 05 07:06:17 UTC 2010:

Does this also work with Ubuntu Karmic Koala? I can't find a slicehost article with that particular version.

Jered commented Mon Apr 05 15:11:26 UTC 2010:

We haven't updated articles for Karmic yet, but for apache configuration there shouldn't be many differences between it and Intrepid. I'd use those articles as references instead of Gutsy (which is an older version than Intrepid). The equivalent article to this one for Intrepid is located here.

Colin commented Thu Aug 25 23:42:55 UTC 2011:

Thanks very much for the tutorial. Just curious about the directory structure. While in the home dir you made publichtml but later you refer to /home/DEMO/publichtml

is demo a typo or did a mkdir demo/public_html command need to take place initially?

Jered commented Fri Aug 26 23:49:31 UTC 2011:

The difference in those paths is the initial "/" - the references to publichtml lack the initial slash, so they're "relative" paths. For those the system looks for publichtml in the directory you're currently in, which should be the home directory for the user account you'll associate with the site's files. The ones starting with "/" are "absolute" paths, so they list the full directory structure instead of just what's relative to where you are now.

The beginning of the article has the cd and mkdir commands in there - just replace "demo" with the name of your user account.

Want to comment?


(not made public)

(optional)

(use plain text or Markdown syntax)