Sunday, March 17, 2013

Apache mod_vhost_alias VirtualDocumentRoot per second level domain name

I wanted to have a virtual document root for each second level domain name (,,, etc...), with subdomain virtual document roots located underneath the main domain name.

For example:
 --> /var/www/ --> /var/www/ --> /var/www/ --> /var/www/ --> /var/www/

And so on, so that each primary domain (that gets registered with a registrar) has its own folder in /var/www.

The problem was, everything that I was trying was failing to give the desired results, because I didn't fully understand how the 'Directory Name Interpolation' was working (how Apache turns the configured VirtualDocumentRoot string into a string that represents a discrete folder each time a file is accessed.

What ended up working was:

VirtualDocumentRoot /var/www/%-2.0.%-1/%0
VirtualScriptAlias  /var/www/%-2.0.%-1/%0/cgi-bin/

I'll break this down in pieces to explain how it's working:

This highlighted piece is the folder that holds all of the domains.  It never changes.

This highlighted piece references the second value from the right of the fully qualified domain name (FQDN).  For example, in the URL "", this will give us "f85".  When you use the - symbol, Apache starts counting from the right (so "%-1" would yield "net", and "%-3" would yield "www").  The ".0" following "%-2" is also important.  Although it doesn't technically do anything ("%-2" == "%-2.0"), it allows us to add the next item without errors.


This highlighted piece is a dot, plain and simple (up to and including this highlighted piece, we would have "/var/www/f85.").  The reason I wanted to dedicate a paragraph to it is because it gave me the most trouble.  The first thing I tried was combining "%-2" with a period ("%-2.") Logically this would give us "f85.", right? Nope!  When Apache sees this period following a "%-2" (or any other "%x"), it expects another number after the dot, as described in the Directory Name Interpolation section of mod_vhost_alias.  This second number is used to select a single character out of the first number's text (for the "" example, "%-2.1" would represent the character "f".  We can use the number 0 here ("%-2.0") to tell Apache to select the entire value and not some specific character, which allows Apache to finish parsing this "%x" phrase so that we can add our "." and have it actually represent a period without breaking anything!

This highlighted piece is the first value from the right of the FQDN ("net", in our "" example).  Pretty straightforward.  Up to and including this piece, we now have "/var/www/".  So far so good, just one last piece.

This highlighted piece represents the entire FQDN (with a forward slash in front of it).  Up to and including this piece, we're done!  We have "/var/www/".

Now, this is definitely not the first way I tried to do this, but it's the only way that I've found to work consistently across sub-domains of various depths.  Please let me know in the comments if you see a problem with this method or have a better idea!!