Virtual Hosts on your local OS X Apache

If you want to easily mirror multiple live websites locally for super fast and offline development, then read on!

When I reinstall OS X, I very quickly reconfigure Apache to allow for local vhosts. Apache can be a bit of a minefield for configuration and I am by no means an expert, however, these simple steps give a huge amount of benefit as you won’t need to edit apache’s configuration files every time you want to add a new vhost.

One example which I use daily is alfredapp.com which is setup locally as alfredapp.localhost – These two sites are exact mirrors of each other both rooted with / can be significant in web development when accessing resources and site links. I can develop and test on the local site, then when I’m happy, push the changes to my distributed repository and deploy to the live site.

Note that the following config changes may mutually exclude any other apache changes you have made… If that means nothing to you, then this will likely work fine.

Before we start, turn on Web Sharing

Open up OS X’s sharing preferences and turn on “Web Sharing”, this will start up Apache.

Step 1 – Backup the configuration files

/etc/apache2/httpd.conf
/etc/apache2/extra/httpd-vhosts.conf
/etc/apache2/users/[username].conf

Step 2 – Import the vhosts config into httpd.conf

Temporarily, we are going to make the httpd.conf writable to make some changes.

Open Terminal.app and type:

sudo chmod u+w /etc/apache2/httpd.conf

Then open the httpd.conf file and remove the # off the beginning of the following line:

#Include /private/etc/apache2/extra/httpd-vhosts.conf

While you are in here and if you haven’t done so already, it’s probably worth also uncommenting PHP too by removing the # from the following line:

#LoadModule php5_module libexec/apache2/libphp5.so

Save your changes and make your mac more secure again by making the httpd.conf file unwritable:

sudo chmod u-w /etc/apache2/httpd.conf

Step 3 – Do some magic in the vhosts config

Replace the contents of /etc/apache2/extra/httpd-vhosts.conf with the following:

UseCanonicalName Off
VirtualDocumentRoot /Users/[username]/Sites/vhosts/%0
LogFormat "%V %h %l %u %t \"%r\" %s %b" vcommon
CustomLog /var/log/apache2/access_log vcommon

Turning off UseCanonicalName makes Apache ignore the ServerName directive and instead use the domain name supplied by the browser to construct the domain (blah blah or something like that). VirtualDocumentRoot sets where Apache looks for the virtual hosts. Replace [username] with your case sensitive usename. The last two lines setup the log format adding the virtual host at the beginning using %V.

Step 4 – Setup the access for vhosts for your user

In my case, edit /etc/apache2/users/preppeller.conf and update the directory access:

<Directory "/Users/[username]/Sites/">
  Options Indexes MultiViews FollowSymLinks
  AllowOverride All
  Order allow,deny
  Allow from all
</Directory>

Naturally change [username] with your user case sensitive again. Updating this config file firstly allows apache to access this folder, but also allows for better .htaccess overrides.

Step 5 – Restart Apache

In Terminal type:

sudo apachectl restart

Step 6 – How to use… this is the easy part!

Lets say I want to setup alfredapp.localhost. Firstly, I create the following folder in Terminal:

mkdir ~/Sites/vhosts/alfredapp.localhost

This will contain the files for the website (I just grab these out of repository). Next, I update hosts file and add alfredapp.localhost to point to localhost. Edit /etc/hosts (you will need to sudo edit this) and add the following line:

127.0.0.1 alfredapp.localhost

Now visiting http://alfredapp.localhost in my browser and magically it works. You can just repeat step 6 for every site you want to add!

Wow, that’s easy! What next?

The next obvious step would be to configure your DNS so that *.localhost resolves to localhost. If you did this, then there is ZERO config to do to setup your local mirrors… simply create folders, populate them, and visit the domain in your browser! DNS configuration is a WHOLE different ballgame, which is why I’m not covering it here.

I hope that helps. Let me know if you have any comments if you have found this useful or if you know of better ways of doing this.

Cheers,
Andrew

8 thoughts on “Virtual Hosts on your local OS X Apache

  1. One thing I had issues with some time ago when using .local was request speed. My local requests were super slow and they should always be faster because of no transit time.

    For me anyway when I used .local OS X first search for computers on the local network because it maps machines as {MACHINE_NAME}.local. I have since changed all my local hosts to .funk and that made a huge speed difference.

    Just a heads up in case anyone else has a speed issue.

  2. Just wanted to suggest that on your local machine you can make this a bit easier by telling Apache to include a conf directory full of Vhost that live in your home directory. This way you don’t have to worry as much about permissions (as long as Apache can read the file) and you don’t have to dig around obscure directories to get at the conf files.

    Also do you really want to pay $40 for VirtualHostX to make the 6 lines in line 4?

    1. Hi Geoff,

      I’m not sure who you are commenting to – but the whole point in this blog post is so that you don’t have to buy 3rd party software AND once setup as described, you don’t even need to touch configuration files… you can just create a folder and it’s automatically setup.

      Cheers,
      Andrew

  3. Alright, I read this the day you wrote it and have been using this technique since I read it, just adding a row into hosts each time. But now I’m ready for a DNS looky up thing so I don’t have to do that step. I’ve looked all over the place, and it doesn’t seem very simple.

    Any change you’re gonna make a blog post about that? or can you point me to a resource that would help me with this?

    Also, I wanted to point out that on Macs (I think starting with Lion), .local looks up Bonjour stuff or whatever first, and so people are experiencing a ~10 delay before loading their pages, so you should use something other than .local.

    Technically, the only “guaranteed” top level domain that will never someday be used is .localhost (or you could probably get away with .test), and it is set aside for this reason (references: in English: https://secure.wikimedia.org/wikipedia/en/wiki/.localhost, https://secure.wikimedia.org/wikipedia/en/wiki/.test; in geek: https://tools.ietf.org/html/rfc2606).

    1. That’s a great extra bit of info (the .local delay), thanks!

      As for DNS, the easiest way to do this would be to run your own BIND server which can be rather complicated to setup and easy to break…. BUT this allows for wildcarded domains so you could just assign *.tld to an internal IP address. If I get some time in the future, I’ll have a bit of a play with BIND on OS X and see if there are easy ways to setup.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s