Module mod_vhost_alias

Important: Information for this topic supports the latest PTF levels for HTTP Server for i5/OS . It is recommended that you install the latest PTFs to upgrade to the latest level of the HTTP Server for i5/OS. Some of the topics documented here are not available prior to this update. See http://www.ibm.com/servers/eserver/iseries/software/http/services/service.htm Link outside Information Center for more information.

Summary

The module mod_vhost_alias provides support for dynamically configured mass virtual hosting.

Virtual hosting

The term Virtual Host refers to the practice of maintaining more than one server on one machine or server instance, as differentiated by their apparent hostname (or server instance name). For example, it is often desirable for companies sharing a web server to have their own domains, with web servers accessible as www.company1.com and www.company2.com, without requiring the user to know extra path information.

HTTP Server (powered by Apache) supports two types of virtual hosting, they are IP-based Virtual Host and Name-based Virtual Host. As the term IP-based indicates, the server must have a different IP address for each IP-based virtual host. This can be achieved by the machine having several physical network connections, or by use of virtual interfaces that are supported by most modern operating systems.

While the approach with IP-based Virtual Hosts works well, it is not the most elegant solution, because a dedicated IP address is needed for every virtual host and is hard to implement on some machines. The HTTP/1.1 protocol contains a method for the server to identify what name it is being addressed as.

The benefits of using the name-based virtual host support is a practically unlimited number of servers, ease of configuration and use, and no additional hardware or software requirements. The main disadvantage is that the client must support this part of the protocol. The latest versions of most browsers (e.g. HTTP 1.1) do, but there are still old browsers (e.g. HTTP 1.0) in use that do not. This can cause problems, although a possible solution is addressed below.

Using non-IP virtual hosts

The notable difference between IP-based and name-based virtual host configuration is the NameVirtualHost directive that specifies an IP address that should be used as a target for name-based virtual hosts. For example, suppose that both www.domain.tld and www.otherdomain.tld point at the IP address 111.22.33.44. Simply add to one of the configuration files (most likely httpd.conf or srm.conf) code similar to the following:

NameVirtualHost 111.22.33.44

<VirtualHost 111.22.33.44>
ServerName www.domain.tld 
DocumentRoot /www/domain 
</VirtualHost> 

<VirtualHost 111.22.33.44>
ServerName www.otherdomain.tld
DocumentRoot /www/otherdomain 
</VirtualHost> 

Of course, any additional directives can (and should) be placed into the <VirtualHost> section. To make this work, make sure that the names www.domain.tld and www.otherdomain.tld are pointing to the IP address 111.22.33.44

Note: When you specify an IP address in a NameVirtualHost directive, requests to that IP address are only served by matching <VirtualHost>s. The main server is never served from the specified IP address. If you start to use virtual hosts you should stop using the main server as an independent server and use it as a place for configuration directives that are common for all your virtual hosts. In other words, you should add a <VirtualHost> section for every server (hostname) you want to maintain on your server.

Additionally, many servers may want to be accessible by more than one name. For example, the example server might want to be accessible as domain.tld, or www2.domain.tld, assuming the IP addresses pointed to the same server. In fact, one might want it so that all addresses at domain.tld were picked up by the server. This is possible with the ServerAlias directive, placed inside the <VirtualHost> section. For example:

ServerAlias domain.tld *.domain.tld
Note: You can use * and ? as wild-card characters.

You might also need ServerAlias if you are serving local users who do not always include the domain name. For example, if local users are familiar with typing "www" or "www.example" then you will need to add ServerAlias www www.example. It isn't possible for the server to know what domain the client uses for their name resolution because the client doesn't provide that information in the request. The ServerAlias directive provides a means for different hostnames to point to the same virtual host.

Dynamic virtual hosting

A virtual host is defined by two pieces of information: its IP address, and the contents of the Host: header in the HTTP request. The dynamic mass virtual hosting technique is based on automatically inserting this information into the pathname of the file that is used to satisfy the request. This is done most easily using mod_vhost_alias.

