Return-Path: Delivered-To: apmail-httpd-docs-archive@httpd.apache.org Received: (qmail 92145 invoked by uid 500); 4 Oct 2002 05:37:23 -0000 Mailing-List: contact docs-help@httpd.apache.org; run by ezmlm Precedence: bulk list-help: list-unsubscribe: list-post: Reply-To: docs@httpd.apache.org Delivered-To: mailing list docs@httpd.apache.org Received: (qmail 92134 invoked from network); 4 Oct 2002 05:37:22 -0000 Message-ID: <38385.200.18.53.181.1033709851.squirrel@www.lsdr.net> Date: Fri, 4 Oct 2002 02:37:31 -0300 (BRT) Subject: [NEW] vhosts XML files From: "Luiz Rocha" To: X-Priority: 3 Importance: Normal X-MSMail-Priority: Normal Reply-To: lsdr@lsdr.net X-Mailer: SquirrelMail (version 1.2.4) MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_)tjiJ7xg_WS:hK+fNboP,lh)UU:Aj(s-'k6ryTdPex0?L0ZVKvZAxaF8xy)w" X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N ------=_)tjiJ7xg_WS:hK+fNboP,lh)UU:Aj(s-'k6ryTdPex0?L0ZVKvZAxaF8xy)w Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 8bit Hi guys, I finished the XML conversion of the vhosts/ directory files. Files are attached. I think I got it right, at least seems right to me, but I'll ask to someone to check those out before commiting. If it need some change, flame me. In time; I think the virtual hosts documentation need to be reviewed. Most of the text refer to version 1.3. -- Luiz Rocha lsdr.net ------=_)tjiJ7xg_WS:hK+fNboP,lh)UU:Aj(s-'k6ryTdPex0?L0ZVKvZAxaF8xy)w Content-Type: text/xml; name="details.xml" Content-Disposition: attachment; filename="details.xml" An In-Depth Discussion of Virtual Host Matching

The virtual host code was completely rewritten in Apache 1.3. This document attempts to explain exactly what Apache does when deciding what virtual host to serve a hit from. With the help of the new NameVirtualHost directive virtual host configuration should be a lot easier and safer than with versions prior to 1.3.

If you just want to make it work without understanding how, here are some examples.

Config File Parsing

There is a main_server which consists of all the definitions appearing outside of <VirtualHost> sections. There are virtual servers, called vhosts, which are defined by VirtualHost sections.

The directives Listen, ServerName, ServerPath, and ServerAlias can appear anywhere within the definition of a server. However, each appearance overrides the previous appearance (within that server).

The default value of the Listen field for main_server is 80. The main_server has no default ServerPath, or ServerAlias. The default ServerName is deduced from the servers IP address.

The main_server Listen directive has two functions. One function is to determine the default network port Apache will bind to. The second function is to specify the port number which is used in absolute URIs during redirects.

Unlike the main_server, vhost ports do not affect what ports Apache listens for connections on.

Each address appearing in the VirtualHost directive can have an optional port. If the port is unspecified it defaults to the value of the main_server's most recent Listen statement. The special port * indicates a wildcard that matches any port. Collectively the entire set of addresses (including multiple A record results from DNS lookups) are called the vhost's address set.

Unless a NameVirtualHost directive is used for a specific IP address the first vhost with that address is treated as an IP-based vhost. The IP address can also be the wildcard *.

If name-based vhosts should be used a NameVirtualHost directive must appear with the IP address set to be used for the name-based vhosts. In other words, you must specify the IP address that holds the hostname aliases (CNAMEs) for your name-based vhosts via a NameVirtualHost directive in your configuration file.

Multiple NameVirtualHost directives can be used each with a set of VirtualHost directives but only one NameVirtualHost directive should be used for each specific IP:port pair.

The ordering of NameVirtualHost and VirtualHost directives is not important which makes the following two examples identical (only the order of the VirtualHost directives for one address set is important, see below):

                                |
  NameVirtualHost 111.22.33.44  | <VirtualHost 111.22.33.44>
  <VirtualHost 111.22.33.44>    | # server A
  # server A                    | </VirtualHost>
  ...                           | <VirtualHost 111.22.33.55>
  </VirtualHost>                | # server C
  <VirtualHost 111.22.33.44>    | ...
  # server B                    | </VirtualHost>
  ...                           | <VirtualHost 111.22.33.44>
  </VirtualHost>                | # server B
                                | ...
  NameVirtualHost 111.22.33.55  | </VirtualHost>
  <VirtualHost 111.22.33.55>    | <VirtualHost 111.22.33.55>
  # server C                    | # server D
  ...                           | ...
  </VirtualHost>                | </VirtualHost>
  <VirtualHost 111.22.33.55>    |
  # server D                    | NameVirtualHost 111.22.33.44
  ...                           | NameVirtualHost 111.22.33.55
  </VirtualHost>                |
                                |

(To aid the readability of your configuration you should prefer the left variant.)

After parsing the VirtualHost directive, the vhost server is given a default Listen equal to the port assigned to the first name in its VirtualHost directive.

