Apache Week
   

Copyright 1996-2005
Red Hat, Inc.

Hints and Tips:

Apache Week regularily contains information about how to get the most out of the Apache server. To save you having to wade through all the past issues, here is a summary of the hints and tips we've carried, plus a few more for good measure.

First published:  1997

Hints and Tips

Upgrading to 1.3

If you are planning on upgrading to 1.3, read our Guide to Apache 1.3.

Using Content Negotiation

See our feature on Content Negotiation

Restricting access to a file

As it implies, the <Directory> directive only applies to directories. Restricting access to particular files The <Location> directive can be used to restrict access based on the request URL. So it can applied to individual files. For example, to prevent access to the file /prices/internal.html by anyone outside 'domain.com', you could use

  <Location /prices/internal.html>
  order deny,allow
  deny from all
  allow from .domain.com
  </Location>

Problems with NCSA .htaccess files

The NCSA tutorial on .htaccess files shown an example .htacces file like this:

AuthUserFile /dev/null
AuthGroupFile /dev/null
AuthName EnterPassword
AuthType Basic

<Limit GET>
order deny,allow
deny from all
allow from .my.domain
</Limit>

This is designed to restrict access based on browser address, and not require any user authentication. The problem is that Apache will ask for user authentication, which fails because none has been setup. Apache does this because of the Auth* directives, which are unneccessary. The fix is to remove the Auth* lines.

How to speed up Apache

There are a number of things which can be done to tune the performance of the server. One quick and effective thing to try is to reduce the number of .htaccess files it tries to access on every request.

Whenever Apache handles a request, it processes .htaccess files which determine access authorisation, and can set other options (e.g. AddType). It checks and processes .htaccess files in the same directory as the file it is serving, and also in all the parent directories. For instance, if you request the URL /docs/about.html and your document root is /usr/local/etc/httpd/htdocs, Apache tries to process .htaccess files in all these directories:

/
/usr
/usr/local
/usr/local/etc
/usr/local/etc/httpd
/usr/local/etc/httpd/htdocs
/usr/local/etc/httpd/htdocs/docs

Normally, there will be no .htaccess files above the document root, but Apache still needs to check the filesystem to make sure. This can be eliminated by using the trick that if the AllowOverride option is set to None, Apache doesn't bother checking for .htaccess files. So set AllowOverride to None for directory /, and turn AllowOverride back on for whatever settings are really needed for the directory /usr/local/etc/httpd/htdocs. For example, the following code in access.conf would speed up Apache:

<Directory />
AllowOverride None
</Directory>

<Directory /usr/local/etc/httpd/htdocs>
AllowOverride All
</Directory>

The second directory section turns on AllowOverrides, so that .htaccess files are processed again. The 'All' can be replaced with whatever level of configurability is wanted.

If you have web documents in different directories besides the document root, you will need to turn on .htaccess file in them as well (if desired). For instance, if you are using UserDir to allow access to files in home directories, you will need to set a suitable AllowOverride (and possibly other restrictions) with something like:

