Skip to: Navigation | Content | Sidebar | Footer

Weblog Entry

Virtual Hosts for Dummies

August 05, 2004

Running your own local Apache server for development is a great idea, and even better if you’ve enabled local virtual hosts.

As demand for open source software increases, so do the options. Popular packages are frequently ported to different platforms, so it’s fully possible to run a local install of Apache regardless of which operating system you use on your workstation.

The stumbling block is mainly know-how, which is fortunately an easy gap to fill. I am decidedly not a system administrator, but I’ve run various Apache installs over the past year — without much conviction I should note, so learning has been slow.

After this past weekend’s rebuild, I got around to re-configuring a fresh copy of Apache Complete last night. Here are two tips from that experience.

Virtual Hosts

Virtual hosts enable you to intelligently run multiple sites on a single server. The useful side effect is that with proper setup, you can point your browser to www.whatever.whatever and load a local copy. My development site is now, which works exactly the same as the .com, just faster. I don’t even need a connection to work on it, because it’s all local; all my PHP scripts and Movable Type templates work, and the local filesystem access is so much nicer than using FTP.

I’ve long been aware of their use, but never committed to learning how to set up virtual hosts in Apache. A conversation with Narayan of Etherfarm on his recent trip through Vancouver enlightened, and it’s really ridiculously easy, to the point where I wish I’d done this last year.

Find your httpd.conf file, and then add this line somewhere near the bottom (there’s a spot with example virtual server code, I stuck mine below that):


You might want to run a search for ‘NameVirtualHost’ within the file before-hand to make sure it’s not already set, or at least commented out with a preceding octothorpe (#).

Next add an entry for localhost pointing to the root of your web server, so that typing localhost in your browser’s address bar continues pulling up the default site:

	ServerName localhost
	DocumentRoot /Path/To/WebRoot

And finally, for each individual virtual site you wish to run, add a new entry pointing to the proper directory. This is especially useful because, at least on Unix-based systems, this means it can sit anywhere in your filesystem. I’m used to dumping all sites in a special ‘www’ folder and pointing the web server to that; this way I can simply direct Apache to, in my case, /Volumes/Shine/mezzoblue/www and keep all articles, .psd files, and web files in one folder.

	DocumentRoot /Volumes/Shine/www/delhi

Host Redirection

But here’s the part I didn’t read, which I should have — you’re only halfway there once you’ve set up Apache. In a bout of doing one thing while having a hunch I should be doing another, I wasted far too much time configuring and re-configuring httpd.conf before realizing I also had to tell my computer where to look for this host I’d just invented. It’s in the articles I linked above, but I missed this step. May you not make the same mistake.

Simply, all that’s required is editing your local computer’s hosts file so that your browser is able to resolve the fake names for your development sites. For each entry created in httpd.conf, a corresponding entry needs to exist in your hosts file. Instructions on how to do this vary between operating systems, but it’s not hard to find tutorials. (The step-by-step instructions on this evolt article work perfectly in Panther.)

And That’s It?

As long as the directories you’ve pointed your virtual hosts to exist, and have files in them, you now have customized local hosts for your sites, on your own computer. Make sure to restart Apache before checking, which may require command line access, depending on your install. Other than that, you’re done.

Getting 403 errors?

If you’ve done everything above and can’t access your new site, due to a ‘403 Forbidden’ error, you have a permissions problem. If the directory/files you wish to load haven’t been given read permission for all users, the web server won’t be able to access them. As a general rule, public-facing directories and files should be at the very least something like 644 or (- r w - r - - r - -), and ideally 755 (or - r w x r - x r - x). If you don’t know what this means, a quick introduction to Unix permissions in general, chmod in particular is in order.

Now, assuming everything looks alright, you may still get a Forbidden error. Turns out this is due to the execute permissions on all folders above the root of your virtual host on the server; namely, it must be set. For all of them.

If you have a directory serving as your root like so:


…then every directory above Sites must have execute permissions set for all users. If you’re feeling brave, a quick and easy way to do this on the command line is as follows:

cd /
sudo chmod -R 755 /Users

You will be prompted for your local computer administrator password. This will change permissions of everything in /Users on down the hierarchy to 755. Fine if you’re in a fairly low-risk situation, like having a firewall in between you and the public internet (and trusting the local network your machine is attached to). Problematic if not. Otherwise, you’d simply do it on a per-directory basis:

cd /
chmod 755 /Users
cd Users
chmod 755 dave
cd dave
chmod 755 Sites

If necessary, add the sudo command before each chmod line and authenticate as necessary.

Reader Comments

Lars says:
August 05, 01h

Best way is certainly to set up another machine with apache and as exactly as possible the same configuration as your webserver has. In particular if you developing any PHP based applications or make use of some very special apache features like .htaccess-files or sessions your windows/mac-system probably won’t be able to handle.

Here’s my way: I’m working with and developing on Win2k (shame on me) just because i’s more comfortable when _not_ working ;-) My laptop is a dual-OS with Win2k and SuSe Linux. I configured my local Linux distribution the same way as I did with my webserver. Instead of I make use of e.g. which I defined in my local hosts file.