A couple of things need to be `faked', that being specific parameters with incorrect parameter values, to make the dynamic virtual host look like a normal one. The most important is the server name which is used by HTTP Server to generate a self referencing URLs. It is configured with the ServerName directive, and it is available to CGIs via the SERVER_NAME environment variable. The actual value used at run time is controlled by the UseCanonicalName setting. With UseCanonicalName off the server name comes from the contents of the Host: header in the request. With UseCanonicalName DNS it comes from a reverse DNS lookup of the virtual host's IP address. The former setting is used for name-based dynamic virtual hosting, and the latter is used for IP-based hosting. If HTTP Server cannot work out the server name because there is no Host: header or the DNS lookup fails then the value configured with ServerName is used instead.

The other thing to `fake' is the document root (configured with DocumentRoot and available to CGIs via the DOCUMENT_ROOT environment variable). This setting is used by the core module when mapping URIs to filenames, but when the server is configured to do dynamic virtual hosting that job is taken over by the mod_vhost_alias module. If any CGIs or SSI documents make use of the DOCUMENT_ROOT environment variable they will therefore get a misleading value; there is not any way to change DOCUMENT_ROOT dynamically.

Motivation for dynamic virtual hosting

The techniques described here are of interest if your httpd.conf contains many <VirtualHost> sections that are substantially the same. For example:

NameVirtualHost 10.22.33.44 
<VirtualHost 10.22.33.44> 
ServerName www.customer-1.com 
DocumentRoot /www/hosts/www.customer-1.com/docs 
ScriptAlias /cgi-bin/ /www/hosts/www.customer-1.com/cgi-bin 
</VirtualHost> 
<VirtualHost 10.22.33.44> 
ServerName www.customer-2.com 
DocumentRoot /www/hosts/www.customer-2.com/docs 
ScriptAlias /cgi-bin/ /www/hosts/www.customer-2.com/cgi-bin 
</VirtualHost> 
# comment line 
<VirtualHost 10.22.33.44> 
ServerName www.customer-N.com 
DocumentRoot /www/hosts/www.customer-N.com/docs 
ScriptAlias /cgi-bin/ /www/hosts/www.customer-N.com/cgi-bin 
</VirtualHost> 

The basic idea is to replace all of the static <VirtualHost> configuration with a mechanism that works it out dynamically. This has a number of advantages:

  1. Your configuration file is smaller so HTTP Server starts faster and uses less memory.
  2. Adding virtual hosts is simply a matter of creating the appropriate directories in the filesystem and entries in the DNS - you do not need to configure or restart HTTP Server (powered by Apache).

The main disadvantage is that you cannot have a different log file for each virtual host; however if you have very many virtual hosts then doing this is dubious anyway because it eats file descriptors. It is better to log to a pipe or a fifo and arrange for the process at the other end to distribute the logs to the customers (it can also accumulate statistics).

A request for http://www.example.isp.com/directory/file.html will be satisfied by the file:

/usr/local/apache/vhosts/isp.com/e/x/a/example/directory/file.html. 

A more even spread of files can be achieved by hashing from the end of the name, for example:

VirtualDocumentRoot /usr/local/apache/vhosts/%3+/%2.-1/%2.-2/%2.-3/%2

The example request would come from /usr/local/apache/vhosts/isp.com/e/l/p/example/directory/file.html. Alternatively you might use:

VirtualDocumentRoot /usr/local/apache/vhosts/%3+/%2.1/%2.2/%2.3/%2.4+

The example request would come from /usr/local/apache/vhosts/isp.com/e/x/a/mple/directory/file.html.

Simple dynamic virtual hosts

This extract from httpd.conf implements the virtual host arrangement outlined in the Motivation section above, but in a generic fashion using mod_vhost_alias.

# get the server name from the Host: header 
UseCanonicalName off 
# this log format can be split per-virtual-host based on the first field 
LogFormat "%V %h %l %u %t \"%r\" %s %b" vcommon 
CustomLog logs/access_log vcommon 
# include the server name in the filenames used to satisfy requests 
VirtualDocumentRoot /www/hosts/%0/docs 
VirtualScriptAlias /www/hosts/%0/cgi-bin 

This configuration can be changed into an IP-based virtual hosting solution by just turning UseCanonicalName off into UseCanonicalName DNS. The server name that is inserted into the filename is then derived from the IP address of the virtual host.

A virtually hosted homepages system

This is an adjustment of the above system tailored for an ISP's homepages server. Using a slightly more complicated configuration we can select substrings of the server name to use in the filename so that e.g. the documents for www.user.isp.com are found in /home/user/. It uses a single cgi-bin directory instead of one per virtual host.