<Directory /home/*/public_html>
AllowOverride FileInfo Indexes IncludesNOEXEC
</Directory>

Rotating log files without killing the transactions in progress

Sending the parent Apache process a USR1 signal will make it close the current log files, and re-open them, without loosing any connections currently in progress. This should be used instead of a HUP signal in any log rotation script. The script should first move the current log files to new names (the logs are still open at this stage). Then it should send a USR1 signal to the parent Apache process. The parent will tell the child process to die when they have finished processing their current request, and will open the log files for newly created children (since the old files have been renamed, the opened files will be newly created). As the old children finish their current requests they will close their handle to the (old) log files, and exit. When all the children are dead you can safely process the old log files (for example, by compressing it). Since you cannot know for definite when the old children have all died, the best way to do this is to make your log rotation script sleep for a while after sending the USR1 signal.

An alternative way to implement log rotation is to get Apache to send log messages to a program of your choice via a pipe. This program can then decide how and when to rotate the log files. A program which may be useful for doing this is available as cronolog (not part of Apache).

Using a single config file

Apache comes with an uses three different config files (the srm.conf, access.conf and httpd.conf files). However it treats them all identically. So all the configuration could take place in a single file - httpd.conf (which is the first one read). This file should include the directives

AccessConfig    /dev/null
ResourceConfig  /dev/null

to prevent it complaining about the missing srm.conf and access.conf files.

Running CGI programs as other users

CGI programs always run as the same user that owns the Apache server process. This is set with the User directive in the config file, and is typically a normal user such as 'www', or the 'nobody' user. In most cases, this is fine, since CGI scripts should run with few privileges to limit any potential malicious damage to the system. However, in some cases it would be nice to be able to run CGI programs as other users. For example:

  • On a virtual host system, with multiple customers, CGIs could run as the customer's user, to let them read and write to the customer's files.
  • On other systems with multiple users, CGIs in home directories could run as that user.

The ability to run CGI programs as other users is referred to as 'running setuid', after the Unix filesystem ability to run a program as another user. The biggest problem with having a setuid CGI facility on a web server is security. It has to be very careful to ensure that the program running setuid cannot be invoked to do malicious damage to the system. Having setuid programs on a system can be dangerous, particularly if you do not trust all the other users on the system (which would be the case with both the example above). The risk is that other users could run the setuid program manually (from the command line) and give it an environment or command arguments that make it perform undesired activities. The risks of setuid programs are well-known to Unix system administrators, but a lot of web administrators do not have so much experience of Unix or setuid security programming.

The suEXEC program included with Apache provides one method of running CGI programs as other users.

Ignoring files

The are some files that should probably never be served up to the user: files called .htaccess, .htpasswd, *.pl, *~ and so on. This can be done by preventing access to these files using a <Files> section. For example

  <Files .htaccess>
  order allow,deny
  deny from all
  </Files>

HTML Scripting

An easy way to add new capabilities to the server without too much programming is to use some sort of "parsed HTML". This is a souped-up version of server side includes which lets you use variables, conditionals, loops and so on. Like SSI, these scripts get parsed on the server so they work with all browsers. There are several implementations of HTML scripting now available: SSI (part of Apache); NeoScript (linked to apache by a module); PHP.

Forcing a handler or mime type

New directives have been added to force all the files in a particular directory to be processed by a given handler, or to be returned with a particular type. To set a handler, use SetHandler, and to set a mime type use ForceType. Note that these directives force the given type or handler to be applied to all files in the section, irrespective of the usually extension mapping rules.

For example, a download directory could use "ForceType applicaton/octet-stream" in a .htaccess file to make the browser save the files, rather than try and display them. Or, all files in a directory could be treated as CGI programs with

<Directory /usr/local/etc/httpd/cgi-bin>
SetHandler cgi-script
</Directory>

Quick Questions

  • How can I get my server to listen to more than one IP address, or more than one port?
    Use the "Listen" directive.
  • How can I create extra virtual hosts without using extra IP address?
    Use the "name-based virtual hosts" as specified in the HTTP/1.1 spec. While this does not work with all browsers at present, the directives ServerPath and ServerAlias can be used to make you site work gracefully for older browsers as well.
  • Can I let users access protected areas 'anonymously' (like anonymous ftp)?
    Yes, Use the anonymous authentication module, mod_auth_anon
  • How can I convert the requested URL into some other format?
    The rewrite module provides a powerful means for translating URLs into other URLs or filenames.
  • How do I set up Apache to handle PUT (or DELETE) requests for my authoring program?
    Use "Script PUT cgi-script" to call a CGI program to implement the PUT request.
  • Can I implement NCSA's 'Satisfy' function?
    Yes, this is now in 1.2.

  • Why does Apache 'lock-up' when accessed from Netscape 2?
    This might be due to a bug in Netscape when using Keep-Alives. The work-around is to turn off keep-alives on the server. In Apache 1.2, use the following directive:
      BrowserMatch Mozilla/2 nokeepalive
    


Comments or criticisms? Please email us at editors@apacheweek.com