Fortunately I’am able to develop with all comfort I like to have, heavenly speed and with the guarantee that there are no incompatibilities when I upload my scripts.

My 2 cents,


Narayan says:
August 05, 02h

Dave, following your lead, I just wiped the hard drives on my PowerBook and my G5, and was writing up a virtual hosts article while I was setting everything up again. Many thanks for saving me the effort!

I’ll just add a few things:

Name-based virtual hosts not only simplify the access to various websites-in-development, they also allow you to more closely match Apache options a client might have turned on or off on their webserver. If a client has indexes turned on, for example, you could turn indexes on (or off) for a particular virtual host using apache directives. Between the VirtualHost tags, add (for example):

<Directory /Users/narayan/Sites/etherfarm>
Options FollowSymLinks Includes ExecCGI

True, you can do this with .htaccess files but, as Robert Hahn proclaims in a previous comment, I’ve taken to mirroring as closely as possible the server on which a client’s site will be running. As such, I have these directives in the the virtual host declaration in the .conf file, then modify them as needed with .htaccess files (as I would on the “live” site).

Similarly, within the virtual host declaration, you can specify locations for logs, add file types or modify icon handling, and (importantly), specify scriptalias directories. Basically, you can place almost any apache directive within <VirtualHost> tags, thereby mirroring various clients’ hosts on a per-virtual host basis.

Lastly, I prefer to use ~/Sites than /Library/Webserver/Documents. I’m the only one on my machine, and I like to keep my stuff in my user folder, which gets backed up on a regular basis. To do this, I move to /Library/Webserver/Documents and create a symbolic link:

$ ln -s /Users/narayan/Sites Documents

This way any calls to localhost get automatically sent to ~/Sites, which for me seems the most logical devbed. I run behind a firewall and don’t grant external access off port 80, so I have no problems doing this.

As for transferring MT data from the dev box to a live server, I twice used an SQL dump (via phpMyAdmin) to do this successfully, but it was my personal site, so I didn’t care too much if things went awry. I don’t know if an SQL dump is a recommended practice for MT or if it work if tried again.

gavin says:
August 05, 04h

Patrick Gibson has a shell script (not too geek intensive) available to set up virtual hosts:

I have only had a quick play with it but it seems to work OK.

Stephane says:
August 05, 08h

I just discovered virtual host 2 month ago. I was running two website in development and I use only use relative to root links (link beginning with a /). I had some problem with my PHP include that use relative to root links, they kept pointing in one site only.

It might be useful but I’m only a designer, it’s getting to be too much for me, I might be a real geek but configuring my Apache server and host file is way out of my field of expertise.

Scott Plumlee says:
August 05, 09h