The complete list of names in the VirtualHost directive are treated just like a ServerAlias (but are not overridden by any ServerAlias statement) if all names resolve to the same address set. Note that subsequent Listen statements for this vhost will not affect the ports assigned in the address set.

During initialization a list for each IP address is generated and inserted into an hash table. If the IP address is used in a NameVirtualHost directive the list contains all name-based vhosts for the given IP address. If there are no vhosts defined for that address the NameVirtualHost directive is ignored and an error is logged. For an IP-based vhost the list in the hash table is empty.

Due to a fast hashing function the overhead of hashing an IP address during a request is minimal and almost not existent. Additionally the table is optimized for IP addresses which vary in the last octet.

For every vhost various default values are set. In particular:

  1. If a vhost has no ServerAdmin, ResourceConfig, AccessConfig, Timeout, KeepAliveTimeout, KeepAlive, MaxKeepAliveRequests, or SendBufferSize directive then the respective value is inherited from the main_server. (That is, inherited from whatever the final setting of that value is in the main_server.)
  2. The "lookup defaults" that define the default directory permissions for a vhost are merged with those of the main_server. This includes any per-directory configuration information for any module.
  3. The per-server configs for each module from the main_server are merged into the vhost server.

Essentially, the main_server is treated as "defaults" or a "base" on which to build each vhost. But the positioning of these main_server definitions in the config file is largely irrelevant -- the entire config of the main_server has been parsed when this final merging occurs. So even if a main_server definition appears after a vhost definition it might affect the vhost definition.

If the main_server has no ServerName at this point, then the hostname of the machine that httpd is running on is used instead. We will call the main_server address set those IP addresses returned by a DNS lookup on the ServerName of the main_server.

For any undefined ServerName fields, a name-based vhost defaults to the address given first in the VirtualHost statement defining the vhost.

Any vhost that includes the magic _default_ wildcard is given the same ServerName as the main_server.

Virtual Host Matching

The server determines which vhost to use for a request as follows:

Hash table lookup

When the connection is first made by a client, the IP address to which the client connected is looked up in the internal IP hash table.

