mirror of
https://github.com/apache/httpd.git
synced 2025-08-26 05:42:34 +03:00
Suggested by: Scott Goodman <scott@searchbc.com> git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@84904 13f79535-47bb-0310-9956-ffa450edef68
406 lines
14 KiB
HTML
406 lines
14 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
|
|
<HTML><HEAD>
|
|
<TITLE>Dynamically configured mass virtual hosting</TITLE>
|
|
</HEAD>
|
|
|
|
<!-- Background white, links blue (unvisited), navy (visited), red (active) -->
|
|
<BODY
|
|
BGCOLOR="#FFFFFF"
|
|
TEXT="#000000"
|
|
LINK="#0000FF"
|
|
VLINK="#000080"
|
|
ALINK="#FF0000"
|
|
>
|
|
<!--#include virtual="header.html" -->
|
|
<H1 ALIGN="CENTER">Dynamically configured mass virtual hosting</H1>
|
|
|
|
<P>This document describes how to efficiently serve an arbitrary number
|
|
of virtual hosts with Apache 1.3.
|
|
|
|
<!--
|
|
|
|
Written by Tony Finch (fanf@demon.net) (dot@dotat.at).
|
|
|
|
Some examples were derived from Ralf S. Engleschall's document
|
|
http://www.engelschall.com/pw/apache/rewriteguide/
|
|
|
|
Some suggestions were made by Brian Behlendorf.
|
|
|
|
-->
|
|
|
|
<H2><A NAME="contents">Contents:</A></H2>
|
|
|
|
<UL>
|
|
<LI><A HREF="#motivation">Motivation</A>
|
|
<LI><A HREF="#overview">Overview</A>
|
|
<LI><A HREF="#simple">Simple dynamic virtual hosts</A>
|
|
<LI><A HREF="#homepages">A virtually hosted homepages system</A>
|
|
<LI><A HREF="#combinations">Using more than one virtual hosting system on the same server</A>
|
|
<LI><A HREF="#ipbased">More efficient IP-based virtual hosting</A>
|
|
<LI><A HREF="#oldversion">Using older versions of Apache</A>
|
|
<LI><A HREF="#simple.rewrite">Simple dynamic virtual hosts using <CODE>mod_rewrite</CODE></A>
|
|
<LI><A HREF="#homepages.rewrite">A homepages system using <CODE>mod_rewrite</CODE></A>
|
|
<LI><A HREF="#xtra-conf">Using a separate virtual host configuration file</A>
|
|
</UL>
|
|
|
|
<HR><H2><A NAME="motivation">Motivation</A></H2>
|
|
|
|
<P>The techniques described here are of interest if your
|
|
<CODE>httpd.conf</CODE> contains many
|
|
<CODE><VirtualHost></CODE> sections that are substantially the
|
|
same, for example:
|
|
<PRE>
|
|
NameVirtualHost 111.22.33.44
|
|
<VirtualHost 111.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 111.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>
|
|
# blah blah blah
|
|
<VirtualHost 111.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>
|
|
</PRE>
|
|
</P>
|
|
|
|
<P>The basic idea is to replace all of the static
|
|
<CODE><VirtualHost></CODE> configuration with a mechanism that
|
|
works it out dynamically. This has a number of advantages:
|
|
<OL>
|
|
<LI>Your configuration file is smaller so Apache starts faster and
|
|
uses less memory.
|
|
<LI>Adding virtual hosts is simply a matter of creating the
|
|
appropriate directories in the filesystem and entries in the DNS -
|
|
you don't need to reconfigure or restart Apache.
|
|
</OL>
|
|
</P>
|
|
|
|
<P>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, etc.).</P>
|
|
|
|
|
|
<HR><H2><A NAME="overview">Overview</A></H2>
|
|
|
|
<P>A virtual host is defined by two pieces of information: its IP
|
|
address, and the contents of the <CODE>Host:</CODE> 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
|
|
<A HREF="../mod/mod_vhost_alias.html"><CODE>mod_vhost_alias</CODE></A>,
|
|
but if you are using a version of Apache up to 1.3.6 then you must use
|
|
<A HREF="../mod/mod_rewrite.html"><CODE>mod_rewrite</CODE></A>. Both
|
|
of these modules are disabled by default; you must enable one of them
|
|
when configuring and building Apache if you want to use this technique.</P>
|
|
|
|
<P>A couple of things need to be `faked' to make the dynamic virtual
|
|
host look like a normal one. The most important is the server name
|
|
which is used by Apache to generate self-referential URLs, etc. It
|
|
is configured with the <CODE>ServerName</CODE> directive, and it is
|
|
available to CGIs via the <CODE>SERVER_NAME</CODE> environment
|
|
variable. The actual value used at run time is controlled by the
|
|
<A HREF="../mod/core.html#usecanonicalname"><CODE>UseCanonicalName</CODE></A>
|
|
setting. With <CODE>UseCanonicalName Off</CODE> the server name
|
|
comes from the contents of the <CODE>Host:</CODE> header in the
|
|
request. With <CODE>UseCanonicalName DNS</CODE> 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 Apache cannot work out the server
|
|
name because there is no <CODE>Host:</CODE> header or the DNS lookup
|
|
fails then the value configured with <CODE>ServerName</CODE> is used
|
|
instead.</P>
|
|
|
|
<P>The other thing to `fake' is the document root (configured
|
|
with <CODE>DocumentRoot</CODE> and available to CGIs via the
|
|
<CODE>DOCUMENT_ROOT</CODE> environment variable). In a normal
|
|
configuration 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 another module (either
|
|
<CODE>mod_vhost_alias</CODE> or <CODE>mod_rewrite</CODE>) which has
|
|
a different way of doing the mapping. Neither of these modules is
|
|
responsible for setting the <CODE>DOCUMENT_ROOT</CODE> environment
|
|
variable so if any CGIs or SSI documents make use of it they will
|
|
get a misleading value.</P>
|
|
|
|
|
|
<HR><H2><A NAME="simple">Simple dynamic virtual hosts</A></H2>
|
|
|
|
<P>This extract from <CODE>httpd.conf</CODE> implements the virtual
|
|
host arrangement outlined in the <A HREF="#motivation">Motivation</A>
|
|
section above, but in a generic fashion using
|
|
<CODE>mod_vhost_alias</CODE>.</P>
|
|
|
|
<PRE>
|
|
# 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
|
|
</PRE>
|
|
|
|
<P>This configuration can be changed into an IP-based virtual hosting
|
|
solution by just turning <CODE>UseCanonicalName Off</CODE> into
|
|
<CODE>UseCanonicalName DNS</CODE>. The server name that is inserted
|
|
into the filename is then derived from the IP address of the virtual
|
|
host.</P>
|
|
|
|
|
|
<HR><H2><A NAME="homepages">A virtually hosted homepages system</A></H2>
|
|
|
|
<P>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 <SAMP>www.user.isp.com</SAMP> are found in
|
|
<CODE>/home/user/</CODE>. It uses a single <CODE>cgi-bin</CODE>
|
|
directory instead of one per virtual host.</P>
|
|
|
|
<PRE>
|
|
# 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/
|
|
</PRE>
|
|
|
|
<P>There are examples of more complicated
|
|
<CODE>VirtualDocumentRoot</CODE> settings in
|
|
<A HREF="../mod/mod_vhost_alias.html">the
|
|
<CODE>mod_vhost_alias</CODE> documentation</A>.</P>
|
|
|
|
|
|
<HR><H2><A NAME="combinations">Using more than one virtual hosting
|
|
system on the same server</A></H2>
|
|
|
|
<P>With more complicated setups you can use Apache's normal
|
|
<CODE><VirtualHost></CODE> 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 <CODE><VirtualHost></CODE> configuration
|
|
sections.</P>
|
|
|
|
<PRE>
|
|
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 111.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 111.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>
|
|
</PRE>
|
|
|
|
|
|
<HR><H2><A NAME="ipbased">More efficient IP-based virtual hosting</A></H2>
|
|
|
|
<P>After <A HREF="#simple">the first example</A> I noted 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. Apache will
|
|
then usually not need to work out the server name and so incur a DNS
|
|
lookup.</P>
|
|
|
|
<PRE>
|
|
# get the server name from the reverse DNS of the IP address
|
|
UseCanonicalName DNS
|
|
|
|
# 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 /www/hosts/%0/docs
|
|
VirtualScriptAliasIP /www/hosts/%0/cgi-bin
|
|
</PRE>
|
|
|
|
|
|
<HR><H2><A NAME="oldversion">Using older versions of Apache</A></H2>
|
|
|
|
<P>The examples above rely on <CODE>mod_vhost_alias</CODE> which
|
|
appeared after version 1.3.6. If you are using a version of Apache
|
|
without <CODE>mod_vhost_alias</CODE> then you can implement this
|
|
technique with <CODE>mod_rewrite</CODE> as illustrated below, but
|
|
only for Host:-header-based virtual hosts.</P>
|
|
|
|
<P>In addition there are some things to beware of with logging. Apache
|
|
1.3.6 is the first version to include the <CODE>%V</CODE> log format
|
|
directive; in versions 1.3.0 - 1.3.3 the <CODE>%v</CODE> option did
|
|
what <CODE>%V</CODE> does; version 1.3.4 has no equivalent. In
|
|
all these versions of Apache the <CODE>UseCanonicalName</CODE>
|
|
directive can appear in <CODE>.htaccess</CODE> files which means that
|
|
customers can cause the wrong thing to be logged. Therefore the best
|
|
thing to do is use the <CODE>%{Host}i</CODE> directive which logs the
|
|
<CODE>Host:</CODE> header directly; note that this may include
|
|
<CODE>:port</CODE> on the end which is not the case for
|
|
<CODE>%V</CODE>.</P>
|
|
|
|
|
|
<HR><H2><A NAME="simple.rewrite">Simple dynamic virtual hosts
|
|
using <CODE>mod_rewrite</CODE></A></H2>
|
|
|
|
<P>This extract from <CODE>httpd.conf</CODE> does the same thing as
|
|
<A HREF="#simple">the first example</A>. The first half is very
|
|
similar to the corresponding part above but with some changes for
|
|
backward compatibility and to make the <CODE>mod_rewrite</CODE> part
|
|
work properly; the second half configures <CODE>mod_rewrite</CODE> to
|
|
do the actual work.</P>
|
|
|
|
<P>There are a couple of especially tricky bits: By default,
|
|
<CODE>mod_rewrite</CODE> runs before the other URI translation modules
|
|
(<CODE>mod_alias</CODE> etc.) so if they are used then
|
|
<CODE>mod_rewrite</CODE> must be configured to accommodate them.
|
|
Also, mome magic must be performed to do a per-dynamic-virtual-host
|
|
equivalent of <CODE>ScriptAlias</CODE>.</P>
|
|
|
|
<PRE>
|
|
# get the server name from the Host: header
|
|
UseCanonicalName Off
|
|
|
|
# splittable logs
|
|
LogFormat "%{Host}i %h %l %u %t \"%r\" %s %b" vcommon
|
|
CustomLog logs/access_log vcommon
|
|
|
|
<Directory /www/hosts>
|
|
# ExecCGI is needed here because we can't force
|
|
# CGI execution in the way that ScriptAlias does
|
|
Options FollowSymLinks ExecCGI
|
|
</Directory>
|
|
|
|
# now for the hard bit
|
|
|
|
RewriteEngine On
|
|
|
|
# a ServerName derived from a Host: header may be any case at all
|
|
RewriteMap lowercase int:tolower
|
|
|
|
## deal with normal documents first:
|
|
# allow Alias /icons/ to work - repeat for other aliases
|
|
RewriteCond %{REQUEST_URI} !^/icons/
|
|
# allow CGIs to work
|
|
RewriteCond %{REQUEST_URI} !^/cgi-bin/
|
|
# do the magic
|
|
RewriteRule ^/(.*)$ /www/hosts/${lowercase:%{SERVER_NAME}}/docs/$1
|
|
|
|
## and now deal with CGIs - we have to force a MIME type
|
|
RewriteCond %{REQUEST_URI} ^/cgi-bin/
|
|
RewriteRule ^/(.*)$ /www/hosts/${lowercase:%{SERVER_NAME}}/cgi-bin/$1 [T=application/x-httpd-cgi]
|
|
|
|
# that's it!
|
|
</PRE>
|
|
|
|
|
|
<HR><H2><A NAME="homepages.rewrite">A homepages system
|
|
using <CODE>mod_rewrite</CODE></A></H2>
|
|
|
|
<P>This does the same thing as <A HREF="#homepages">the
|
|
second example</A>.</P>
|
|
|
|
<PRE>
|
|
RewriteEngine on
|
|
|
|
RewriteMap lowercase int:tolower
|
|
|
|
# allow CGIs to work
|
|
RewriteCond %{REQUEST_URI} !^/cgi-bin/
|
|
|
|
# check the hostname is right so that the RewriteRule works
|
|
RewriteCond ${lowercase:%{SERVER_NAME}} ^www\.[a-z-]+\.isp\.com$
|
|
|
|
# concatenate the virtual host name onto the start of the URI
|
|
# the [C] means do the next rewrite on the result of this one
|
|
RewriteRule ^(.+) ${lowercase:%{SERVER_NAME}}$1 [C]
|
|
|
|
# now create the real file name
|
|
RewriteRule ^www\.([a-z-]+)\.isp\.com/(.*) /home/$1/$2
|
|
|
|
# define the global CGI directory
|
|
ScriptAlias /cgi-bin/ /www/std-cgi/
|
|
</PRE>
|
|
|
|
|
|
<HR><H2><A NAME="xtra-conf">Using a separate virtual host configuration file</A></H2>
|
|
|
|
<P>This arrangement uses more advanced <CODE>mod_rewrite</CODE>
|
|
features to get the translation from virtual host to document root
|
|
from a separate configuration file. This provides more flexibility but
|
|
requires more complicated configuration.</P>
|
|
|
|
<P>The <CODE>vhost.map</CODE> file contains something like this:
|
|
<PRE>
|
|
www.customer-1.com /www/customers/1
|
|
www.customer-2.com /www/customers/2
|
|
# ...
|
|
www.customer-N.com /www/customers/N
|
|
</PRE>
|
|
</P>
|
|
|
|
<P>The <CODE>http.conf</CODE> contains this:
|
|
<PRE>
|
|
RewriteEngine on
|
|
|
|
RewriteMap lowercase int:tolower
|
|
|
|
# define the map file
|
|
RewriteMap vhost txt:/www/conf/vhost.map
|
|
|
|
# deal with aliases as above
|
|
RewriteCond %{REQUEST_URI} !^/icons/
|
|
RewriteCond %{REQUEST_URI} !^/cgi-bin/
|
|
RewriteCond ${lowercase:%{SERVER_NAME}} ^(.+)$
|
|
# this does the file-based remap
|
|
RewriteCond ${vhost:%1} ^(/.*)$
|
|
RewriteRule ^/(.*)$ %1/docs/$1
|
|
|
|
RewriteCond %{REQUEST_URI} ^/cgi-bin/
|
|
RewriteCond ${lowercase:%{SERVER_NAME}} ^(.+)$
|
|
RewriteCond ${vhost:%1} ^(/.*)$
|
|
RewriteRule ^/(.*)$ %1/cgi-bin/$1
|
|
</PRE>
|
|
</P>
|
|
|
|
<!--#include virtual="footer.html" -->
|
|
</BODY>
|
|
</HTML>
|