# all the preliminary stuff is the same as above, then 
# include part of the server name in the filenames 
VirtualDocumentRoot /www/hosts/%2/docs 
# single cgi-bin directory 
ScriptAlias /cgi-bin/ /www/std-cgi/

Use more than one virtual hosting system on the same server

With more complicated setups you can use HTTP Server's normal <VirtualHost> directives to control the scope of the various virtual hosting configurations. For example, you could have one IP address for homepages customers and another for commercial customers with the following setup. This can of course be combined with conventional <VirtualHost> configuration sections.

UseCanonicalName off 

LogFormat "%V %h %l %u %t \"%r\" %s %b" vcommon 

<Directory /www/commercial> 
Options FollowSymLinks 
AllowOverride All 
</Directory> 
<Directory /www/homepages> 
Options FollowSymLinks 
AllowOverride None 
</Directory> 
<VirtualHost 10.22.33.44> 
ServerName www.commercial.isp.com 
CustomLog logs/access_log.commercial vcommon 
VirtualDocumentRoot /www/commercial/%0/docs 
VirtualScriptAlias /www/commercial/%0/cgi-bin 
</VirtualHost> 
<VirtualHost 10.22.33.45> 
ServerName www.homepages.isp.com 
CustomLog logs/access_log.homepages vcommon 
VirtualDocumentRoot /www/homepages/%0/docs 
ScriptAlias /cgi-bin/ /www/std-cgi/ 
</VirtualHost>

Directory name interpolation

All the directives in this module interpolate (insert) a string into a pathname. The interpolated string may either be the server name (see UseCanonicalName for more information) or the IP address of the virtual host on the server in dotted-quad format. The interpolation is controlled by specifiers inspired by UNIX® printf which have a number of formats:

Specifier Description
%% Insert a % sign
%p Insert the port number of the virtual host
%N.M Insert (part of) the interpolated string

N and M are used to specify substrings of the interpolated string. N selects from the period separated components of the interpolated string, and M selects characters within whatever N has selected. M is optional and defaults to zero if it is not present. The period (.) must be present if and only if M is present. The interpretation is as follows:

N.M interpretation Description
0 The whole name.
1 The first part.
2 The second part.
-1 The last part.
-2 The next to last part.
2+ The second and all subsequent parts.
-2+ The next to last part and all preceding parts.
1+ and -1+ The same as 0 (zero).

If N or M is greater than the number of parts available a single underscore is interpolated.

For a simple name-based virtual hosts you might use the following directives in your server configuration file:

UseCanonicalName off 

VirtualDocumentRoot 
/usr/local/www.example.isp.com/vhosts/%0 
A request for http://www.example.com/directory/file.html will be satisfied by the
file /usr/local/www.example.isp.com/vhosts/www.example.com/directory/file.html.

For a very large number of virtual hosts it is a good idea to arrange the files to reduce the size of the vhosts directory. To do this you might use the following in your configuration file:

UseCanonicalName off 

VirtualDocumentRoot 
/usr/local/www.example.isp.com/vhosts/%3+/%2.1/%2.2/%2.3/%2 
A request for http://www.example.isp.com/directory/file.html will be satisfied by
the file /usr/local/www.example.isp.com/isp.com/e/x/a/example/directory/file.html.

A more even spread of files can be achieved by hashing from the end of the name, for example:

VirtualDocumentRoot 
/usr/web/www.example.isp.com/vhosts/%3+/%2.-1/%2.-2/%2.-3/%2

The example request would come from /usr/web/www.example.isp.com/vhosts/isp.com/e/l/p/example/directory/file.html. Alternatively you might use:

VirtualDocumentRoot 
/usr/local/www.example.isp.com/vhosts/%3+/%2.1/%2.2/%2.3/%2.4+

The example request would come from /usr/web/www.example.isp.com/vhosts/isp.com/e/x/a/mple/directory/file.html. For IP-based virtual hosting you might use the following in your configuration file:

UseCanonicalName DNS 

VirtualDocumentRootIP /usr/local/www.example.isp.com/vhost/%1/%2/%3/%4/docs 
VirtualScriptAliasIP 
/usr/local/www.example.isp.com/vhost/%1/%2/%3/%4/cgi-bin

