...where persistent camels roam...

How-to - ModPerl Virtual Hosting

This document describes a logical server-side directory structure for hosting a large number of internet sites, and explains how to correctly configure virtual hosting in Apache HTTPd server with ModPerl.

Apache HTTPd is ideally suited to hosting multiple internet sites from a given server, and we use it on production Unix environments, each hosting hundreds of sites.

§ Directory structure

We use a logical directory structure that scales very well in our hosting environments, doesn't sacrifice simplicity, and makes site-specific backups (and restores) very easy.  In this example, we'll use the RFC-compliant internet domain name "" (RFC 2606, section 3) for the internet site.

The "root" of the internet site structure is all self-contained within the "/internet/" directory.  Some system administrators may prefer to store this under "/usr/internet/" but for the purposes of this instructional document we won't be doing this.

Initially, the "/internet/" path must be created.  Then, for each internet domain name, using the period as a delimiter to separate it into pieces, create the sub-directories in reverse order.  For example, "" yields a relative path of "com/example/" (for "" the relative path would be "ca/bc/lumbercartel/").

So, to host "" like we do, the following directories will need to be created:

Directory Description
/internet/com/example/cgi-bin/ Various pre-compiled scripts and other binaries that are not related to ModPerl are stored here.  Although this is mostly traditional, it can come in very handy when there's a last-minute need to set up a Unix shell script or some other program that generates dynamic output.
/internet/com/example/db/ Database data files are stored here.  PostgreSQL and Oracle both have options to store databases and table spaces in specific locations (most other databases should too).
/internet/com/example/etc/ The "include" file that stores the VirtualHost container stanza is stored here, which we will be naming "httpd.conf" (if this is confusing, then you probably need to learn more about file system directory structure).  Other various configuration files that your scripts use should be stored here too (we also store the site's DNS zone file{s} here).
/internet/com/example/lib/ A site-specific Perl Module will be stored here.  Other such files should be stored here too.
/internet/com/example/logs/ Web server logs are stored here.  We also recommend storing any other log files here, such as debug output (e.g., with DBI, DBIC/DBIx::Class, etc.), web application logs (if any), etc.
/internet/com/example/usr/ User account/home directories are placed here.  For the web master, a symbolic link from within a user's home directory can provide easy access to the web site.  The user's eMail message can also be stored here, among other things.
/internet/com/example/www/ and
The contents of the web site are stored here.  The additional "images/" sub-directory is just a suggestion, but as an optimization (for which the explanation is beyond the scope of this document) we create it ahead of time because a lot of web masters seem to prefer to store images in this path.

§ VirtualHost stanzas

Even if you're only needing to host a single web site, we highly recommend using a VirtualHost stanza (a.k.a., "container" or "section") because one of the advantages is that server-specific errors, which are included in the main web server error logs, will not be included in your web server's error logs.

Create the following file, which we will refer to as your "virtual host configuration file:"

  • /internet/com/example/etc/httpd.conf

Then, add the following content to that newly created configuration file:

# One VirtualHost container is needed for each internet
# site (unique server names and server alises required).
  PerlSetVar       ROOT /internet/com/example
  DocumentRoot          /internet/com/example/www
  ScriptAlias /cgi-bin/ /internet/com/example/cgi-bin
  CustomLog  "|cronolog /internet/com/example/logs/access.%Y-%m.log" combined
  ErrorLog   "|cronolog /internet/com/example/logs/errors.%Y-%m.log"
  AcceptPathInfo        On
  PerlModule            Apache2::Reload
  PerlModule            Apache2::Request
  PerlInitHandler       Apache2::Reload
  PerlRequire           /internet/com/example/lib/
  <Location />
    AddOutputFilter INCLUDES .html
    Options +Includes +ExecCGI
    DirectoryIndex index.html
    ErrorDocument 404 /
  <FilesMatch "(\.pl|^[^\.]+)$">
    SetHandler modperl
    PerlResponseHandler ModPerl::Registry
    AddOutputFilter INCLUDES .pl
    Options +Includes +ExecCGI

If the "cronolog" utility is not installed on your system (we highly recommend that you get it because it's very helpful), change the "CustomLog" and "ErrorLog" directives in the virtual host configuration file that you just created to the following:

  CustomLog             /internet/com/example/logs/access.log combined
  ErrorLog              /internet/com/example/logs/errors.log

In some environments your web server daemon might fail to find "cronolog" during automatic startup during boot.  If this happens to you (one of the signs is that Apache HTTPd failed to start with an undefined error), it can be resolved easily by either creating a symbolic link in the "/sbin/" directory (on Unix) to cronolog (we prefer this approach), or by specifying the entire path to cronolog within the configuration file.

§ Include directive

Add the following to the end of your main Apache HTTPd configuration file (which is also called "httpd.conf" and may be stored in "/etc/httpd.conf"):

Include "/internet/com/example/etc/httpd.conf"

The "NameVirtualHost" directive won't be needed if the web site doesn't have a dedicated IP address (there are many good reasons that each web site should have a dedicated IP address, such as bandwidth tracking, HTTPS, etc., but further discussion on these points is beyond the scope of this document).

Previous | Index | Next

Home | Contact us
Copyright © Inter-Corporate Computer & Network Services, Inc.  All rights reserved.
All trademarks are the property of their respective owners.