Chapter 6
Text-Based Configuration
The server configuration file is ServerRoot/conf/httpd.conf, a simple text file that Stronghold reads each time it starts. This chapter introduces you to this file and shows you how to
Once you understand the configuration concepts discussed here, you can use Chapter 7 to find the specific directives you need to customize httpd.conf for your site.
Each time you edit the configuration file, you must restart the server in order to apply your changes. "Starting and Stopping Stronghold" on page 1-1 shows you how to restart the server.
|
NOTE:
|
Stronghold's indexing and searching features require separate configuration, and Chapter 12 discusses this.
|
Using Directives
Directives are configuration commands. Each directive controls a different aspect of Stronghold's behavior, including how it treats the objects on your site. Different directives take different kinds of values as arguments, such as
Since many of the objects on your server require special treatment, each object can have its own configuration within httpd.conf. An object's configuration describes deviations from the global configuration. This granularity gives Stronghold (and its Apache cousin) its enormous flexibility. Infinitely many different configurations are possible.
Figure 6-1: Configuration Granularity
Containers
Directives can be applied in different contexts. A directive's context is the scope of its application. The configuration file uses containers to delineate directives whose context is a particular virtual host, a URI, an HTTP access method, a directory, or a file. Containers resemble HTML tags. For example:
<Directory /logos/jpegs>
. . .
</Directory>
This example shows an opening container tag, which specifies an object on your server, followed by a closing container tag that begins with a slash (/). The directives that apply only to the /logos/jpegs directory go between the opening and closing container tags.
When entering configuration directives, use the following guidelines:
These are the available containers:
- <VirtualHost IP:port>
Specifies a virtual host to which the directives following the opening container tag apply. IP is an IP number. Always close a virtual host container with </VirtualHost>. For more detailed information about using this container, see "Configuring Virtual Hosts" on page 6-9.
- <Directory directory>
Specifies a directory on your server, and also applies to its subdirectories unless a subdirectory has its own <Directory> section. Directory is either the full path to a directory or a wildcard string. Always close a directory container with </Directory>.
This container is also used to configure proxy service, as described in "Configuring the Proxy Server" on page 4-3.
- <DirectoryMatch regex>
Same as the <Directory> container, except that it takes a regular expression instead of a literal directory name. For example,
<DirectoryMatch "^/www/.*/[0-9]{3}">
matches directories in /www/ that consist of three numbers.
- <Location URI>
Specifies a URI that does not necessarily map to a directory on your server. URI should, except for proxy requests, be of the form /path/, and should not include the http://hostname portion. It doesn't necessarily have to protect a directory (it can be an individual file, or a number of files), and can include wildcards. Always close a location container with </Location>.
- <LocationMatch regex>
Same as the <Location> container, except that it takes a regular expression instead for the URI. For example,
<LocationMatch "/(extra|special)/data">
matches URIs that contained the substring "/extra/data" or "/special/data."
- <Limit method>
Specifies an HTTP access method, such as GET, PUT, or POST, as the condition under which the enclosed directives apply. Always close a limit directive container with </Limit>.
- <Files filename>
Specifies a filename or the end of a filename and can take wildcards. The directives it contains apply to the named file or to any file ending in the filename. You can a filename or construct an expression that matches any number of files. Always close a file directive container with </Files>.
|
NOTE:
|
Wildcards in <Files> containers do not match slash (/).
|
- <FilesMatch regex>
Same as the <Files> container, except that it takes a regular expression instead of a filename. For example,
<FilesMatch "\.(gif|jpe?g|png)$">
matches most common Internet graphics formats.
- <IfModule module>
Specifies a module which may be active or inactive, depending on whether it is specified by the AddModule directive. The directives in this container apply only if the module is active. If the value is !module, the directives apply only if the module is inactive. Always close this container with </IfModule>.
Dynamic module linking is discussed in greater detail in "Dynamic Module Linking" on page 8-8.
- <IfDefine parameter>
This container encloses directives that apply if the specified parameter was defined at the command line (or in the start-server script) on startup. The parameter is defined using the -D command-line flag and is entirely arbitrary. For example, several different servers can run with different parameters that each enable a different section of the same configuration file. This is equivalent to running several different servers with several different configuration files. Always close this container with </IfDefine>.
Each of these can be nested inside the others, with the following exceptions:
- <VirtualHost> should not be nested inside another container.
- No container should be nested inside a <File> container except <Limit> because files are the smallest server objects.
- No container should be nested inside a <Limit> container. <Limit> is the container with the narrowest scope.
- <Directory> and <Location> containers should not be nested inside each other.
Directives that appear outside all containers apply globally and are read by the server first. Directives inside containers are processed in the following order:
- <Directory> containers without regular expressions and .htaccess files
The .htaccess files override <Directory> containers. Multiple <Directory> containers without regular expressions are processed from the shortest directory path to the longest. For example, <Directory /animals> is processed before <Directory /animals/hyrax>, even if it appears later in the configuration file.
- <DirectoryMatch> and <Directory> containers with regular expressions
- <Files> and <FilesMatch> containers
- <Location> and <LocationMatch> containers
- <VirtualHost> containers and the containers nested inside them
The processing order above applies to containers inside <VirtualHost> containers.
This processing order allows more specific containers to override the directives inside more general containers. Except for <Directory> containers without regular expressions, containers of each type are processed in the order in which they appear. Configuration elements inserted with the Include directive are treated as if they are located at the point of inclusion.
Wildcards
Wildcards are a simple method of denoting variable values. Containers can take wildcards in place of ordinary hostnames, paths, and so on. Some directives can also take wildcards as values.
There are two wildcards:
For example, imagine that you are running Stronghold Web Server as an internal server on your organization's local area network (LAN). Each host on the LAN has a hostname that ends with your organization's basic domain name, such as c2.net. You can use the asterisk wildcard to restrict access so that your server only responds to hosts on your LAN:
AddAlt "JPEG banner" banner*.jpeg
In this example, any filename that begins with "banner" and has the .jpeg filename extension is given the "JPEG banner" description in directory index listings. Any number of filenames could qualify, such as banner1.jpeg, banner_advertisement.jpeg, and so on.
Regular Expressions
Regular expressions are patterns that describe a set of strings. They consist of any number of ordinary characters and metacharacters. When combined as a regular expression, these can match zero or more real strings that you want to pick out. Stronghold supports POSIX Extended Regular Expressions (EREs).
Some directives can take regular expressions as values. Containers can also take regular expressions as long as the beginning of the expression is denoted with a tilde (~). For example:
<Directory ~ "^/www/.*/[a-z]{3}">
. . .
</Directory>
Stronghold 2.4.1 also includes several "match" containers designed specifically for regular expressions. The tilde character is not required in those containers. Where regular expressions are required, use the match containers. For example, the <DirectoryMatch> container can accomplish the same task as the <Directory> container above:
<DirectoryMatch "^/www/.*/[a-z]{3}">
. . .
</DirectoryMatch>
Metacharacters modify single characters within a regular expression:
Certain classes of characters are predefined, and you can use them instead of expressions:
Finally, regular expressions can be combined. If you have expression A and expression B, you can combine them in two ways:
- AB matches "AB"
- A|B matches "A" or "B"
Configuring Virtual Hosts
In addition to the "main" host, the server can support a number of virtual hosts. The server must be able to distinguish between virtual hosts. Virtual hosts can be distinguished in three different ways:
Regardless of which virtual host configuration you choose, each SSL/TLS virtual host must have a separate key pair and certificate, and every virtual host must have a <VirtualHost> container that specifies an IP number and a port number:
<VirtualHost 205.254.204.194:80>
. . .
</VirtualHost>
Each virtual host should be designated by its IP number, even if it is not an IP-based virtual host, to avoid relying on DNS lookups. Because regular hosts and SSL/TLS hosts use different ports and require separate configurations, each virtual host container tag must also specify a port number, even if it does not pertain to a port-based virtual host.
|
NOTE:
|
If you are running an SSL/TLS-only server, you do not need a specify a port because all hosts listen on the globally-configured SSL/TLS port.
|
Each <VirtualHost> container should include these directives:
For example:
<VirtualHost 205.254.204.194:80>
ServerName www.example.com
ServerAdmin webmaster@example.com
DocumentRoot /www/htdocs/example
CustomLog logs/example.log "%h %l %u %t \"%r\" %s %b"
</VirtualHost>
If you want the virtual hosts to serve SSL/TLS requests, you must add an SSL/TLS <VirtualHost> container for each one. Each SSL/TLS container must include the directives above (except CustomLog), plus these SSL/TLS-specific directives:
For example:
<VirtualHost www.example.com:443>
ServerName www.example.com
DocumentRoot /usr/local/www/htdocs/example
ServerAdmin webmaster@example.com
SSLFlag on
SSLCertificateKeyFile private/example.key
SSLCertificateFile certs/example.cert
SSLLogFile logs/ssl/example_cipher_log
</VirtualHost>
Note that the opening container tag must specify the SSL/TLS port number, usually port 443. If you are using port-based virtual hosts, each SSL/TLS host has a different port number.
If you are configuring a virtual host as a mirror proxy and intend to perform server-side authentication with a proxy client certificate, you must also give the proxy virtual host a SSLProxyMachineCertPath or SSLProxyMachineCertFile directive. For more information, see "Proxy Client Certificates" on page 2-18.
IP-Based Virtual Hosts
By assigning multiple IP numbers to your server machine, you can distinguish each virtual host with its own IP address. This is the recommended virtual host configuration because it
- does not rely on browsers for support,
- does not require that users enter special port numbers, and
- supports SSL and TLS
The means for configuring multiple IP addresses at the system level vary from platform to platform, and the documentation for your operating system can provide assistance. Once you've established multiple IP support at the system level, you can enter containers for each virtual host in the configuration file. When you enter a virtual host container, specify an IP number and a port number, like this:
<VirtualHost 140.174.185.14:80>
Stronghold simply matches the IP number of each incoming request with the IP number in one of the virtual host containers. When responding, Stronghold uses the hostname specified in the ServerName directive in that container.
Port-Based Virtual Hosts
Port-based virtual hosts may share a single IP number, but each is distinguished by two unique port numbers: one for ordinary transactions, and one for SSL/TLS-secured transactions. For example:
<VirtualHost 127.65.42.1:880>
ServerAdmin webmaster@example.com
DocumentRoot /usr/local/www/htdocs/example
ServerName www.example.com
</VirtualHost>
<VirtualHost 127.65.42.1:4430>
ServerAdmin webmaster@example.com
DocumentRoot /usr/local/www/htdocs/example
ServerName www.example.com
SSLFlag on
SSLCertificateKeyFile private/www.example.com.key
SSLCertificateFile certs/www.example.com.cert
</VirtualHost>
No other virtual hosts on this server can use port 880 or 4430. Each port-based virtual host must be assigned ports for SSL/TLS and regular (non-secure) transactions that are not used by any other virtual hosts on the server.
Under this scheme, every link in every file belonging to a host must take one of two forms:
Inevitably, users enter URLs without port numbers. When this happens under a port-based virtual host scheme, port 80 receives the request. When a user specifies HTTPS without a port number, port 443 receives the request. Be sure that one of your hosts listens on ports 80 and 443 and that its main page contains links to your virtual host ports.
|
NOTE:
|
If you use port-based virtual hosts, you cannot use name-based virtual hosts in the same instance of the server.
|
Name-Based Virtual Hosts
Name-based virtual host support depends largely on the compliance of browsers with the HTTP/1.1 protocol, which requires the Host header in all client requests. This allows the server to determine which hostname is being requested. It also allows multiple virtual hosts to share a single IP number. The latest browsers, including Netscape Navigator and Microsoft Internet Explorer, support HTTP/1.1. Many older browsers do not.
Name-based virtual hosts do not support SSL/TLS. Under SSL and TLS, all HTTP headers are encrypted, including the Host header required to determine which host is being requested. Without the Host header, Stronghold cannot determine which virtual host configuration to apply. Without the correct configuration, Stronghold also cannot determine which site certificate to send or which private key to use when decrypting SSL/TLS requests.
As with IP-based virtual hosts, you must configure the Domain Naming System (DNS) to point all hostnames to your IP number. The means for doing this vary from platform to platform, and the documentation for your operating system can provide assistance.
For each IP number that is used for name-based virtual hosts, the server's global configuration must contain a NameVirtualHost directive. The IP number specified by NameVirtualHost is used only for name-based virtual hosts; the main server and other types of virtual hosts never respond to that IP number. This means that you must have a separate IP number reserved for use with name-based virtual hosts. If you only have one IP number, all hosts (including the main host) must be name-based virtual hosts in order to work.
For example:
ServerRoot /www
ServerName www.main.net
DocumentRoot /www/main/htdocs
NameVirtualHost 205.254.204.194
<VirtualHost 205.254.204.194:80>
ServerName www.kayak.com
DocumentRoot /www/kayak/htdocs
. . .
</VirtualHost>
<VirtualHost 205.254.204.194:80>
ServerName www.anorak.com
DocumentRoot /www/anorak/htdocs
. . .
</VirtualHost>
When it receives a request, Stronghold reads the Host header to get the hostname. If the host is www.kayak.com, the server looks in /www/kayak/htdocs for the requested document. If it is www.anorak.com, Stronghold uses the /www/anorak/htdocs directory instead.
Now imagine that 205.254.204.194 is the only IP number available to you. In that case, the globally configured server never responds to a request, because that IP number is reserved for name-based virtual hosts. To solve this problem, you can create a name-based virtual host configuration to represent the main server. For example:
ServerRoot /www
ServerName www.main.net
DocumentRoot /www/main/htdocs
NameVirtualHost 205.254.204.194
<VirtualHost 205.254.204.194:80>
ServerName www.main.net
DocumentRoot /www/main/htdocs
. . .
</VirtualHost>
<VirtualHost 205.254.204.194:80>
ServerName www.kayak.com
DocumentRoot /www/kayak/htdocs
. . .
</VirtualHost>
<VirtualHost 205.254.204.194:80>
ServerName www.anorak.com
DocumentRoot /www/anorak/htdocs
. . .
</VirtualHost>
In the absence of a Host header, any request for a name-based virtual host is still directed to the main server's pages. If your main server has a name-based virtual host configuration, it should also retain a global configuration in order to allow for this contingency. You must, therefore, provide a link from the main server's pages to the name-based virtual hosts. Furthermore, any links in the virtual host's pages should be relative in order to work with older browsers. This is a cumbersome approach and may become less important as browsers evolve.
Certificates and Key Pairs for Virtual Hosts
Because Microsoft Internet Explorer and Netscape Navigator check the URL against the hostname on any server certificate, each SSL/TLS virtual host requires a separate certificate. You must generate a key pair, request a certificate, and install the certificate for each SSL/TLS virtual host.
Run the ServerRoot/bin/genkey program, specifying a virtual hostname:
# genkey hostname
For complete genkey instructions, see "Generating a New Key Pair and Requesting a New Certificate" on page 2-27. The key pair is saved at ServerRoot/ssl/private/hostname.key. Along with the key pair, genkey generates a certificate signing request (CSR) to send to a Certification Authority (CA), typically Verisign or Thawte.
For more detailed information about certificates, certification authorities, Verisign, or Thawte, see Chapter 2.
Reconfiguring an SSL/TLS-Only Server
When you install Stronghold Web Server, you have the option to enter "0" when prompted for a port to use for unsecured transactions. This disables normal, unsecured transactions. If you later decide to introduce non-secure transactions on your server, follow these instructions:
To convert an secure-only server
to a dual secure/nonsecure server
- Open httpd.conf in a text editor.
- Insert the following virtual host configuration below all other virtual hosts:
Listen 80
<VirtualHost _default_:80>
ServerName hostname
ServerAdmin email-address
SSLFlag off
DocumentRoot /full/path/to/document/root
TransferLog logs/access_log
ErrorLog logs/error_log
</VirtualHost>
This virtual host responds to HTTP requests for your main host.
- Run the restart-server script to restart the server.
Stronghold rereads the httpd.conf file and implements your changes.
If you also add nonsecure counterparts for your existing, SSL/TLS-only virtual hosts, you must first make sure those hosts use an IP/port number configuration. For example:
<VirtualHost 209.60.53.41:443>
For each IP- or port-based SSL/TLS virtual host, add a nonsecure counterpart. Insert any new, non-SSL virtual hosts above the <VirtualHost _default_:80> container. Each must also use an IP address and a port number. For example, the nonsecure counterpart to the example above looks like this:
<VirtualHost 209.60.53.41:80>
ServerName hostname
ServerAdmin login@hostname
SSLFlag off
DocumentRoot /full/path/to/document/root
TransferLog logs/hostname_access_log
ErrorLog logs/hostname_error_log
</VirtualHost>
Note that if you want to insert single HTTP-only virtual hosts with no counterparts, these can be name-based.