A request for http://www.example.isp.com/directory/file.html would be satisfied by the file /usr/local/www.example.isp.com/10/20/30/40/docs/directory/file.html if the IP address of www.example.com were 10.20.30.40. A request for http://www.example.isp.com/cgi-bin/script.pl would be satisfied by executing the program /usr/local/www.example.isp.com/10/20/30/40/cgi-bin/script.pl.

The LogFormat directives %V and %A are useful in conjunction with this module. See LogFormat for more information.

Directives

VirtualDocumentRoot

Module: mod_vhost_alias
Syntax: VirtualDocumentRoot interpolated-directory
Default: none
Context: server config, virtual host
Override: none
Origin: Apache
Usage Considerations: A LoadModule is required in the config file prior to using the directive. The statement should be as follows: LoadModule vhost_alias_module /QSYS.LIB/QHTTPSVR.LIB/QZSRCORE.SRVPGM
Example: See below.

The VirtualDocumentRoot directive allows you to determine where the server will finds your documents based on the value of the server name. The result of expanding interpolated-directory is used as the root of the document tree in a similar manner to the DocumentRoot disabled. See DocumentRoot for more information.

If interpolated-directory is none then VirtualDocumentRoot is disabled. This directive cannot be used in the same context as VirtualDocumentRootIP. See VirtualDocumentRootIP for more information.

Parameter: interpolated-directory
  • The interpolated-directory parameter the full path to a directory.

For example, a simple dynamic virtual host:

# LocalModule directive required 
LoadModule vhost_alias_module /QSYS.LIB/QHTTPSVR.LIB/QZSRCORE.SRVPGM 
# get the server name from the Host: header 
UseCanonicalName off 
# this log format can be split per-virtual-host based on the first field 
LogFormat "%V %h %l %u %t \"%r\" %s %b" vcommon 
CustomLog logs/access_log vcommon 
# include the server name in the filenames used to satisfy requests 
VirtualDocumentRoot /www/web/%0/docs

The next example is an adjustment of the above, system tailored for an ISP's homepage server. Using a slightly more complicated configuration we can select substrings of the server name to use in the filename so that e.g. the documents for www.user.isp.com are found in /home/user/. It uses a single cgi-bin directory instead of one per virtual host:

# LocalModule directive required 
LoadModule vhost_alias_module /QSYS.LIB/QHTTPSVR.LIB/QZSRCORE.SRVPGM 
# get the server name from the Host: header 
UseCanonicalName off 
# include part of the server name in the filenames 
VirtualDocumentRoot /usr/web/hosts/%2/docs 
# single cgi-bin directory 
ScriptAlias /cgi-bin/ /usr/web/std-cgi/ 
Note: This configuration can be changed into an IP-based virtual hosting solution by just turning UseCanonicalName off into UseCanonicalName DNS. The server name that is inserted into the filename is then derived from the IP address of the virtual host. See UseCanonicalName for more information.

VirtualDocumentRootIP

Module: mod_vhost_alias
Syntax: VirtualDocumentRootIP interpolated-directory
Default: none
Context: server config, virtual host
Override: none
Origin: Apache
Usage Considerations: A LoadModule is required in the config file prior to using the directive. The statement should be as follows: LoadModule vhost_alias_module /QSYS.LIB/QHTTPSVR.LIB/QZSRCORE.SRVPGM
Example: See VirtualDocumentRoot.
Parameter: interpolated-directory
  • The interpolated-directory parameter the full path to a directory.

More complicated setups can use the server's normal <VirtualHost> directives to control the scope of the various virtual hosting configurations. For example, you could have one IP address for home page customers and another for commercial customers with the following directives. This can of course be combined with conventional <VirtualHost> configuration sections.

UseCanonicalName off 

LogFormat "%V %h %l %u %t \"%r\" %s %b" vcommon 

<Directory /usr/web/commercial> 
Options FollowSymLinks 
AllowOverride All 
</Directory> 

<Directory /usr/web/homepages> 
Options FollowSymLinks 
AllowOverride None 
</Directory> 
# LocalModule directive required 
LoadModule vhost_alias_module /QSYS.LIB/QHTTPSVR.LIB/QZSRCORE.SRVPGM 


<VirtualHost 10.22.33.44> 
ServerName www.commercial.isp.com 
CustomLog logs/access_log.commercial vcommon 
VirtualDocumentRoot /usr/web/commercial/%0/docs 
VirtualScriptAlias /usr/web/commercial/%0/cgi-bin 
</VirtualHost> 
<VirtualHost 10.22.33.45> 
ServerName www.homepages.isp.com 
CustomLog logs/access_log.homepages vcommon 
VirtualDocumentRoot /usr/web/homepages/%0/docs 
ScriptAlias /cgi-bin/ /usr/web/std-cgi/ 
</VirtualHost>

