Making Apache Smarter: Because Configuring VHosts Sucks

Hello again my friends. It's been almost a month since my last post, so it's time to post again, right? At some point I'm going to develop a healthy balance between work and this blog / my side projects. It hasn't happened yet. But hey, it happens. As promised previously, this article is going to cover how to make your Apache configuration smarter using some simple regular expressions. This article is primarily aimed at Web Developers, and I wouldn't necessarily recommend this configuration in a production environment - although if anyone has done any stress testing of this method I'd love to hear about it.

If you're reading this on the homepage, I hate to break it to you - but you're going to have the click that little continue reading link right now, because I've recently realized the stylesheets for the homepage aren't functioning correctly (oops). So, if you're interested in learning how to configure your last development virtual host, click on through!

Leveraging the Power of Regular Expressions

Pretty URLs are one of the "big things" on the Internet. For that reason, mod_rewrite has become one of the best known Apache modules in existence, because of its ability to transform a URL into something that makes sense to the application running behind the scenes. It supports anything you can imagine because of its powerful conditionals, regular expressions, and the like. One usually expects to find rewrite rules in a .htaccess file, so when I saw on in a VirtualHost configuration, I didn't think it would work - but it does.

It turns out that you can use mod_rewrite to dynamically set the DocumentRoot of a virtual host based on the hostname used to access the VHost. So let's say you have some simplistic domain wildcard like *.mycomputer.local directed at your computer. If this is set up correctly, then www.mycomputer.local, apple.mycomputer.local, and walnut.mycomputer.local will all resolve to 127.0.0.1 with the same DNS record. (this is actually what I covered in my last post).

Then, create a directory to hold your folders. In my example below I'll call it "/path/to/www/". Cliche, but effective. Underneath this, you'll want to create directories that match the name of the hostname they should resolve to. So, for "walnut.mycomputer.local" we create "/path/to/www/walnut.mycomputer.local".

Now, if you've got that set up, then all you need to add to your Apache configuration is something like this:

<VirtualHost *:80>
	ServerName mycomputer.local
	ServerAlias *.mycomputer.local
        RewriteEngine On
        RewriteMap lowercase int:tolower
        # if already rewitten and we have the right path, stop right here
        RewriteRule ^(/path/to/www/[^/]+/.*)$ $1 [L]
        RewriteRule ^(.+) ${lowercase:%{SERVER_NAME}}$1 [C]
        RewriteRule ^(www\.)?([^/]+)/(.*)$ /path/to/www/$2/$3 [E=VHOST_ROOT:/path/to/www/$2/]
        DocumentRoot %{VHOST_ROOT}
</VirtualHost>

And voila! You're now serving up multiple hostnames from the same web folder, and you never have to actually configure a vhost again. The good thing about this solution is you can stretch it as far as your imagination. In my local configuration I have several namespaces set up for each of the kinds of projects I work on. So, stuff for Sound Enterprises is under "se.local", stuff for Boxkite is under "boxkite.local",  and personal projects are under "farmmac.local" -- and their all separated under my www folder (so se stuff is at /path/to/www/se, etc) to make them easy to find.

Also, for the record, I have tested this with web applications that use their own mod_rewrite rules - and it works swimmingly. So what are you waiting for?

I hope you guys will find this little tidbit as helpful as I did. As always leave me some comment love and I'll see you guys again soon!