How to handle all requests with a fallback script in Apache 2.3

Sometimes websites need a standby webserver that tell visitors that a site is down for maintenance. In such times, it's often easiest not to depend on your favorite scripting language being available on the that standby server and use Apache's builtin capabilities to whip up some dynamic response.

Door: Jeroen Pulles, Datum: 18 oktober 2010

Here's a recipe that will sent all requests to a simple script. The Apache configuration sample below shows how to catch requests to some random URI and send a response with a simple CGI script. I use this to sent a 503 Service Unavailable response to all requests when a real website is down for maintenance and a stand-in website takes over.

ScriptAlias /down.cgi /var/www/redslider.net/scripts/down.cgi
Action down-handler /down.cgi virtual

<LocationMatch "^/(?!down.cgi|favicon.ico).*$">
    SetHandler down-handler
</LocationMatch>

Here's how Apache handles this configuration:

  • ScriptAlias sets up the URL /down.cgi. When a user agent requests that URI, the script at /var/www/redslider.net/scripts/down.cgi will be executed. That script can be written in any programming language, since it's a CGI script. I used Bourne Shell for convenience. Note that this means that there's no reason to place a file “down.cgi” in the document root, we've registered this as a virtual URL and the real file will have to be placed at /var/www/redslider.net/scripts/down.cgi.
  • LocationMatch "^/(?!down.cgi|favicon.ico).*$" tells Apache that any requests that match that regular expression will be handled here. The regular expression here actually captures any URI except /down.cgi and /favicon.ico. This (?!down.cgi|favicon.ico) is the PCRE notation for capturing anything but the strings “down.cgi” and “favicon.ico”. You don't want to catch /down.cgi, since that would cause an endless loop where Apache would try to call /down.cgi for each request to /down.cgi.
  • The SetHandler directive instructs Apache to handle any requests in this LocationMatch with the "down-handle" handler. That handler is created in the next step.
  • The Action directive configures Apache to send any requests that is supposed to be handled by "down-handler" to the URI /down.cgi, which is not a real file, but the script I just registered with the ScriptAlias directive.

Now, the down.cgi script can be really simple. Here's the simple shell script that sets the special HTTP Status response code and the Retry-After header that usually goes with it. The error message is in a simple HTML file, where 'cat' is used to send that file to the user agent. Oh, and don't forget to mark the file as executable, i.e. “$ chmod a+x down.cgi”.

#!/bin/sh

echo "Status: 503 Service Unavailable"
echo "Retry-After: 2400"
echo "Content-Type: text/html; charset=utf-8"
echo

cat htdocs/technical-difficulties.html

Note that I'm not using mod_rewrite, I'm using just a few stock Apache modules. The Action directive is available in mod_actions, that was introduced long ago with Apache 2 but hasn't seen much take up;

If you're more inclined to use PHP, you could also have dropped a PHP file at for example /down.php and have the Action handler point to that. No need to use the ScriptAlias then. And there's a performance advantage since Apache won't have to fork a shell script, it can use the PHP interpreter it already has built-in.

You probably spotted the favicon.ico exception in the regular expression. I like to keep sending the favicon in any case, since that has become one of the strongest, well, icons, or flagpoles in a webpage. If that favicon is gone, things really start to feel as if something's wrong on the website. But perhaps I'm just being silly.

Learn more about this Apache feature at Apache Module mod_actions.

More advanced examples of shell scripting can be found in Mendel Cooper’s Advanced Bash-Scripting Guide .