1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
4<html xmlns="http://www.w3.org/1999/xhtml">
5  <head>
6    <meta name="generator" content="HTML Tidy, see www.w3.org" />
7
8    <title>Dynamically configured mass virtual hosting</title>
9  </head>
10  <!-- Background white, links blue (unvisited), navy (visited), red (active) -->
11
12  <body bgcolor="#FFFFFF" text="#000000" link="#0000FF"
13  vlink="#000080" alink="#FF0000">
14        <div align="CENTER">
15      <img src="../images/sub.gif" alt="[APACHE DOCUMENTATION]" />
16
17      <h3>Apache HTTP Server Version 1.3</h3>
18    </div>
19
20
21    <h1 align="CENTER">Dynamically configured mass virtual
22    hosting</h1>
23
24    <p>This document describes how to efficiently serve an
25    arbitrary number of virtual hosts with Apache 1.3. <!--
26
27                Written by Tony Finch (fanf@demon.net) (dot@dotat.at).
28
29                Some examples were derived from Ralf S. Engleschall's document
30                    http://www.engelschall.com/pw/apache/rewriteguide/
31
32                Some suggestions were made by Brian Behlendorf.
33
34                -->
35    </p>
36
37    <h2><a id="contents" name="contents">Contents:</a></h2>
38
39    <ul>
40      <li><a href="#motivation">Motivation</a></li>
41
42      <li><a href="#overview">Overview</a></li>
43
44      <li><a href="#simple">Simple dynamic virtual hosts</a></li>
45
46      <li><a href="#homepages">A virtually hosted homepages
47      system</a></li>
48
49      <li><a href="#combinations">Using more than one virtual
50      hosting system on the same server</a></li>
51
52      <li><a href="#ipbased">More efficient IP-based virtual
53      hosting</a></li>
54
55      <li><a href="#oldversion">Using older versions of
56      Apache</a></li>
57
58      <li><a href="#simple.rewrite">Simple dynamic virtual hosts
59      using <code>mod_rewrite</code></a></li>
60
61      <li><a href="#homepages.rewrite">A homepages system using
62      <code>mod_rewrite</code></a></li>
63
64      <li><a href="#xtra-conf">Using a separate virtual host
65      configuration file</a></li>
66    </ul>
67    <hr />
68
69    <h2><a id="motivation" name="motivation">Motivation</a></h2>
70
71    <p>The techniques described here are of interest if your
72    <code>httpd.conf</code> contains many
73    <code>&lt;VirtualHost&gt;</code> sections that are
74    substantially the same, for example:</p>
75<pre>
76NameVirtualHost 111.22.33.44
77&lt;VirtualHost 111.22.33.44&gt;
78    ServerName                 www.customer-1.com
79    DocumentRoot        /www/hosts/www.customer-1.com/docs
80    ScriptAlias  /cgi-bin/  /www/hosts/www.customer-1.com/cgi-bin
81&lt;/VirtualHost&gt;
82&lt;VirtualHost 111.22.33.44&gt;
83    ServerName                 www.customer-2.com
84    DocumentRoot        /www/hosts/www.customer-2.com/docs
85    ScriptAlias  /cgi-bin/  /www/hosts/www.customer-2.com/cgi-bin
86&lt;/VirtualHost&gt;
87# blah blah blah
88&lt;VirtualHost 111.22.33.44&gt;
89    ServerName                 www.customer-N.com
90    DocumentRoot        /www/hosts/www.customer-N.com/docs
91    ScriptAlias  /cgi-bin/  /www/hosts/www.customer-N.com/cgi-bin
92&lt;/VirtualHost&gt;
93</pre>
94    <br />
95     <br />
96
97
98    <p>The basic idea is to replace all of the static
99    <code>&lt;VirtualHost&gt;</code> configuration with a mechanism
100    that works it out dynamically. This has a number of
101    advantages:</p>
102
103    <ol>
104      <li>Your configuration file is smaller so Apache starts
105      faster and uses less memory.</li>
106
107      <li>Adding virtual hosts is simply a matter of creating the
108      appropriate directories in the filesystem and entries in the
109      DNS - you don't need to reconfigure or restart Apache.</li>
110    </ol>
111    <br />
112     <br />
113
114
115    <p>The main disadvantage is that you cannot have a different
116    log file for each virtual host; however if you have very many
117    virtual hosts then doing this is dubious anyway because it eats
118    file descriptors. It is better to log to a pipe or a fifo and
119    arrange for the process at the other end to distribute the logs
120    to the customers (it can also accumulate statistics, etc.).</p>
121    <hr />
122
123    <h2><a id="overview" name="overview">Overview</a></h2>
124
125    <p>A virtual host is defined by two pieces of information: its
126    IP address, and the contents of the <code>Host:</code> header
127    in the HTTP request. The dynamic mass virtual hosting technique
128    is based on automatically inserting this information into the
129    pathname of the file that is used to satisfy the request. This
130    is done most easily using <a
131    href="../mod/mod_vhost_alias.html"><code>mod_vhost_alias</code></a>,
132    but if you are using a version of Apache up to 1.3.6 then you
133    must use <a
134    href="../mod/mod_rewrite.html"><code>mod_rewrite</code></a>.
135    Both of these modules are disabled by default; you must enable
136    one of them when configuring and building Apache if you want to
137    use this technique.</p>
138
139    <p>A couple of things need to be `faked' to make the dynamic
140    virtual host look like a normal one. The most important is the
141    server name which is used by Apache to generate
142    self-referential URLs, etc. It is configured with the
143    <code>ServerName</code> directive, and it is available to CGIs
144    via the <code>SERVER_NAME</code> environment variable. The
145    actual value used at run time is controlled by the <a
146    href="../mod/core.html#usecanonicalname"><code>UseCanonicalName</code></a>
147    setting. With <code>UseCanonicalName Off</code> the server name
148    comes from the contents of the <code>Host:</code> header in the
149    request. With <code>UseCanonicalName DNS</code> it comes from a
150    reverse DNS lookup of the virtual host's IP address. The former
151    setting is used for name-based dynamic virtual hosting, and the
152    latter is used for IP-based hosting. If Apache cannot work out
153    the server name because there is no <code>Host:</code> header
154    or the DNS lookup fails then the value configured with
155    <code>ServerName</code> is used instead.</p>
156
157    <p>The other thing to `fake' is the document root (configured
158    with <code>DocumentRoot</code> and available to CGIs via the
159    <code>DOCUMENT_ROOT</code> environment variable). In a normal
160    configuration this setting is used by the core module when
161    mapping URIs to filenames, but when the server is configured to
162    do dynamic virtual hosting that job is taken over by another
163    module (either <code>mod_vhost_alias</code> or
164    <code>mod_rewrite</code>) which has a different way of doing
165    the mapping. Neither of these modules is responsible for
166    setting the <code>DOCUMENT_ROOT</code> environment variable so
167    if any CGIs or SSI documents make use of it they will get a
168    misleading value.</p>
169    <hr />
170
171    <h2><a id="simple" name="simple">Simple dynamic virtual
172    hosts</a></h2>
173
174    <p>This extract from <code>httpd.conf</code> implements the
175    virtual host arrangement outlined in the <a
176    href="#motivation">Motivation</a> section above, but in a
177    generic fashion using <code>mod_vhost_alias</code>.</p>
178<pre>
179# get the server name from the Host: header
180UseCanonicalName Off
181
182# this log format can be split per-virtual-host based on the first field
183LogFormat "%V %h %l %u %t \"%r\" %s %b" vcommon
184CustomLog logs/access_log vcommon
185
186# include the server name in the filenames used to satisfy requests
187VirtualDocumentRoot /www/hosts/%0/docs
188VirtualScriptAlias  /www/hosts/%0/cgi-bin
189</pre>
190
191    <p>This configuration can be changed into an IP-based virtual
192    hosting solution by just turning <code>UseCanonicalName
193    Off</code> into <code>UseCanonicalName DNS</code>. The server
194    name that is inserted into the filename is then derived from
195    the IP address of the virtual host.</p>
196    <hr />
197
198    <h2><a id="homepages" name="homepages">A virtually hosted
199    homepages system</a></h2>
200
201    <p>This is an adjustment of the above system tailored for an
202    ISP's homepages server. Using a slightly more complicated
203    configuration we can select substrings of the server name to
204    use in the filename so that e.g. the documents for
205    <samp>www.user.isp.com</samp> are found in
206    <code>/home/user/</code>. It uses a single <code>cgi-bin</code>
207    directory instead of one per virtual host.</p>
208<pre>
209# all the preliminary stuff is the same as above, then
210
211# include part of the server name in the filenames
212VirtualDocumentRoot /www/hosts/%2/docs
213
214# single cgi-bin directory
215ScriptAlias  /cgi-bin/  /www/std-cgi/
216</pre>
217
218    <p>There are examples of more complicated
219    <code>VirtualDocumentRoot</code> settings in <a
220    href="../mod/mod_vhost_alias.html">the
221    <code>mod_vhost_alias</code> documentation</a>.</p>
222    <hr />
223
224    <h2><a id="combinations" name="combinations">Using more than
225    one virtual hosting system on the same server</a></h2>
226
227    <p>With more complicated setups you can use Apache's normal
228    <code>&lt;VirtualHost&gt;</code> directives to control the
229    scope of the various virtual hosting configurations. For
230    example, you could have one IP address for homepages customers
231    and another for commercial customers with the following setup.
232    This can of course be combined with conventional
233    <code>&lt;VirtualHost&gt;</code> configuration sections.</p>
234<pre>
235UseCanonicalName Off
236
237LogFormat "%V %h %l %u %t \"%r\" %s %b" vcommon
238
239&lt;Directory /www/commercial&gt;
240    Options FollowSymLinks
241    AllowOverride All
242&lt;/Directory&gt;
243
244&lt;Directory /www/homepages&gt;
245    Options FollowSymLinks
246    AllowOverride None
247&lt;/Directory&gt;
248
249&lt;VirtualHost 111.22.33.44&gt;
250    ServerName www.commercial.isp.com
251
252    CustomLog logs/access_log.commercial vcommon
253
254    VirtualDocumentRoot /www/commercial/%0/docs
255    VirtualScriptAlias  /www/commercial/%0/cgi-bin
256&lt;/VirtualHost&gt;
257
258&lt;VirtualHost 111.22.33.45&gt;
259    ServerName www.homepages.isp.com
260
261    CustomLog logs/access_log.homepages vcommon
262
263    VirtualDocumentRoot /www/homepages/%0/docs
264    ScriptAlias         /cgi-bin/ /www/std-cgi/
265&lt;/VirtualHost&gt;
266</pre>
267    <hr />
268
269    <h2><a id="ipbased" name="ipbased">More efficient IP-based
270    virtual hosting</a></h2>
271
272    <p>After <a href="#simple">the first example</a> I noted that
273    it is easy to turn it into an IP-based virtual hosting setup.
274    Unfortunately that configuration is not very efficient because
275    it requires a DNS lookup for every request. This can be avoided
276    by laying out the filesystem according to the IP addresses
277    themselves rather than the corresponding names and changing the
278    logging similarly. Apache will then usually not need to work
279    out the server name and so incur a DNS lookup.</p>
280<pre>
281# get the server name from the reverse DNS of the IP address
282UseCanonicalName DNS
283
284# include the IP address in the logs so they may be split
285LogFormat "%A %h %l %u %t \"%r\" %s %b" vcommon
286CustomLog logs/access_log vcommon
287
288# include the IP address in the filenames
289VirtualDocumentRootIP /www/hosts/%0/docs
290VirtualScriptAliasIP  /www/hosts/%0/cgi-bin
291</pre>
292    <hr />
293
294    <h2><a id="oldversion" name="oldversion">Using older versions
295    of Apache</a></h2>
296
297    <p>The examples above rely on <code>mod_vhost_alias</code>
298    which appeared after version 1.3.6. If you are using a version
299    of Apache without <code>mod_vhost_alias</code> then you can
300    implement this technique with <code>mod_rewrite</code> as
301    illustrated below, but only for Host:-header-based virtual
302    hosts.</p>
303
304    <p>In addition there are some things to beware of with logging.
305    Apache 1.3.6 is the first version to include the
306    <code>%V</code> log format directive; in versions 1.3.0 - 1.3.3
307    the <code>%v</code> option did what <code>%V</code> does;
308    version 1.3.4 has no equivalent. In all these versions of
309    Apache the <code>UseCanonicalName</code> directive can appear
310    in <code>.htaccess</code> files which means that customers can
311    cause the wrong thing to be logged. Therefore the best thing to
312    do is use the <code>%{Host}i</code> directive which logs the
313    <code>Host:</code> header directly; note that this may include
314    <code>:port</code> on the end which is not the case for
315    <code>%V</code>.</p>
316    <hr />
317
318    <h2><a id="simple.rewrite" name="simple.rewrite">Simple dynamic
319    virtual hosts using <code>mod_rewrite</code></a></h2>
320
321    <p>This extract from <code>httpd.conf</code> does the same
322    thing as <a href="#simple">the first example</a>. The first
323    half is very similar to the corresponding part above but with
324    some changes for backward compatibility and to make the
325    <code>mod_rewrite</code> part work properly; the second half
326    configures <code>mod_rewrite</code> to do the actual work.</p>
327
328    <p>There are a couple of especially tricky bits: By default,
329    <code>mod_rewrite</code> runs before the other URI translation
330    modules (<code>mod_alias</code> etc.) so if they are used then
331    <code>mod_rewrite</code> must be configured to accommodate
332    them. Also, mome magic must be performed to do a
333    per-dynamic-virtual-host equivalent of
334    <code>ScriptAlias</code>.</p>
335<pre>
336# get the server name from the Host: header
337UseCanonicalName Off
338
339# splittable logs
340LogFormat "%{Host}i %h %l %u %t \"%r\" %s %b" vcommon
341CustomLog logs/access_log vcommon
342
343&lt;Directory /www/hosts&gt;
344    # ExecCGI is needed here because we can't force
345    # CGI execution in the way that ScriptAlias does
346    Options FollowSymLinks ExecCGI
347&lt;/Directory&gt;
348
349# now for the hard bit
350
351RewriteEngine On
352
353# a ServerName derived from a Host: header may be any case at all
354RewriteMap  lowercase  int:tolower
355
356## deal with normal documents first:
357# allow Alias /icons/ to work - repeat for other aliases
358RewriteCond  %{REQUEST_URI}  !^/icons/
359# allow CGIs to work
360RewriteCond  %{REQUEST_URI}  !^/cgi-bin/
361# do the magic
362RewriteRule  ^/(.*)$  /www/hosts/${lowercase:%{SERVER_NAME}}/docs/$1
363
364## and now deal with CGIs - we have to force a MIME type
365RewriteCond  %{REQUEST_URI}  ^/cgi-bin/
366RewriteRule  ^/(.*)$  /www/hosts/${lowercase:%{SERVER_NAME}}/cgi-bin/$1  [T=application/x-httpd-cgi]
367
368# that's it!
369</pre>
370    <hr />
371
372    <h2><a id="homepages.rewrite" name="homepages.rewrite">A
373    homepages system using <code>mod_rewrite</code></a></h2>
374
375    <p>This does the same thing as <a href="#homepages">the second
376    example</a>.</p>
377<pre>
378RewriteEngine on
379
380RewriteMap   lowercase  int:tolower
381
382# allow CGIs to work
383RewriteCond  %{REQUEST_URI}  !^/cgi-bin/
384
385# check the hostname is right so that the RewriteRule works
386RewriteCond  ${lowercase:%{SERVER_NAME}}  ^www\.[a-z-]+\.isp\.com$
387
388# concatenate the virtual host name onto the start of the URI
389# the [C] means do the next rewrite on the result of this one
390RewriteRule  ^(.+)  ${lowercase:%{SERVER_NAME}}$1  [C]
391
392# now create the real file name
393RewriteRule  ^www\.([a-z-]+)\.isp\.com/(.*) /home/$1/$2
394
395# define the global CGI directory
396ScriptAlias  /cgi-bin/  /www/std-cgi/
397</pre>
398    <hr />
399
400    <h2><a id="xtra-conf" name="xtra-conf">Using a separate virtual
401    host configuration file</a></h2>
402
403    <p>This arrangement uses more advanced <code>mod_rewrite</code>
404    features to get the translation from virtual host to document
405    root from a separate configuration file. This provides more
406    flexibility but requires more complicated configuration.</p>
407
408    <p>The <code>vhost.map</code> file contains something like
409    this:</p>
410<pre>
411www.customer-1.com  /www/customers/1
412www.customer-2.com  /www/customers/2
413# ...
414www.customer-N.com  /www/customers/N
415</pre>
416    <br />
417     <br />
418
419
420    <p>The <code>http.conf</code> contains this:</p>
421<pre>
422RewriteEngine on
423
424RewriteMap   lowercase  int:tolower
425
426# define the map file
427RewriteMap   vhost      txt:/www/conf/vhost.map
428
429# deal with aliases as above
430RewriteCond  %{REQUEST_URI}               !^/icons/
431RewriteCond  %{REQUEST_URI}               !^/cgi-bin/
432RewriteCond  ${lowercase:%{SERVER_NAME}}  ^(.+)$
433# this does the file-based remap
434RewriteCond  ${vhost:%1}                  ^(/.*)$
435RewriteRule  ^/(.*)$                      %1/docs/$1
436
437RewriteCond  %{REQUEST_URI}               ^/cgi-bin/
438RewriteCond  ${lowercase:%{SERVER_NAME}}  ^(.+)$
439RewriteCond  ${vhost:%1}                  ^(/.*)$
440RewriteRule  ^/(.*)$                      %1/cgi-bin/$1
441</pre>
442    <br />
443     <br />
444         <hr />
445
446    <h3 align="CENTER">Apache HTTP Server Version 1.3</h3>
447    <a href="./"><img src="../images/index.gif" alt="Index" /></a>
448    <a href="../"><img src="../images/home.gif" alt="Home" /></a>
449
450  </body>
451</html>
452
453