Recently, I placed some rather large PDF files on my Web server. This presented a problem: even with a relatively high bandwidth DSL connection, people quickly saturated my link when they began downloading these files.

Apache 1.3.x (which is what I use) does not have a built-in capability to limit the transfer speed of large downloads, but fortunately, others came to the rescue. Specifically, CohProg Sàrl, a Swiss Internet company that makes an Apache module, mod_bandwidth, available for free.

Here are the steps one has to take to implement bandwidth limiting on a running Apache server.

First, you need to (of course) download the module. Should go without saying. What you download is a single source file, mod_bandwidth.c.

Next, you need to compile this module. On an existing Apache installation, the following line should do the trick:

/usr/sbin/apxs -c ./mod_bandwidth.c -o mod_bandwidth.so

Next, you need to copy mod_bandwidth.so to your libexec directory (typically, /usr/libexec). This you need to do as root.

Next, edit your httpd.conf file. As the first LoadModule line, add the following:

LoadModule bandwidth_module  libexec/mod_bandwidth.so

As the first AddModule line, add the following:

AddModule mod_bandwidth.c

Then, just before your VirtualHosts blocks, insert the following:

<IfModule mod_bandwidth.c>
    BandWidthModule On
    BandWidthDataDir /var/tmp/apachebw/
</IfModule>

You can now gracefully restart Apache:

apachectl graceful

Now you're ready to limit the bandwidth in specific directories (and all their subdirectories) by editing the .htaccess file in them. For instance:

<IfModule mod_bandwidth.c>
    BandWidth 199.166.252 0
    BandWidth vttoth.com 0
    BandWidth all 8192
</IfModule>

More documentation about mod_bandwidth, including alternate methods to rebuild the code, is available at the CohProg Sàrl Web site.

And before I forget, according to the author it is also a good idea to run their cleanlink.pl script, which periodically removes stale link information (without which the server's performance might suffer). I added the following to my /etc/rc.d/rc.local file:

# Running mod_bandwidth cleanup process
if [ -x /usr/local/sbin/cleanlink.pl ]; then
  echo "Running cleanlink.pl..."
  /usr/bin/sudo -u nobody /usr/local/sbin/cleanlink.pl
fi