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><VirtualHost></code> sections that are 74 substantially the same, for example:</p> 75<pre> 76NameVirtualHost 111.22.33.44 77<VirtualHost 111.22.33.44> 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</VirtualHost> 82<VirtualHost 111.22.33.44> 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</VirtualHost> 87# blah blah blah 88<VirtualHost 111.22.33.44> 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</VirtualHost> 93</pre> 94 <br /> 95 <br /> 96 97 98 <p>The basic idea is to replace all of the static 99 <code><VirtualHost></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><VirtualHost></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><VirtualHost></code> configuration sections.</p> 234<pre> 235UseCanonicalName Off 236 237LogFormat "%V %h %l %u %t \"%r\" %s %b" vcommon 238 239<Directory /www/commercial> 240 Options FollowSymLinks 241 AllowOverride All 242</Directory> 243 244<Directory /www/homepages> 245 Options FollowSymLinks 246 AllowOverride None 247</Directory> 248 249<VirtualHost 111.22.33.44> 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</VirtualHost> 257 258<VirtualHost 111.22.33.45> 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</VirtualHost> 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<Directory /www/hosts> 344 # ExecCGI is needed here because we can't force 345 # CGI execution in the way that ScriptAlias does 346 Options FollowSymLinks ExecCGI 347</Directory> 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