If the lookup fails (the IP address wasn't found) the request is served from the _default_ vhost if there is such a vhost for the port to which the client sent the request. If there is no matching _default_ vhost the request is served from the main_server.

If the IP address is not found in the hash table then the match against the port number may also result in an entry corresponding to a NameVirtualHost *, which is subsequently handled like other name-based vhosts.

If the lookup succeeded (a corresponding list for the IP address was found) the next step is to decide if we have to deal with an IP-based or a name-base vhost.

IP-based vhost

If the entry we found has an empty name list then we have found an IP-based vhost, no further actions are performed and the request is served from that vhost.

Name-based vhost

If the entry corresponds to a name-based vhost the name list contains one or more vhost structures. This list contains the vhosts in the same order as the VirtualHost directives appear in the config file.

The first vhost on this list (the first vhost in the config file with the specified IP address) has the highest priority and catches any request to an unknown server name or a request without a Host: header field.

If the client provided a Host: header field the list is searched for a matching vhost and the first hit on a ServerName or ServerAlias is taken and the request is served from that vhost. A Host: header field can contain a port number, but Apache always matches against the real port to which the client sent the request.

If the client submitted a HTTP/1.0 request without Host: header field we don't know to what server the client tried to connect and any existing ServerPath is matched against the URI from the request. The first matching path on the list is used and the request is served from that vhost.

If no matching vhost could be found the request is served from the first vhost with a matching port number that is on the list for the IP to which the client connected (as already mentioned before).

Persistent connections

The IP lookup described above is only done once for a particular TCP/IP session while the name lookup is done on every request during a KeepAlive/persistent connection. In other words a client may request pages from different name-based vhosts during a single persistent connection.

Absolute URI

If the URI from the request is an absolute URI, and its hostname and port match the main server or one of the configured virtual hosts and match the address and port to which the client sent the request, then the scheme/hostname/port prefix is stripped off and the remaining relative URI is served by the corresponding main server or virtual host. If it does not match, then the URI remains untouched and the request is taken to be a proxy request.

Observations
  • A name-based vhost can never interfere with an IP-base vhost and vice versa. IP-based vhosts can only be reached through an IP address of its own address set and never through any other address. The same applies to name-based vhosts, they can only be reached through an IP address of the corresponding address set which must be defined with a NameVirtualHost directive.
  • ServerAlias and ServerPath checks are never performed for an IP-based vhost.
  • The order of name-/IP-based, the _default_ vhost and the NameVirtualHost directive within the config file is not important. Only the ordering of name-based vhosts for a specific address set is significant. The one name-based vhosts that comes first in the configuration file has the highest priority for its corresponding address set.
  • For security reasons the port number given in a Host: header field is never used during the matching process. Apache always uses the real port to which the client sent the request.
  • If a ServerPath directive exists which is a prefix of another ServerPath directive that appears later in the configuration file, then the former will always be matched and the latter will never be matched. (That is assuming that no Host: header field was available to disambiguate the two.)
  • If two IP-based vhosts have an address in common, the vhost appearing first in the config file is always matched. Such a thing might happen inadvertently. The server will give a warning in the error logfile when it detects this.
  • A _default_ vhost catches a request only if there is no other vhost with a matching IP address and a matching port number for the request. The request is only caught if the port number to which the client sent the request matches the port number of your _default_ vhost which is your standard Listen by default. A wildcard port can be specified (i.e., _default_:*) to catch requests to any available port. This also applies to NameVirtualHost * vhosts.
  • The main_server is only used to serve a request if the IP address and port number to which the client connected is unspecified and does not match any other vhost (including a _default_ vhost). In other words the main_server only catches a request for an unspecified address/port combination (unless there is a _default_ vhost which matches that port).
  • A _default_ vhost or the main_server is never matched for a request with an unknown or missing Host: header field if the client connected to an address (and port) which is used for name-based vhosts, e.g., in a NameVirtualHost directive.
  • You should never specify DNS names in VirtualHost directives because it will force your server to rely on DNS to boot. Furthermore it poses a security threat if you do not control the DNS for all the domains listed. There's more information available on this and the next two topics.
  • ServerName should always be set for each vhost. Otherwise A DNS lookup is required for each vhost.
Tips

In addition to the tips on the DNS Issues page, here are some further tips:

  • Place all main_server definitions before any VirtualHost definitions. (This is to aid the readability of the configuration -- the post-config merging process makes it non-obvious that definitions mixed in around virtual hosts might affect all virtual hosts.)
  • Group corresponding NameVirtualHost and VirtualHost definitions in your configuration to ensure better readability.
  • Avoid ServerPaths which are prefixes of other ServerPaths. If you cannot avoid this then you have to ensure that the longer (more specific) prefix vhost appears earlier in the configuration file than the shorter (less specific) prefix (i.e., "ServerPath /abc" should appear after "ServerPath /abc/def").
------=_)tjiJ7xg_WS:hK+fNboP,lh)UU:Aj(s-'k6ryTdPex0?L0ZVKvZAxaF8xy)w Content-Type: text/xml; name="examples.xml" Content-Disposition: attachment; filename="examples.xml" VirtualHost Examples

This document attempts to answer the commonly-asked questions about setting up virtual hosts. These scenarios are those involving multiple web sites running on a single server, via name-based or IP-based virtual hosts. A document should be coming soon about running sites on several servers behind a single proxy server.

Virtual Host examples for common setups
Additional Features
Examples
Running several name-based web sites on a single IP address.

Setup:

Your server has a single IP address, and multiple aliases (CNAMES) point to this machine in DNS. You want to run a web server for www.example1.com and www.example2.org on this machine.

Note: Creating virtual host configurations on your Apache server does not magically cause DNS entries to be created for those host names. You must have the names in DNS, resolving to your IP address, or nobody else will be able to see your web site. You can put entries in your hosts file for local testing, but that will work only from the machine with those hosts entries.

Server configuration:

   # Ensure that Apache listens on port 80
   Listen 80

   # Listen for virtual host requests on all IP addresses
   NameVirtualHost *
		
   <VirtualHost *>
       DocumentRoot /www/example1
       ServerName www.example1.com

       # Other directives here
		
   </VirtualHost>
    		
   <VirtualHost *>
       DocumentRoot /www/example2
       ServerName www.example2.org
    		
       # Other directives here
		
   </VirtualHost> 

The asterisks match all addresses, so the main server serves no requests. Due to the fact that www.example1.com is first in the configuration file, it has the highest priority and can be seen as the default or primary server. That means that if a request is received that does not match one of the specified ServerName directives, it will be served by this first VirtualHost.

Note:

You can, if you wish, replace * with the actual IP address of the system. In that case, the argument to VirtualHost must match the argument to NameVirtualHost:

    NameVirtualHost 172.20.30.40

    <VirtualHost 172.20.30.40>
        # etc ...

However, it is additionally useful to use * on systems where the IP address is not predictable - for example if you have a dynamic IP address with your ISP, and you are using some variety of dynamic DNS solution. Since * matches any IP address, this configuration would work without changes whenever your IP address changes.

The above configuration is what you will want to use in almost all name-based virtual hosting situations. The only think that this configuration will not work for, in fact, is when you are serving different content based on differing IP addresses or ports.


Name-based hosts on more than one IP address. Note: Any of the techniques discussed here can be extended to any number of IP addresses. Setup 1:

The server has two IP addresses. On one (172.20.30.40), we will serve the "main" server, server.domain.com and on the other (172.20.30.50), we will serve two or more virtual hosts.

Server configuration:

    Listen 80

    # This is the "main" server running on 172.20.30.40
    ServerName server.domain.com
    DocumentRoot /www/mainserver

    # This is the other address
    NameVirtualHost 172.20.30.50

    <VirtualHost 172.20.30.50>
        DocumentRoot /www/example1
        ServerName www.example1.com
    
        # Other directives here ...

    </VirtualHost>
    
    <VirtualHost 172.20.30.50>
        DocumentRoot /www/example2
        ServerName www.example2.org
    
        # Other directives here ...

    </VirtualHost> 

Any request to an address other than 172.20.30.50 will be served from the main server. A request to 172.20.30.50 with an unknown hostname, or no Host: header, will be served from www.example1.com.

Serving the same content on different IP addresses (such as an internal and external address).

Setup:

The server machine has two IP addresses (192.168.1.1 and 172.20.30.40). The machine is sitting between an internal (intranet) network and an external (internet) network. Outside of the network, the name server.example.com resolves to the external address (172.20.30.40), but inside the network, that same name resolves to the internal address (192.168.1.1).

The server can be made to respond to internal and external requests with the same content, with just one VirtualHost section.

Server configuration:

    NameVirtualHost 192.168.1.1
    NameVirtualHost 172.20.30.40

    <VirtualHost 192.168.1.1 172.20.30.40>
        DocumentRoot /www/server1
        ServerName server.example.com
        ServerAlias server
    </VirtualHost>

Now requests from both networks will be served from the same VirtualHost.

Note: On the internal network, one can just use the name server rather than the fully qualified host name server.example.com.

Note also that, in the above example, you can replace the list of IP addresses with *, which will cause the server to respond the same on all addresses.


Running different sites on different ports.

Setup:

You have multiple domains going to the same IP and also want to serve multiple ports. By defining the ports in the "NameVirtualHost" tag, you can allow this to work. If you try using <VirtualHost name:port> without the NameVirtualHost name:port or you try to use the Listen directive, your configuration will not work.

Server configuration:

    Listen 80
    Listen 8080

    NameVirtualHost 172.20.30.40:80
    NameVirtualHost 172.20.30.40:8080

    <VirtualHost 172.20.30.40:80>
        ServerName www.example1.com
        DocumentRoot /www/domain-80
    </VirtualHost>

    <VirtualHost 172.20.30.40:8080>
        ServerName www.example1.com
        DocumentRoot /www/domain-8080
    </VirtualHost>

    <VirtualHost 172.20.30.40:80>
        ServerName www.example2.org
        DocumentRoot /www/otherdomain-80
    </VirtualHost>

    <VirtualHost 172.20.30.40:8080>
        ServerName www.example2.org
        DocumentRoot /www/otherdomain-8080
    </VirtualHost>

IP-based virtual hosting

Setup:

The server has two IP addresses (172.20.30.40 and 172.20.30.50) which resolve to the names www.example1.com and www.example2.org respectively.

Server configuration:

    Listen 80

    <VirtualHost 172.20.30.40>
        DocumentRoot /www/example1
        ServerName www.example1.com
    </VirtualHost>
   
    <VirtualHost 172.20.30.50>
        DocumentRoot /www/example2
        ServerName www.example2.org
    </VirtualHost>

Requests for any address not specified in one of the <VirtualHost> directives (such as localhost, for example) will go to the main server, if there is one.


Mixed port-based and ip-based virtual hosts

Setup:

The server machine has two IP addresses (172.20.30.40 and 172.20.30.50) which resolve to the names www.example1.com and www.example2.org respectively. In each case, we want to run hosts on ports 80 and 8080.

    Listen 172.20.30.40:80
    Listen 172.20.30.40:8080
    Listen 172.20.30.50:80
    Listen 172.20.30.50:8080
    
    <VirtualHost 172.20.30.40:80>
        DocumentRoot /www/example1-80
        ServerName www.example1.com
    </VirtualHost>

    <VirtualHost 172.20.30.40:8080>
        DocumentRoot /www/example1-8080
        ServerName www.example1.com
    </VirtualHost>
    
    <VirtualHost 172.20.30.50:80>
        DocumentRoot /www/example2-80
        ServerName www.example1.org
    </VirtualHost>

    <VirtualHost 172.20.30.50:8080>
        DocumentRoot /www/example2-8080
        ServerName www.example2.org
    </VirtualHost>

Mixed name-based and IP-based vhosts

Setup:

On some of my addresses, I want to do name-based virtual hosts, and on others, IP-based hosts.

Server configuration:

    Listen 80

    NameVirtualHost 172.20.30.40

    <VirtualHost 172.20.30.40>
        DocumentRoot /www/example1
        ServerName www.example1.com
    </VirtualHost>
   
    <VirtualHost 172.20.30.40>
        DocumentRoot /www/example2
        ServerName www.example2.org
    </VirtualHost> 
    
    <VirtualHost 172.20.30.40>
        DocumentRoot /www/example3
        ServerName www.example3.net
    </VirtualHost> 

    # IP-based
    <VirtualHost 172.20.30.50>
        DocumentRoot /www/example4
        ServerName www.example4.edu
    </VirtualHost> 
    
    <VirtualHost 172.20.30.60>
        DocumentRoot /www/example5
        ServerName www.example5.gov
    </VirtualHost>     

Using <code>_default_</code> vhosts

Setup 1:

Catching every request to any unspecified IP address and port, i.e., an address/port combination that is not used for any other virtual host.

Server configuration:

    <VirtualHost _default_:*>
        DocumentRoot /www/default
    </VirtualHost>

Using such a default vhost with a wildcard port effectively prevents any request going to the main server.

A default vhost never serves a request that was sent to an address/port that is used for name-based vhosts. If the request contained an unknown or no Host: header it is always served from the primary name-based vhost (the vhost for that address/port appearing first in the configuration file).

You can use AliasMatch or RewriteRule to rewrite any request to a single information page (or script).

Setup 2:

Same as setup 1, but the server listens on several ports and we want to use a second _default_ vhost for port 80.

Server configuration:

    <VirtualHost _default_:80>
        DocumentRoot /www/default80
        # ...
    </VirtualHost>
    
    <VirtualHost _default_:*>
        DocumentRoot /www/default
        # ...
    </VirtualHost>    

The default vhost for port 80 (which must appear before any default vhost with a wildcard port) catches all requests that were sent to an unspecified IP address. The main server is never used to serve a request.

Setup 3:

We want to have a default vhost for port 80, but no other default vhosts.

Server configuration:

    <VirtualHost _default_:80>
    DocumentRoot /www/default
    ...
    </VirtualHost>

A request to an unspecified address on port 80 is served from the default vhost any other request to an unspecified address and port is served from the main server.


Migrating a name-based vhost to an IP-based vhost

Setup:

The name-based vhost with the hostname www.example2.org (from our name-based example, setup 2) should get its own IP address. To avoid problems with name servers or proxies who cached the old IP address for the name-based vhost we want to provide both variants during a migration phase.
The solution is easy, because we can simply add the new IP address (172.20.30.50) to the VirtualHost directive.

Server configuration:

    Listen 80
    ServerName www.example1.com
    DocumentRoot /www/example1

    NameVirtualHost 172.20.30.40

    <VirtualHost 172.20.30.40 172.20.30.50>
        DocumentRoot /www/example2
        ServerName www.example2.org
        # ...
    </VirtualHost>
   
    <VirtualHost 172.20.30.40>
        DocumentRoot /www/example3
        ServerName www.example3.net
        ServerAlias *.example3.net
        # ...
    </VirtualHost>

The vhost can now be accessed through the new address (as an IP-based vhost) and through the old address (as a name-based vhost).


Using the <code>ServerPath</code> directive

Setup:

We have a server with two name-based vhosts. In order to match the correct virtual host a client must send the correct Host: header. Old HTTP/1.0 clients do not send such a header and Apache has no clue what vhost the client tried to reach (and serves the request from the primary vhost). To provide as much backward compatibility as possible we create a primary vhost which returns a single page containing links with an URL prefix to the name-based virtual hosts.

Server configuration:

    NameVirtualHost 172.20.30.40

    <VirtualHost 172.20.30.40>
        # primary vhost
        DocumentRoot /www/subdomain
        RewriteEngine On
        RewriteRule ^/.* /www/subdomain/index.html
        # ...
    </VirtualHost>

    <VirtualHost 172.20.30.40>
    DocumentRoot /www/subdomain/sub1
        ServerName www.sub1.domain.tld
        ServerPath /sub1/
        RewriteEngine On
        RewriteRule ^(/sub1/.*) /www/subdomain$1 
        # ...
    </VirtualHost>

    <VirtualHost 172.20.30.40>
        DocumentRoot /www/subdomain/sub2
        ServerName www.sub2.domain.tld
        ServerPath /sub2/
        RewriteEngine On
        RewriteRule ^(/sub2/.*) /www/subdomain$1 
        # ...
    </VirtualHost>

Due to the ServerPath directive a request to the URL http://www.sub1.domain.tld/sub1/ is always served from the sub1-vhost.
A request to the URL http://www.sub1.domain.tld/ is only served from the sub1-vhost if the client sent a correct Host: header. If no Host: header is sent the client gets the information page from the primary host.
Please note that there is one oddity: A request to http://www.sub2.domain.tld/sub1/ is also served from the sub1-vhost if the client sent no Host: header.
The RewriteRule directives are used to make sure that a client which sent a correct Host: header can use both URL variants, i.e., with or without URL prefix.

------=_)tjiJ7xg_WS:hK+fNboP,lh)UU:Aj(s-'k6ryTdPex0?L0ZVKvZAxaF8xy)w Content-Type: text/xml; name="fd-limits.xml" Content-Disposition: attachment; filename="fd-limits.xml" File Descriptor Limits

When using a large number of Virtual Hosts, Apache may run out of available file descriptors (sometimes called file handles) if each Virtual Host specifies different log files. The total number of file descriptors used by Apache is one for each distinct error log file, one for every other log file directive, plus 10-20 for internal use. Unix operating systems limit the number of file descriptors that may be used by a process; the limit is typically 64, and may usually be increased up to a large hard-limit.

Although Apache attempts to increase the limit as required, this may not work if:

  1. Your system does not provide the setrlimit() system call.
  2. The setrlimit(RLIMIT_NOFILE) call does not function on your system (such as Solaris 2.3)
  3. The number of file descriptors required exceeds the hard limit.
  4. Your system imposes other limits on file descriptors, such as a limit on stdio streams only using file descriptors below 256. (Solaris 2)
In the event of problems you can:
  • Reduce the number of log files; don't specify log files in the <VirtualHost> sections, but only log to the main log files. (See Splitting up your log files, below, for more information on doing this.)
  • If you system falls into 1 or 2 (above), then increase the file descriptor limit before starting Apache, using a script like #!/bin/sh
    ulimit -S -n 100
    exec httpd

Please see the Descriptors and Apache document containing further details about file descriptor problems and how they can be solved on your operating system.

Splitting up your log files

If you want to log multiple virtual hosts to the same log file, you may want to split up the log files afterwards in order to run statistical analysis of the various virtual hosts. This can be accomplished in the following manner.

First, you will need to add the virtual host information to the log entries. This can be done using the LogFormat directive, and the %v variable. Add this to the beginning of your log format string:

 LogFormat "%v %h %l %u %t \"%r\" %>s %b" vhost
 CustomLog logs/multiple_vhost_log vhost

This will create a log file in the common log format, but with the canonical virtual host (whatever appears in the ServerName directive) prepended to each line. (See Custom Log Formats for more about customizing your log files.)

When you wish to split your log file into its component parts (one file per virtual host) you can use the program split-logfile to accomplish this. You'll find this program in the support directory of the Apache disribution.

Run this program with the command:

split-logfile < /logs/multiple_vhost_log

This program, when run with the name of your vhost log file, will generate one file for each virtual host that appears in your log file. Each file will be called hostname.log.

------=_)tjiJ7xg_WS:hK+fNboP,lh)UU:Aj(s-'k6ryTdPex0?L0ZVKvZAxaF8xy)w Content-Type: text/xml; name="index.xml" Content-Disposition: attachment; filename="index.xml" Apache Virtual Host documentation

The term Virtual Host refers to the practice of running more than one web site (such as www.company1.com and www.company2.com) on a single machine. Virtual hosts can be "IP-based," meaning that you have a different IP address for every web site, or "name-based," meaning that you have multiple names running on a single IP address. The fact that they are running on the same server is not apparent to the end user.

Apache was one of the first servers to support IP-based virtual hosts right out of the box. Versions 1.1 and later of Apache support both IP-based and name-based virtual hosts (vhosts). The latter variant of virtual hosts is sometimes also called host-based or non-IP virtual hosts.

Below is a list of documentation pages which explain all details of virtual host support in Apache version 1.3 and later.

mod_vhost_alias
Virtual Host Support
Configuration directives
  • VirtualHost
  • NameVirtualHost
  • ServerName
  • ServerAlias
  • ServerPath

If you are trying to debug your virtual host configuration, you may find the Apache -t -D DUMP_VHOSTS command line switch useful. That is, type the following command:

/usr/local/apache/bin/httpd -t -D DUMP_VHOSTS

This command will dump out a description of how Apache parsed the configuration file. Careful examination of the IP addresses and server names may help uncover configuration mistakes. (See the docs for the httpd program for other command line options)

------=_)tjiJ7xg_WS:hK+fNboP,lh)UU:Aj(s-'k6ryTdPex0?L0ZVKvZAxaF8xy)w Content-Type: text/xml; name="ip-based.xml" Content-Disposition: attachment; filename="ip-based.xml" Apache IP-based Virtual Host Support Name-based Virtual Hosts Support
System requirements

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 which are supported by most modern operating systems (see system documentation for details, these are frequently called "ip aliases", and the "ifconfig" command is most commonly used to set them up).

How to set up Apache

There are two ways of configuring apache to support multiple hosts. Either by running a separate httpd daemon for each hostname, or by running a single daemon which supports all the virtual hosts.

Use multiple daemons when:

  • There are security partitioning issues, such as company1 does not want anyone at company2 to be able to read their data except via the web. In this case you would need two daemons, each running with different User, Group, Listen, and ServerRoot settings.
  • You can afford the memory and file descriptor requirements of listening to every IP alias on the machine. It's only possible to Listen to the "wildcard" address, or to specific addresses. So if you have a need to listen to a specific address for whatever reason, then you will need to listen to all specific addresses. (Although one httpd could listen to N-1 of the addresses, and another could listen to the remaining address.)

Use a single daemon when:

  • Sharing of the httpd configuration between virtual hosts is acceptable.
  • The machine services a large number of requests, and so the performance loss in running separate daemons may be significant.
Setting up multiple daemons

Create a separate httpd installation for each virtual host. For each installation, use the Listen directive in the configuration file to select which IP address (or virtual host) that daemon services. e.g.

    Listen www.smallco.com:80

It is recommended that you use an IP address instead of a hostname (see DNS caveats).

Setting up a single daemon with virtual hosts

For this case, a single httpd will service requests for the main server and all the virtual hosts. The VirtualHost directive in the configuration file is used to set the values of ServerAdmin, ServerName, DocumentRoot, ErrorLog and TransferLog or CustomLog configuration directives to different values for each virtual host. e.g.

    <VirtualHost www.smallco.com>
    ServerAdmin webmaster@mail.smallco.com
    DocumentRoot /groups/smallco/www
    ServerName www.smallco.com
    ErrorLog /groups/smallco/logs/error_log
    TransferLog /groups/smallco/logs/access_log
    </VirtualHost>

    <VirtualHost www.baygroup.org>
    ServerAdmin webmaster@mail.baygroup.org
    DocumentRoot /groups/baygroup/www
    ServerName www.baygroup.org
    ErrorLog /groups/baygroup/logs/error_log
    TransferLog /groups/baygroup/logs/access_log
    </VirtualHost>

It is recommended that you use an IP address instead of a hostname (see DNS caveats).

Almost any configuration directive can be put in the VirtualHost directive, with the exception of directives that control process creation and a few other directives. To find out if a directive can be used in the VirtualHost directive, check the Context using the directive index.

User and Group may be used inside a VirtualHost directive if the suEXEC wrapper is used.

SECURITY: When specifying where to write log files, be aware of some security risks which are present if anyone other than the user that starts Apache has write access to the directory where they are written. See the security tips document for details.

------=_)tjiJ7xg_WS:hK+fNboP,lh)UU:Aj(s-'k6ryTdPex0?L0ZVKvZAxaF8xy)w Content-Type: text/xml; name="mass.xml" Content-Disposition: attachment; filename="mass.xml" Dynamically configured mass virtual hosting

This document describes how to efficiently serve an arbitrary number of virtual hosts with Apache 1.3.

Motivation

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

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>

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 Apache 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 don't need to reconfigure or restart 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, etc.).

Overview

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, but if you are using a version of Apache up to 1.3.6 then you must use mod_rewrite. 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.

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 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 Apache 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). 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 mod_vhost_alias or mod_rewrite) which has a different way of doing the mapping. Neither of these modules is responsible for setting the DOCUMENT_ROOT environment variable so if any CGIs or SSI documents make use of it they will get a misleading value.

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/

