Getting Apache to Work with Subdirectories

Shawn D. Sheridan's picture

WARNING:  Techie post!  This may be of interest to webmasters and web server admins, but the general marketing folks eyes may glaze over...  you know who you are.  ;-)

I spent a couple of days sorting through setting up my internal development webservers to better organise their file systems and get Apache to play nice with my new structure.  Every once in a while I get very techie, and this seemed to be one of those time trying to figure this out.  It took a bit of finessing, and so in the interest of saving someone else time, I figured I'd let y'all know what my solution was at the end of it all.

First, a bit of background.  I wanted to organise my sites under c:/www/sites, with subdirectories there each being the document root of an individual site.  One way to accomplish this is to have each of those directories in both the httpd.conf file as well as the httpd-vhosts.conf files, with appropriate re-write rules in httpd.conf for each directory.  But I'm a bit on the lazy side, and didn't want to have to edit both files every time I added a site.  I just wanted to edit one, and preferably httpd-vhosts.conf, as it's the smaller editing job.  So after much trial and error, this is what I came up with.

  1. I created a 'generic' set of rewrite rules for c:/www/sites in the httpd.conf file that would apply to any subdirectory as follows:


    <Directory "C:/www/sites">
      Options Indexes FollowSymLinks ExecCGI
      AllowOverride None
      Order allow,deny
      Allow from all

      RewriteEngine on
      RewriteBase /
      RewriteCond %{REQUEST_FILENAME} !-f
      RewriteCond %{REQUEST_FILENAME} !-d
      RewriteRule ^([^/]*/)?(.*)$ index.php?q=$2 [L,QSA]

    </Directory>

    The important bit of this is the RewriteRule, and in particular the regular expression.  What it's doing is essentially looking for the site identifier and stripping it off.  It would otherwise be left on after everything else was stripped off, and nothing would match my URLs.  The first bit of the expression — ^([^/]*/)? — says, "match everything up to and including the first slash, if there is one" (the trailing question mark at the end signifies optionality).  The second part — (.*)$ — says, "match everything else up to the end of the line".  Then we rewrite it to be "index.php?q=" along with the second bit we matched earlier.  The flags in the square brackets just let the rewrite module know that this is the Last rewrite rule it should execute, and please append the query string while you're at it (QSA).

    So, if the incoming URL was site.name.here/some/path/here, the rewritten URL would be
    index.php?q=/some/path/here
    .
  2. Further down in the httpd.conf file is the <ifModule alias_module> section, and we need the following directive there (and the module has to be enabled, of course):

      AliasMatch ^(.*)\.name\.here/(.*)$ c:/www/sites/$1.name.here/$2

    which tells Apache that I want to match everything up to ".name.here" (the periods are escaped, as a period in a regular expression means "match anything"), and then match everything up to the end of the line, and alias that to be the path
    c:/www/sites/the_original_path.  The reason it looks a bit more convoluted is that I want to match on any first part, while fixing the second and third parts of the internal domain bits.  In other words, I needed to pull them apart to construct my internal path, and wanted only certain URLs to map to this alias (ones ending in ".name.here").  If i wanted everything to be aliased into c:/www/sites, I could have used simply:

      AliasMatch ^(.*)$ c:/www/sites/$1

  3. Then, in the httpd-vhosts.conf file, each site is set up as a virtual host, as follows:


    <VirtualHost *:80>
      DocumentRoot "C:/www/sites/site.name.here"
      ServerName site.name.here
    </VirtualHost>

    where site.name.here is the name for each site.

After all that, my sites are now served out of their individual subdirectories under c:/www/sites, and the URLs entered into the browser are of the form http://site1.name.here/some/page, and http://site2.name.here/another/page, and it all seems to be working just fine.

Portfolio

exeQutive
ClimbingPartner.net
OutSport Toronto
Accelerated Evolution
Ryan Dunlop Design & Drafting
The Privacy Solution
Lotus Gill Pilates
Investigative Research Group
Crag Crux Climbers