1 <?xml version='1.0' encoding='UTF-8' ?>
2 <!DOCTYPE manualpage SYSTEM "../style/manualpage.dtd">
3 <?xml-stylesheet type="text/xsl" href="../style/manual.en.xsl"?>
4 <!-- $LastChangedRevision$ -->
7 Licensed to the Apache Software Foundation (ASF) under one or more
8 contributor license agreements. See the NOTICE file distributed with
9 this work for additional information regarding copyright ownership.
10 The ASF licenses this file to You under the Apache License, Version 2.0
11 (the "License"); you may not use this file except in compliance with
12 the License. You may obtain a copy of the License at
14 http://www.apache.org/licenses/LICENSE-2.0
16 Unless required by applicable law or agreed to in writing, software
17 distributed under the License is distributed on an "AS IS" BASIS,
18 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 See the License for the specific language governing permissions and
20 limitations under the License.
23 <manualpage metafile="mass.xml.meta">
24 <parentdocument href="./">Virtual Hosts</parentdocument>
25 <title>Dynamically Configured Mass Virtual Hosting</title>
29 <p>This document describes how to efficiently serve an
30 arbitrary number of virtual hosts with the Apache httpd webserver.
35 <section id="motivation"><title>Motivation</title>
37 <p>The techniques described here are of interest if your
38 <code>httpd.conf</code> contains many
39 <code><VirtualHost></code> sections that are
40 substantially the same, for example:</p>
43 NameVirtualHost 111.22.33.44<br />
44 <VirtualHost 111.22.33.44><br />
46 ServerName www.customer-1.com<br />
47 DocumentRoot /www/hosts/www.customer-1.com/docs<br />
48 ScriptAlias /cgi-bin/ /www/hosts/www.customer-1.com/cgi-bin<br />
50 </VirtualHost><br />
51 <VirtualHost 111.22.33.44><br />
53 ServerName www.customer-2.com<br />
54 DocumentRoot /www/hosts/www.customer-2.com/docs<br />
55 ScriptAlias /cgi-bin/ /www/hosts/www.customer-2.com/cgi-bin<br />
57 </VirtualHost><br />
58 # blah blah blah<br />
59 <VirtualHost 111.22.33.44><br />
61 ServerName www.customer-N.com<br />
62 DocumentRoot /www/hosts/www.customer-N.com/docs<br />
63 ScriptAlias /cgi-bin/ /www/hosts/www.customer-N.com/cgi-bin<br />
68 <p>The basic idea is to replace all of the static
69 <code><VirtualHost></code> configurations with a mechanism
70 that works them out dynamically. This has a number of
74 <li>Your configuration file is smaller, so Apache starts
75 more quickly and uses less memory.</li>
77 <li>Adding virtual hosts is simply a matter of creating the
78 appropriate directories in the filesystem and entries in the
79 DNS - you don't need to reconfigure or restart Apache.</li>
82 <p>The main disadvantage is that you cannot have a different log file for
83 each virtual host; however, if you have many virtual hosts, doing
84 this can be a bad idea anyway, because of the number of file
85 descriptors needed. It is better to log to a pipe or a fifo, and arrange for
86 the process at the other end to distribute the logs to the customers.
87 (This can also be used to accumulate statistics, etc.).</p>
91 <section id="overview"><title>Overview</title>
93 <p>A virtual host is defined by two pieces of information: its
94 IP address, and the contents of the <code>Host:</code> header
95 in the HTTP request. The dynamic mass virtual hosting technique
96 used here is based on automatically inserting this information into the
97 pathname of the file that is used to satisfy the request. This
98 can be most easily done by using <module>mod_vhost_alias</module>
99 with Apache 2.0. Alternatively, <module>mod_rewrite</module> can be used.
100 Both of these modules are disabled by default; you must enable
101 one of them when configuring and building Apache if you want to
102 use this technique.</p>
104 <p>A couple of things need to be `faked' to make the dynamic
105 virtual host look like a normal one. The most important is the
106 server name, which is used by Apache to generate
107 self-referential URLs etc. It is configured with the
108 <code>ServerName</code> directive, and it is available to CGIs
109 via the <code>SERVER_NAME</code> environment variable. The
110 actual value used at run time is controlled by the <directive
111 module="core">UseCanonicalName</directive>
112 setting. With <code>UseCanonicalName Off</code>, the server name
113 is taken from the contents of the <code>Host:</code> header in the
114 request. With <code>UseCanonicalName DNS</code>, it is taken from a
115 reverse DNS lookup of the virtual host's IP address. The former
116 setting is used for name-based dynamic virtual hosting, and the
117 latter is used for IP-based hosting. If Apache cannot work out
118 the server name because there is no <code>Host:</code> header,
119 or the DNS lookup fails, then the value configured with
120 <code>ServerName</code> is used instead.</p>
122 <p>The other thing to `fake' is the document root (configured
123 with <code>DocumentRoot</code> and available to CGIs via the
124 <code>DOCUMENT_ROOT</code> environment variable). In a normal
125 configuration, this is used by the core module when
126 mapping URIs to filenames, but when the server is configured to
127 do dynamic virtual hosting, that job must be taken over by another
128 module (either <code>mod_vhost_alias</code> or
129 <code>mod_rewrite</code>), which has a different way of doing
130 the mapping. Neither of these modules is responsible for
131 setting the <code>DOCUMENT_ROOT</code> environment variable so
132 if any CGIs or SSI documents make use of it, they will get a
133 misleading value.</p>
137 <section id="simple"><title>Simple Dynamic Virtual Hosts</title>
139 <p>This extract from <code>httpd.conf</code> implements the
140 virtual host arrangement outlined in the <a
141 href="#motivation">Motivation</a> section above, but in a
142 generic fashion using <code>mod_vhost_alias</code>.</p>
145 # get the server name from the Host: header<br />
146 UseCanonicalName Off<br />
148 # this log format can be split per-virtual-host based on the first field<br />
149 LogFormat "%V %h %l %u %t \"%r\" %s %b" vcommon<br />
150 CustomLog logs/access_log vcommon<br />
152 # include the server name in the filenames used to satisfy requests<br />
153 VirtualDocumentRoot /www/hosts/%0/docs<br />
154 VirtualScriptAlias /www/hosts/%0/cgi-bin
157 <p>This configuration can be changed into an IP-based virtual
158 hosting solution by just turning <code>UseCanonicalName
159 Off</code> into <code>UseCanonicalName DNS</code>. The server
160 name that is inserted into the filename is then derived from
161 the IP address of the virtual host.</p>
165 <section id="homepages"><title>A Virtually Hosted Homepages System</title>
167 <p>This is an adjustment of the above system, tailored for an
168 ISP's homepages server. Using a slightly more complicated
169 configuration, we can select substrings of the server name to
170 use in the filename so that, for example, the documents for
171 <code>www.user.isp.com</code> are found in
172 <code>/home/user/</code>. It uses a single <code>cgi-bin</code>
173 directory instead of one per virtual host.</p>
176 # all the preliminary stuff is the same as above, then<br />
178 # include part of the server name in the filenames<br />
179 VirtualDocumentRoot /www/hosts/%2/docs<br />
181 # single cgi-bin directory<br />
182 ScriptAlias /cgi-bin/ /www/std-cgi/<br />
185 <p>There are examples of more complicated
186 <code>VirtualDocumentRoot</code> settings in the
187 <module>mod_vhost_alias</module> documentation.</p>
191 <section id="combinations"><title>Using Multiple Virtual
192 Hosting Systems on the Same Server</title>
194 <p>With more complicated setups, you can use Apache's normal
195 <code><VirtualHost></code> directives to control the
196 scope of the various virtual hosting configurations. For
197 example, you could have one IP address for general customers' homepages,
198 and another for commercial customers, with the following setup.
199 This can, of course, be combined with conventional
200 <code><VirtualHost></code> configuration sections.</p>
203 UseCanonicalName Off<br />
205 LogFormat "%V %h %l %u %t \"%r\" %s %b" vcommon<br />
207 <Directory /www/commercial><br />
209 Options FollowSymLinks<br />
210 AllowOverride All<br />
212 </Directory><br />
214 <Directory /www/homepages><br />
216 Options FollowSymLinks<br />
217 AllowOverride None<br />
219 </Directory><br />
221 <VirtualHost 111.22.33.44><br />
223 ServerName www.commercial.isp.com<br />
225 CustomLog logs/access_log.commercial vcommon<br />
227 VirtualDocumentRoot /www/commercial/%0/docs<br />
228 VirtualScriptAlias /www/commercial/%0/cgi-bin<br />
230 </VirtualHost><br />
232 <VirtualHost 111.22.33.45><br />
234 ServerName www.homepages.isp.com<br />
236 CustomLog logs/access_log.homepages vcommon<br />
238 VirtualDocumentRoot /www/homepages/%0/docs<br />
239 ScriptAlias /cgi-bin/ /www/std-cgi/<br />
246 <p>If the first VirtualHost block does <em>not</em> include a
247 <directive module="core">ServerName</directive> directive, the reverse
248 DNS of the relevant IP will be used instead.
249 If this is not the server name you
250 wish to use, a bogus entry (<code>ServerName
251 none.example.com</code>) can be added to get around this
257 <section id="ipbased"><title>More Efficient IP-Based Virtual Hosting</title>
259 <p>The configuration changes suggested to turn <a href="#simple">the first
260 example</a> into an IP-based virtual hosting setup result in
261 a rather inefficient setup. A new DNS lookup is required for every
262 request. To avoid this overhead, the filesystem can be arranged to
263 correspond to the IP addresses, instead of to the host names, thereby
264 negating the need for a DNS lookup. Logging will also have to be adjusted
265 to fit this system.</p>
268 # get the server name from the reverse DNS of the IP address<br />
269 UseCanonicalName DNS<br />
271 # include the IP address in the logs so they may be split<br />
272 LogFormat "%A %h %l %u %t \"%r\" %s %b" vcommon<br />
273 CustomLog logs/access_log vcommon<br />
275 # include the IP address in the filenames<br />
276 VirtualDocumentRootIP /www/hosts/%0/docs<br />
277 VirtualScriptAliasIP /www/hosts/%0/cgi-bin<br />
282 <section id="simple.rewrite"><title>Simple Dynamic
283 Virtual Hosts Using <module>mod_rewrite</module></title>
285 <p>This extract from <code>httpd.conf</code> does the same
286 thing as <a href="#simple">the first example</a>. The first
287 half is very similar to the corresponding part above, except for
288 some changes, required for backward compatibility and to make the
289 <code>mod_rewrite</code> part work properly; the second half
290 configures <code>mod_rewrite</code> to do the actual work.</p>
292 <p>There are a couple of especially tricky bits: by default,
293 <code>mod_rewrite</code> runs before other URI translation
294 modules (<code>mod_alias</code> etc.) - so if you wish to use these modules, <code>mod_rewrite</code> must be configured to accommodate
295 them. Also, some magic is required to do a
296 per-dynamic-virtual-host equivalent of
297 <code>ScriptAlias</code>.</p>
300 # get the server name from the Host: header<br />
301 UseCanonicalName Off<br />
303 # splittable logs<br />
304 LogFormat "%{Host}i %h %l %u %t \"%r\" %s %b" vcommon<br />
305 CustomLog logs/access_log vcommon<br />
307 <Directory /www/hosts><br />
309 # ExecCGI is needed here because we can't force<br />
310 # CGI execution in the way that ScriptAlias does<br />
311 Options FollowSymLinks ExecCGI<br />
313 </Directory><br />
315 # now for the hard bit<br />
317 RewriteEngine On<br />
319 # a ServerName derived from a Host: header may be any case at all<br />
320 RewriteMap lowercase int:tolower<br />
322 ## deal with normal documents first:<br />
323 # allow Alias /icons/ to work - repeat for other aliases<br />
324 RewriteCond %{REQUEST_URI} !^/icons/<br />
325 # allow CGIs to work<br />
326 RewriteCond %{REQUEST_URI} !^/cgi-bin/<br />
328 RewriteRule ^/(.*)$ /www/hosts/${lowercase:%{SERVER_NAME}}/docs/$1<br />
330 ## and now deal with CGIs - we have to force a handler<br />
331 RewriteCond %{REQUEST_URI} ^/cgi-bin/<br />
332 RewriteRule ^/(.*)$ /www/hosts/${lowercase:%{SERVER_NAME}}/cgi-bin/$1 [H=cgi-script]<br />
339 <section id="homepages.rewrite"><title>A
340 Homepages System Using <code>mod_rewrite</code></title>
342 <p>This does the same thing as <a href="#homepages">the second
346 RewriteEngine on<br />
348 RewriteMap lowercase int:tolower<br />
350 # allow CGIs to work<br />
351 RewriteCond %{REQUEST_URI} !^/cgi-bin/<br />
353 # check the hostname is right so that the RewriteRule works<br />
354 RewriteCond ${lowercase:%{SERVER_NAME}} ^www\.[a-z-]+\.isp\.com$<br />
356 # concatenate the virtual host name onto the start of the URI<br />
357 # the [C] means do the next rewrite on the result of this one<br />
358 RewriteRule ^(.+) ${lowercase:%{SERVER_NAME}}$1 [C]<br />
360 # now create the real file name<br />
361 RewriteRule ^www\.([a-z-]+)\.isp\.com/(.*) /home/$1/$2<br />
363 # define the global CGI directory<br />
364 ScriptAlias /cgi-bin/ /www/std-cgi/
369 <section id="xtra-conf"><title>Using a Separate Virtual
370 Host Configuration File</title>
372 <p>This arrangement uses more advanced <module>mod_rewrite</module>
373 features to work out the translation from virtual host to document
374 root, from a separate configuration file. This provides more
375 flexibility, but requires more complicated configuration.</p>
377 <p>The <code>vhost.map</code> file should look something like
381 www.customer-1.com /www/customers/1<br />
382 www.customer-2.com /www/customers/2<br />
384 www.customer-N.com /www/customers/N<br />
387 <p>The <code>httpd.conf</code> should contain the following:</p>
390 RewriteEngine on<br />
392 RewriteMap lowercase int:tolower<br />
394 # define the map file<br />
395 RewriteMap vhost txt:/www/conf/vhost.map<br />
397 # deal with aliases as above<br />
398 RewriteCond %{REQUEST_URI} !^/icons/<br />
399 RewriteCond %{REQUEST_URI} !^/cgi-bin/<br />
400 RewriteCond ${lowercase:%{SERVER_NAME}} ^(.+)$<br />
401 # this does the file-based remap<br />
402 RewriteCond ${vhost:%1} ^(/.*)$<br />
403 RewriteRule ^/(.*)$ %1/docs/$1<br />
405 RewriteCond %{REQUEST_URI} ^/cgi-bin/<br />
406 RewriteCond ${lowercase:%{SERVER_NAME}} ^(.+)$<br />
407 RewriteCond ${vhost:%1} ^(/.*)$<br />
408 RewriteRule ^/(.*)$ %1/cgi-bin/$1 [H=cgi-script]