There are examples of more complicated VirtualDocumentRoot settings in the mod_vhost_alias documentation.

Using more than one virtual hosting system on the same server

With more complicated setups you can use Apache'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 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>
More efficient IP-based virtual hosting

After the first example 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.

# 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
Using older versions of Apache

The examples above rely on mod_vhost_alias which appeared after version 1.3.6. If you are using a version of Apache without mod_vhost_alias then you can implement this technique with mod_rewrite as illustrated below, but only for Host:-header-based virtual hosts.

In addition there are some things to beware of with logging. Apache 1.3.6 is the first version to include the %V log format directive; in versions 1.3.0 - 1.3.3 the %v option did what %V does; version 1.3.4 has no equivalent. In all these versions of Apache the UseCanonicalName directive can appear in .htaccess files which means that customers can cause the wrong thing to be logged. Therefore the best thing to do is use the %{Host}i directive which logs the Host: header directly; note that this may include :port on the end which is not the case for %V.

Simple dynamic virtual hosts using <code>mod_rewrite</code>

This extract from httpd.conf does the same thing as the first example. The first half is very similar to the corresponding part above but with some changes for backward compatibility and to make the mod_rewrite part work properly; the second half configures mod_rewrite to do the actual work.

There are a couple of especially tricky bits: By default, mod_rewrite runs before the other URI translation modules (mod_alias etc.) so if they are used then mod_rewrite must be configured to accommodate them. Also, mome magic must be performed to do a per-dynamic-virtual-host equivalent of ScriptAlias.