I just finished this on my OpenBSD laptop. One thing I was considering is setting up all my URIs to be a php variable so I can drop the new code into the live site with one change. I don’t like relative URIs as a personal preference - I’ve made too many mistakes with the number of directory levels to go up or down.
What I’m considering is having every URI be of the form $host/some/path/to/a/file and declaring $host to be the local copy of the site, in your case $host=””. Then, when I move it over to the real server, all I need to do is adjust the $host variable to be $host=””.
I’d be interested to know if anyone else has ideas on the best way to handle such things, or if I’m overlooking some major issue that’s going to come back and bite me.

August 05, 09h

> I don’t like relative URIs as a personal preference - I’ve made too many mistakes with the number of directory levels to go up or down.

What’s wrong with absolute URI’s?


You certainly shouldn’t be using within the site itself!

August 05, 09h

i use a similar setup. but one thing i wish is that the rendezvous (opentalk?) support for apache would just automatically lay claim to any .local virtualhosts you define. it would save the step of tweaking the /etc/hosts file, and make those virtual hosts available to other local machines (assuming you’re using NameVirtualHost * and not just NameVirtualHost

August 05, 09h

I’d like to contribute a couple of other tips on the topic.

Like Dave, I use .dev for development work. I *also* have a .static set of domains if I’m running a site that generates static pages destined for the live site. So, on my business site,, I have on my machine and roberthahn.static for development and staging servers.

The first tip I want to contribute might not be an amazing revelation, but here ‘tis: If you can swing it, try to set up a directory structure that exactly matches what the live server’s is. This structure should extend ‘above’ the web root as well, in case some of your scripts need filesystem-based root-oriented paths to files or other scripts. This paves the way to a zero-tweak staging-to-live server move.

The second tip has to do with where you put your virtual host information. Dave suggests editing the httpd.conf file. If you are using Mac OS X, you should be aware of one important gotcha: every time you update your operating system, if it includes an update to Apache, then Apple will replace your httpd.conf file in favour of theirs, which will cause you to lose all your virtual host configuration.

An I idea I saw that I think I can credit to Rael Dornfest is to create a virtual.conf file in /etc/httpd/users/. In this file, you put all your virtual hosting configuration. Once you restart Apache, it will automatically load all files found in that users/ directory, including the virtual.conf. The benefits: you keep all the virtual host configs in one place, and it will never be overwritten by Apple.

Feel free to ask me any questions if I didn’t explain anything clearly enough.

Vincent Grouls says:
August 05, 10h

Jim - this article might help you in implementing RendezVous correctly so that sites do show up:

I came across this link a few days ago and bookmarked it. I haven’t tested it myself yet though as I haven’t found time to do it yet.

Good luck!

August 05, 10h

Quick question for everyone. I have a local apache configuration, but I haven’t installed movable type because of synchronization. When you work locally, what is your procedure for synchronization up to the live server? Aside from a manual copy using FTP, is there a more elegant solution?

phnk says:
August 05, 10h

By pure coincidence, some discussion had taken place about OS X, Apache and virtual hosts here not so long ago :

Dave S. says:
August 05, 10h

“every time you update your operating system, if it includes an update to Apache, then Apple will replace your httpd.conf file in favour of theirs”

If you’re using the copy of Apache built-in to OS X, that’s true. I’ve installed the ‘Complete Apache’ package from Server Logistics — — and it sticks all config files in its own directory. Problem solved. (The ‘Complete’ packages offer extra options that most people love, although I find their control panel applets a little buggy)

‘When you work locally, what is your procedure for synchronization up to the live server?’

I’m doing it two ways. First, all my templates are saved as external files in a /templates/ directory, so those go via FTP. Second, all data is easily exportable from the MT admin interface, so I just export and import all entries/comments as needed. (I’m sure there’s a better way to do this if you’re a database person, but I’m not, so Export works great.)

The only thing this leaves is manual configuration of preferences and archives and things within the manager. I do that by hand, and it’s a pain, but you only have to do it once.

No real reason to transfer the actual generated .html pages themselves, those can easily be re-generated once you have the data/templates set up properly.

August 05, 10h

You can go a lot further than just running Apache locally (especially if you are using *nix or OS X).

On my Win XP box I have a complete application server running locally: Apache (and a whole bunch of modules), Perl, PHP, MySQL, Shapeshifter (the CMS), CVS, etc.

Better still, once local development is complete you can use CVS (or Subversion, etc) or RSync to automagically bring the production server up-to-date!

August 05, 10h

I’m just starting to set this stuff up myself, but i’ve decided it would be best for my situation to have one config file for each virtual host like and etc. in a virtualhosts directory. This way i can set up individual virtualhosts through safari using my own php stuff super easy.

Now all i need to get all this working is figure out how to get this to live next to my router in peace. it works from the lan, but not from the web as is now.

M. Perakis says:
August 05, 10h

Just a note for the Windows people: If you want to use virtual hosts in a local environment, you have to follow this method, but you should also edit this file:


hosts is a file without extension (not a directory) and all you have to do is enter the localhost’s IP and the name you would like to resolve (e.g.

Jim Royal says:
August 05, 10h

Setting up virtual hosts with Apache on Mac OS X does not involve editing a HOSTS file. Rather, the edits are done in NetInfo Manager:

Run NetInfo Manager.

Click the lock to authenticate.

Select /machines/localhost.

Click the Duplicate button.

In the Property list for the new entry, change the name to the same name as the virtual ServerName in the Apache httpd.conf file.

Click a different machine name to save the changes.

Add a new machine for each virtual host you have set up in your Apache configuration.

You may have to restart your browser.

Eric says:
August 05, 12h

I just actually set up something like this yesterday…I am using a Rendexvous base station with its own IP, so I set up ports on the base station IP for each site, and then added these ports to net info manager in os x. Works great, so far, except that I can’t access the domains through the name alone (e.g. http://arkitrave), I have to use I don’t know why this is, as this IP is in the /hosts file…But it does work across the entire intranet via the port address, which is what I really need to work.

I also configured a localhost page to access the files from the laptop when it isn’t plugged into the network, via the 127…. address.

I haven’t seen a lot written about using virtual hosts with a networked system and a wireless station, so I’m just experimenting and throwing out the stuff that doesn’t work.

Scott Plumlee says:
August 05, 12h

In response to the comment by Martin-Lucas Smith, I’m not sure what your point is. I’m saying that I don’t like relative URIs. If I’m in and I want to go to, I prefer to use instead of ../../../dir4/dir5/dir6 for the link to that page. Maybe I confused the issue by saying file versus page. Hope that makes sense.

Patrick O'Leary says:
August 05, 12h

Scott, to get to from, you just have to link to href=”/dir4/dir5/dir6”. The important bit is the leading slash, which means “from the server root”. That’s what Martin was trying to say. Therefore, to go to from any page in, just link to href=”/”. If you ever register and move your website there, all the links within your site will still work without any additional effort from you.

Sorry for the somewhat OT post.

Alex says:
August 06, 03h

Another good tool is the vhost module for apache. Bascially you give apache a root directory to look into, and then just stick your site directories in there. Apache uses the host: header to then look for your directory.

/www/vhtdocs/ is the root directory
you then add a directory called
(no apache reboot or configuration file tweeking needed)
call up, and apache will serve out the contents of the /www/vhtdocs/ directory.

V. Useful if you are working on multiple sites, or need to quickly set sites up without wanting to fiddle with the apache configuration file.


Brade says:
August 06, 04h

Very useful article. I finally got around to setting up my v-hosts yesterday after reading this. I use Fedora Core 2 and the process couldn’t be easier. After following the directions in the article, just open up /etc/hosts and add the line(s) vhost

where vhost is the name you gave in the apache file. repeat for all your vhosts. restart apache. voila.

Stephen Arehart says:
August 06, 04h


Thanks for the info! I’ve been meaning to do this for a while, just hadn’t had the time. Your instructions were great, and it took me all of 30s to get it done on OpenBSD 3.5. Thanks again!

To Scott Plumlee: drop me a line sometime if you want to bounce ideas / chew the fat about web development on OpenBSD - I’ve been working on that platform for a little while now - nice to see someone else is using it as well!

Take it easy, everyone!


Scott Plumlee says:
August 06, 05h

> The important bit is the leading slash, which means “from the server root”.

Thanks Patrick, and apologies to Martin-Lucas Smith if I sounded rude. Everytime I think I’ve got my head wrapped around something, I learn something new. I had learned my HTML via Dreamweaver, and everytime I used a relative URI it was always of the ../../ form.

Stephan Arehart, if you can drop me a line sometime at my first name then the symbol above the 2 then my last name, it would be great to have someone to toss ideas around with. Not much experience yet with the blowfish, but always willing to learn.

Lots of great ideas here. The vhost module looks interesting. Now to go tear apart everything I just did and redo it the right way!

August 06, 05h

“Octothorpe” not “otcothorpe” surely. :)

nice article though!

August 06, 06h

Another method to consider is to use Webmin in conjunction with the Virtualmin module. It does a whole lot of legwork in addition to the Apache setup.

Vincent Grouls says:
August 06, 09h

Narayan wrote:
> I don’t know if an SQL dump is a recommended practice for MT
> or if it work if tried again.
I don’t know if it’s a recommended practice for MT but it sure is a recommended practice for anything SQL dumps ;-).

As Jonathan M. Hollin mentioned, CVS is great when developing. I use it all the time. And it is included in OS X 10.3.x by default :-D.

Owen says:
August 06, 12h

“Octothorpe” rocks, much more so than “hash”. Thank you.

JH says:
August 07, 01h

For those of you running something other than OS X on your dev servers … most Linux distributions’ default Apache configs are a bit more secure, with directory access set to “deny” by default and then selectively enabled for whatever the distro’s default DocumentRoot is (/var/www or /opt/www or whatever).

If you’re getting a “Forbidden” error after setting things up Dave’s way, this is likely the problem.

So in addition to the VirtualHost definition you’ll also want to do something like this. You should probably put it in the same .conf file as your virtual host config so everything’s in the same place (but be sure to put it outside the <VirtualHost> block):

<Directory /path/to/vhostdir>
Options -Indexes FollowSymLinks MultiViews
AllowOverride All
<IfModule mod_access.c>
Order allow,deny
Allow from all

This example mirrors the default security settings of Mandrake … you probably will want to set the Options and AllowOverride directives to mirror your production server’s config.

More info here:

August 07, 01h

Following these instructions, and the ones at, I have everything running great in OSX. Does anyone know how to get Windows running in Virtual PC to see the same virtual hosts? thanks

Mats Persson says:
August 07, 04h

Re: Comment # 17 by gavin

I have been using the shellscript by Patrick Gibson [see URL above] and it is absolutely great !!!! Highly recommended.

I have 8 ‘sites’ in /Users/me/Sites/ directory, and I have another setup running under the fixed IP address of my computer on the LAN. ( pointing to /Library/WebServer/Documents/ where I have other projects, or code samples, etc. stored.

Just download it, create a folder called ‘bin’ in your Home folder /Users/<yourname>/, store the script in there and then open Terminal and type the following:

sudo ./bin/ <>

Hit return, and then enter your admin password. You then only have to type Y =yes or N = no to the options in the window.

Forget all the above complexities and use the Mac way of working. :)

setmajer says:
August 10, 04h

Regarding VirtualPC:

On a VPC, Localhost and the loopback address ( point to the VPC, not to the host machine on which it is running. The way I worked around that was to give my host machine (a beige G3 running OS X.2.8) a static IP and then either access the site from the VPC via the IP or edit the VPC’s hosts file.

That works great if you’re using a router to handle your ‘Net connection, but I’m not sure it could be made to work if you’re connecting the host machine directly to a modem as the machine would be getting a dynamic IP from your ISP everytime you connect. That is, your IP would keep changing on you.

Regardless, I eventually got tired of editing Netinfo on the Mac and hosts files on all 4 VPCs (this was prior to the discovery that yes, Virginia, there is a way to run multiple versions of IE/Win on the same PC), my VAIO and my GF’s Dell.

Instead, I set up BIND on the OS X machine (there’s a great tutorial on BIND 8, the version included in OS X.2.x, here: I configured it to be a caching-only server, and to only respond to requests from machines on the same LAN (there are instructions for both at the aforementioned URL) . Then I set up zone files for each of the domains I wanted (all my various .dev sites) and set up BIND to handle them. Finally, I added the Mac’s IP to the DNS servers list on all my machines (virtual and otherwise).

From that point on, setting up a new site was as simple as adding a new domain to BIND and a new host to apache—no more Netinfo, no more hosts files. Set it up on the Mac and all the machines in the apartment would recognize it instantly.

Very convenient—and *major* geek points to boot. ;-)

August 10, 12h

Personally, i have an old machine built from spares left over form upgrades etc with Windows 2K server on it.

This way i can have a pretty much identical setup to my live web servers.

Running the server addition means no virtual directories needed, each site has their own site.

I also run windows DNS on the machine, which enables me to run multiple sites for each client haveing a .dev equivalent to their live domain.

I never test anything live, everything is tested on the development server. Once i’m happy its stable, a copy is moved to dev.clientdomain.suf for feedback and then finally moved to their own account.

Ken says:
August 13, 05h

I encourage all to go and grab to do the apache virtual host config for you through an UI.

August 16, 09h

PHP coders – a method that allows you to create PHP programs that can be relocated later (or installed to your friends’/enemies’ hosts)/

Consider using $_SERVER[‘PHP_SELF’] and similar variables (such as ‘DOCUMENT_ROOT’, ‘SCRIPT_FILENAME’, ‘PATH_TRANSLATED’) to refer to the current script and files located near it.

Check out

August 18, 04h

If you’re looking to set up canonical domains on Win32 (with apache) I have an article i wrote a while ago that might help. It’s a little rough (not to mention badly formatted) but it should be enough to point you in the right direction.

Oh, and it doesn’t require a dns server:



bryce says:
August 19, 06h

If you’re setting up a virtual host on a windows installation of Apache, make sure you put the DocumentRoot in quotes.

DocumentRoot “e:/dev/insight/trunk”

Jemima says:
August 19, 10h

I set up virtual hosts on my mac a few days ago and I discovered that the method described at evolt for resolving the domain no longer works in some cases. Details are here:

In Panther, NetInfo was moved in the lookup order, so adding your domain to NetInfo will work only if DNS resolution fails. For fake top-level domains like .dev that will always happen, but if you’re using a fake subdomain of a real domain or a new domain name that’s registered but not live yet, the response you get back will depend on how that domain’s DNS is set up. You may not be able to see the local page. There are several solutions to the problem; I switched the lookup order back to the pre-Panther version.

Taylor Barstow says:
August 23, 01h

A quick note about moving smoothly from development to staging to live servers, which was discussed above (comment #4, by Robert Hahn). Using apache virtual hosts for this works, but it is still a little too static for my tastes. In some situations, you simply cannot mirror the directory stucture (“above” the web root, at least) of the live machine on the development/staging machine.

What I do instead is use an XML file (INI format would work well too) to define all the different paths (e.g., document root, web root, cgi bin, …) that I will use in building the website. Call these the “logical paths”. For each logical path, I specify three separate physical paths (one for the developement, staging, and testing server, respectively). Then, I use a PHP (insert your scripting language of choice) function to select which path should be used based on the current server’s hostname.

joshua says:
September 01, 09h

Great post! So handy…

Just two quick notes:

1. You may want to also use ServerAlias, like so:

DocumentRoot /path/to/

2. If you are behind a HTTP proxy server, you need to add your domains to “Bypass these domains…” under System Preferences > Network > Proxies. (“*.dev” works just fine) Took me way to long to figure that out!

hoolio says:
September 03, 12h

Actually there is already a ton of utilities which allow you to get a running apache server, with sql, php and stuff, by simply installing them.

The other advantage is that the size of this “packs” is about 5Mb.

Here’s one - - but, unfortunately, it’s in russian.