Automatic Virtual Hosts w/ Proxy Auto-Config

I often tell my co-workers that if they’re doing the same basic thing over and over again, to let me know, because there’s probably a way to automate it.  That’s why whenever I used to start a new web development project I’d feel a twinge of guilt.  Does this look familiar?

  • Create /path/to/vhosts/projectname/public
  • Edit /etc/hosts to add 127.0.0.1 projectname.localhost
  • Edit /path/to/httpd-vhosts.conf to add a new <VirtualHost> directive for projectname.localhost
  • Repeat for each new project

It’s not a big deal—maybe a two minute distraction—but it always bugged me.  I’d looked into automating this before, but it always led to me installing a DNS server on my local machine, which is something I don’t particularly want to do.  Then, just a few days ago, I accidentally stumbled on to a fantastic cross-platform solution.

First let’s start with Apache, which was always the un-problematic part of the equation.  There’s a great Apache extension called mod_vhost_alias that was made to do just this.  All you need is one slightly modified <VirtualHost> directive and you’re set:

<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    VirtualDocumentRoot "/path/to/vhosts/%1/public"
    ServerName subdomains.localhost
    ServerAlias *.localhost
    LogFormat "%V %h %l %u %t \"%r\" %s %b" vcommon
    ErrorLog "logs/vhosts-error_log"
    CustomLog "logs/vhosts-access_log" vcommon
</VirtualHost>

And you’re also going to want to set directory permissions on all those directories:

<Directory "/path/to/vhosts/*/public">
    Options Indexes FollowSymLinks
    AllowOverride All
    Order allow,deny
    Allow from all
</Directory>

You’ll also probably want to turn UseCanonicalName Off.  Now Apache is set up to map anything.localhost to /path/to/vhosts/anything/public.  The problem is, your computer still doesn’t know that it should be handling http://anything.localhost.  That’s where the proxy auto-config file comes into play.

Proxy Auto-Config files, or PAC files, were designed to help your browser determine if and when it should use a proxy.  PAC files are actually just simple JavaScript files with one function that takes URL and Host Name arguments and returns a string telling the browser what to do.  Often this would be used to send certain traffic through a proxy, or proxy certain traffic at certain times of the week (it might be useful as a distraction-blocker as well), but in our case we’re going to use it to forward all .localhost traffic back to our local web server.

Just create a file called localhost.pac and put the following inside it:

function FindProxyForURL(url, host)
{
	if (dnsDomainIs(host, ".localhost")) {
		return "PROXY localhost";
	}

	return "DIRECT";
}

Basically what this file is saying is, if the domain is *.localhost, send it to localhost, otherwise just connect directly.  All you have to do is save that file and tell your browsers to use it, and you’re set.  Each browser is a little different, but most (if not all) support PAC files:

  • Safari: System Preferences -> Network -> Advanced… -> Proxies -> Automatic Proxy Configuration
  • Firefox: Preferences -> Advanced -> Network -> “Configure how Firefox connects to the Internet” -> Automatic proxy configuration URL
  • MSIE: Tools -> Internet Options -> Connections -> LAN Settings -> Use automatic configuration script
  • Chrome: Uses Safari/Internet Explorer settings
  • Opera: Preferences -> Advanced -> Network -> Use automatic proxy configuration

Now, when you go to http://mynextawesomeidea.localhost your system will automatically attempt to load /path/to/vhosts/mynextawesomeidea/public.  Any time you want to start a new project, just create the directory and go!

A couple notes: this technique messes with a few environmental variables.  Apache seems to get confused about your DOCUMENT_ROOT and REQUEST_URI.  Your document root is going to be your global document root, not the /path/to/vhosts/… directory, and your REQUEST_URI will include the hostname and protocol parts, not just the path and query parts.  Another side effect is that you need to set your RewriteBase to / if you’re using mode_rewrite.

Related posts:

  1. IDE Wishlist – HTML/CSS Auto-Complete/Magic Edition This list is clearly not comprehensive, but these are a...
  2. Auto-Focus Input OK, this has bugged me for a long time.  Many...
  3. Find oversized files in *nix Every once in a while I run the following command...
This entry was posted in Web Development. Bookmark the permalink.
  • http://twitter.com/inxilpro inxilpro

    Cool little trick I discovered. Automatically have your system point http://x.localhost to /path/to/vhost/x/public_html http://bit.ly/aXFc2Q

    This comment was originally posted on Twitter

  • http://twitter.com/newmediahub newmediahub

    Chris Morrell posted: Automatic Virtual Hosts w/ Proxy Auto-Config http://bit.ly/aXFc2Q

    This comment was originally posted on Twitter

  • http://blog.hackix.com Danny

    Now if we could only get Zend Studio to understand pac files as well :)

    • http://cmorrell.com/ Chris Morrell

      I believe that ZS respects system-wide proxy configurations, at least on OS X, so if you set it in System Preferences you should be good to go. I’m not 100% sure, but I think so.

  • http://nevermore.pri.ee German Rumm

    Unfortunately mod_rewrite doesn’t work well with VirtualDocumentRoot.

  • http://nevermore.pri.ee German Rumm

    … On the other hand,

    RewriteBase /

    kinda makes it work.

    P.S. Sorry for double posting.

    • http://cmorrell.com/ Chris Morrell

      Yeah, you just have to set a RewriteBase and you’re set.

  • Pingback: German Rumm’s blog » Blog Archive » Proxy Auto Config and VirtualDocumentRoot

  • Stijn Huyberechts

    The apache documentation says that the default of RewriteBase is the physical directory path. Does that mean that it would contain ‘/path/to/vhosts/%1/public’ in case of the automated virtuals hosts setup?

    Isn’t there another solution than adding ‘RewriteBase /’ in the .htaccess file of each documentroot?

    thanks,
    great article by the way, didn’t like the ‘old way’ of creating virtual hosts for each of my projects :-)

    • http://cmorrell.com/ Chris Morrell

      As far as I know, you need to use RewriteBase if you want to do things this way.

  • http://www.gerv.net/ Gervase Markham

    Top tip: the VirtualHost config above breaks when your “mynextawesomeidea” string contains dots – e.g. “fooapp-3.6″. To fix it, instead of “%1″, write “%-2+”. That means “every path component apart from the last (i.e. “localhost”). Thanks to the docs for mod_vhost_alias for this idea.