# 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!
A homepages system using <code>mod_rewrite</code>

This does the same thing as the second example.

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/
Using a separate virtual host configuration file

This arrangement uses more advanced mod_rewrite 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.

The vhost.map file contains something like this:

www.customer-1.com  /www/customers/1
www.customer-2.com  /www/customers/2
# ...
www.customer-N.com  /www/customers/N

The http.conf contains this:

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
------=_)tjiJ7xg_WS:hK+fNboP,lh)UU:Aj(s-'k6ryTdPex0?L0ZVKvZAxaF8xy)w Content-Type: text/xml; name="name-based.xml" Content-Disposition: attachment; filename="name-based.xml" Name-based Virtual Host Support

This document describes when and how to use name-based virtual hosts.

IP-based Virtual Host Support An In-Depth Discussion of Virtual Host Matching Dynamically configured mass virtual hosting Virtual Host examples for common setups ServerPath configuration example
Name-based vs. IP-based Virtual Hosts

IP-based virtual hosts use the IP address of the connection to determine the correct virtual host to serve. Therefore you need to have a separate IP address for each host. With name-based virtual hosting, the server relies on the client to report the hostname as part of the HTTP headers. Using this technique, many different hosts can share the same IP address.

Name-based virtual hosting is usually simpler, since you need only configure your DNS server to map each hostname to the correct IP address and then configure the Apache HTTP Server to recognize the different hostnames. Name-based virtual hosting also eases the demand for scarce IP addresses. Therefore you should use name-based virtual hosting unless there is a specific reason to choose IP-based virtual hosting. Some reasons why you might consider using IP-based virtual hosting:

  • Some ancient clients are not compatible with name-based virtual hosting. For name-based virtual hosting to work, the client must send the HTTP Host header. This is required by HTTP/1.1, and is implemented by all modern HTTP/1.0 browsers as an extension. If you need to support obsolete clients and still use name-based virtual hosting, a possible technique is discussed at the end of this document.
  • Name-based virtual hosting cannot be used with SSL secure servers because of the nature of the SSL protocol.
  • Some operating systems and network equipment implement bandwidth management techniques that cannot differentiate between hosts unless they are on separate IP addresses.
Using Name-based Virtual Hosts core DocumentRoot NameVirtualHost ServerAlias ServerName ServerPath VirtualHost

To use name-based virtual hosting, you must designate the IP address (and possibly port) on the server that will be accepting requests for the hosts. This is configured using the NameVirtualHost directive. In the normal case where any and all IP addresses on the server should be used, you can use * as the argument to NameVirtualHost. Note that mentioning an IP address in a NameVirtualHost directive does not automatically make the server listen to that IP address. See Setting which addresses and ports Apache uses for more details. In addition, any IP address specified here must be associated with a network interface on the server.

The next step is to create a VirtualHost block for each different host that you would like to serve. The argument to the <VirtualHost> directive should be the same as the argument to the NameVirtualHost directive (ie, an IP address, or * for all addresses). Inside each <VirtualHost> block, you will need at minimum a / ServerName directive to designate which host is served and a DocumentRoot directive to show where in the filesystem the content for that host lives.

If you are adding virtual hosts to an existing web server, you must also create a <VirtualHost> block for the existing host. The ServerName and DocumentRoot included in this virtual host should be the same as the global ServerName and DocumentRoot. List this virtual host first in the configuration file so that it will act as the default host.

For example, suppose that you are serving the domain www.domain.tld and you wish to add the virtual host www.otherdomain.tld, which points at the same IP address. Then you simply add the following to httpd.conf:

    NameVirtualHost *

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

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

You can alternatively specify an explicit IP address in place of the * in both the NameVirtualHost and <VirtualHost> directives.

Many servers want to be accessible by more than one name. This is possible with the ServerAlias directive, placed inside the <VirtualHost> section. For example if you add this to the first <VirtualHost> block above

ServerAlias domain.tld *.domain.tld

then requests for all hosts in the domain.tld domain will be served by the www.domain.tld virtual host. The wildcard characters * and ? can be used to match names. Of course, you can't just make up names and place them in ServerName or ServerAlias. You must first have your DNS server properly configured to map those names to an IP address associated with your server.

Finally, you can fine-tune the configuration of the virtual hosts by placing other directives inside the <VirtualHost> containers. Most directives can be placed in these containers and will then change the configuration only of the relevant virtual host. To find out if a particular directive is allowed, check the Context of the directive. Configuration directives set in the main server context (outside any <VirtualHost> container) will be used only if they are not overriden by the virtual host settings.

Now when a request arrives, the server will first check if it is using an IP address that matches the NameVirtualHost. If it is, then it will look at each <VirtualHost> section with a matching IP address and try to find one where the ServerName or ServerAlias matches the requested hostname. If it finds one, then it uses the configuration for that server. If no matching virtual host is found, then the first listed virtual host that matches the IP address will be used.

As a consequence, the first listed virtual host is the default virtual host. The DocumentRoot from the main server will never be used when an IP address matches the NameVirtualHost directive. If you would like to have a special configuration for requests that do not match any particular virtual host, simply put that configuration in a <VirtualHost> container and list it first in the configuration file.

Compatibility with Older Browsers

As mentioned earlier, there are some clients who do not send the required data for the name-based virtual hosts to work properly. These clients will always be sent the pages from the first virtual host listed for that IP address (the primary name-based virtual host).

There is a possible workaround with the ServerPath directive, albeit a slightly cumbersome one:

Example configuration:

    NameVirtualHost 111.22.33.44

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

What does this mean? It means that a request for any URI beginning with "/domain" will be served from the virtual host www.domain.tld This means that the pages can be accessed as http://www.domain.tld/domain/ for all clients, although clients sending a Host: header can also access it as http://www.domain.tld/.

In order to make this work, put a link on your primary virtual host's page to http://www.domain.tld/domain/ Then, in the virtual host's pages, be sure to use either purely relative links (e.g., "file.html" or "../icons/image.gif" or links containing the prefacing /domain/ (e.g., "http://www.domain.tld/domain/misc/file.html" or "/domain/misc/file.html").

This requires a bit of discipline, but adherence to these guidelines will, for the most part, ensure that your pages will work with all browsers, new and old.

------=_)tjiJ7xg_WS:hK+fNboP,lh)UU:Aj(s-'k6ryTdPex0?L0ZVKvZAxaF8xy)w Content-Type: text/plain; charset=us-ascii --------------------------------------------------------------------- To unsubscribe, e-mail: docs-unsubscribe@httpd.apache.org For additional commands, e-mail: docs-help@httpd.apache.org ------=_)tjiJ7xg_WS:hK+fNboP,lh)UU:Aj(s-'k6ryTdPex0?L0ZVKvZAxaF8xy)w--