More efficient IP-based virtual hosting:

In the first example note that it is easy to turn it into an IP-based virtual hosting setup. Unfortunately that configuration is not very efficient because it requires a DNS lookup for every request. This can be avoided by laying out the filesystem according to the IP addresses themselves rather than the corresponding names and changing the logging similarly. HTTP Server will not usually need to work out the server name and a DNS lookup. For example:

# Get the server name from the reverse DNS of the IP address 
UseCanonicalName DNS 
# LocalModule directive required 
LoadModule vhost_alias_module /QSYS.LIB/QHTTPSVR.LIB/QZSRCORE.SRVPGM 

# include the IP address in the logs so they may be split 
LogFormat "%A %h %l %u %t \"%r\" %s %b" vcommon 
CustomLog logs/access_log vcommon 
# include the IP address in the filenames 
VirtualDocumentRootIP /usr/web/hosts/%0/docs 
VirtualScriptAliasIP /usr/web/hosts/%0/cgi-bin

The VirtualDocumentRootIP directive is like the VirtualDocumentRoot directive, except that it uses the IP address of the server end of the connection instead of the server name. See VirtualDocumentRoot for more information.

VirtualScriptAlias

Module: mod_vhost_alias
Syntax: VirtualScriptAlias interpolated-directory
Default: none
Context: server config, virtual host
Override: none
Origin: Apache
Usage Considerations: A LoadModule is required in the config file prior to using the directive. The statement should be as follows: LoadModule vhost_alias_module /QSYS.LIB/QHTTPSVR.LIB/QZSRCORE.SRVPGM
Example: See below.
Parameter: interpolated-directory
  • The interpolated-directory parameter the full path to a directory.

Using more than one virtual hosting system on the same server instance:

More complicated setups use the server's normal <VirtualHost> directives to control the scope of the various virtual hosting configurations. For example, you could have one IP address for homepages customers and another for commercial customers with the following directives. This can of course be combined with conventional <VirtualHost> configuration sections.

UseCanonicalName off 

LogFormat "%V %h %l %u %t \"%r\" %s %b" vcommon 

<Directory/usr/web/commercial> 
Options FollowSymLinks 
AllowOverride All 


</Directory> 
<Directory /usr/web/homepages> 
Options FollowSymLinks 
AllowOverride None 
</Directory> 


# LocalModule directive required 
LoadModule vhost_alias_module /QSYS.LIB/QHTTPSVR.LIB/QZSRCORE.SRVPGM 
<VirtualHost 10.22.33.44> 
ServerName www.commercial.isp.com 
CustomLog logs/access_log.commercial vcommon 
VirtualDocumentRoot /usr/web/commercial/%0/docs 
VirtualScriptAlias /usr/web/commercial/%0/cgi-bin 
</VirtualHost> 


<VirtualHost 10.22.33.45> 
ServerName www.homepages.isp.com 
CustomLog logs/access_log.homepages vcommon 
VirtualDocumentRoot /usr/web/homepages/%0/docs 
ScriptAlias /cgi-bin/ /usr/web/std-cgi/ 
</VirtualHost>
Note: The VirtualScriptAlias directive allows you to specify the directory path where the server will find CGI scripts in a similar manner to VirtualDocumentRoot does for other documents. In this case the target directory of the CGI scripts must be named "cgi-bin". For example:
VirtualScriptAlias /user/web/commercial/%0/cgi-bin

VirtualScriptAliasIP

Module: mod_vhost_alias
Syntax: VirtualScriptAliasIP interpolated-directory
Default: none
Context: server config, virtual host
Override: none
Origin: Apache
Usage Considerations: A LoadModule is required in the config file prior to using the directive. The statement should be as follows: LoadModule vhost_alias_module /QSYS.LIB/QHTTPSVR.LIB/QZSRCORE.SRVPGM
Example: See VirtualScriptAlias.

The VirtualScriptAliasIP directive is like the VirtualScriptAlias directive, except that it uses the IP address of the server end of the connection instead of the server name.

Parameter: interpolated-directory
  • The interpolated-directory parameter the full path to a directory.