Make Browsers Cache Static Files With mod_expire On Lighttpd (Debian Squeeze)

Version 1.0
Author: Falko Timme
Follow me on Twitter

This tutorial explains how you can configure Lighttpd to set the Expires HTTP header and the max-age directive of the Cache-Control HTTP header of static files (such as images, CSS and Javascript files) to a date in the future so that these files will be cached by your visitors' browsers. This saves bandwidth and makes your web site appear faster (if a user visits your site for a second time, static files will be fetched from the browser cache). This tutorial was written for Debian Squeeze.

I do not issue any guarantee that this will work for you!


1 Preliminary Note

I'm assuming you have a working Lighttpd setup on your Debian Squeeze server, e.g. as shown in this tutorial: Installing Lighttpd With PHP5 And MySQL Support On Debian Squeeze


2 Enabling mod_expire

You *could* enable mod_expire with the command lighty-enable-mod expire, however this gives you no control in which order Lighttpd modules are loaded, and as stated in the Troubleshoot section on, it is strongly recommended to load mod_expire before all other modules.

Therefore we open /etc/lighttpd/lighttpd.conf...

vi /etc/lighttpd/lighttpd.conf

... and add mod_expire as the first module in the server.modules stanza:

server.modules = (
#       "mod_rewrite",

Restart Lighttpd afterwards:

/etc/init.d/lighttpd restart


3 Configuring mod_expire

The mod_expire configuration can be placed in the overall Lighttpd server configuration or inside a virtual host container.

In this example, I will place it in the overall server configuration (i.e., this configuration is active for all vhosts):

vi /etc/lighttpd/lighttpd.conf

On Lighttpd, Expires headers are set based on the directory where a file is located, not on the file type (this is different from Apache). For example, a valid mod_expire configuration would be as follows:

expire.url = ("/images/" => "access plus 7 days", "/jquery/" => "access plus 2 weeks", "/js/" => "access plus 2 months", "/misc" => "access plus 1 days", "/themes/" => "access plus 7 days", "/modules/" => "access plus 24 hours")

In the above example, all files from the /images/ directory (and its subdirectories) get an Expires header with a date 7 days in the future from the browser access time. Therefore, you should make sure that the directories you list in the expire.url directive really only contain static files that can be cached by browsers.

Restart Lighttpd after your changes:

/etc/init.d/lighttpd restart

You can use the following time units in your configuration:

  • years
  • months
  • weeks
  • days
  • hours
  • minutes
  • seconds

Please note that you must use these time units in plural because otherwise Lighttpd will refuse to start. So you must not use access plus 1 day, but access plus 1 days instead (this is also different from Apache where both singular and plural are allowed).

It is possible to combine multiple time units, e.g. as follows:

"access plus 1 months 15 days 2 hours"

Also note that if you use a far future Expires header you have to change the component's filename whenever the component changes. Therefore it's a good idea to version your files. For example, if you have a file javascript.js and want to modify it, you should add a version number to the file name of the modified file (e.g. javascript-1.1.js) so that browsers have to download it. If you don't change the file name, browsers will load the (old) file from their cache.

Instead of basing the Expires header on the access time of the browser (e.g. "access plus 60 days"), you can also base it on the modification date of a file (please note that this works only for real files that are stored on the hard drive!) by using the modification keyword instead of access:

"modification plus 7 days"

It is also possible to include your mod_expire rules inside a condition, e.g. as follows:

	  $HTTP["url"] =~ "^/images/" {
         expire.url = ( "" => "access plus 1 hours" )

This tells Lighttpd to add an Expires header to all files where the URL begins with /images/ (like


4 Testing

To test if your configuration works, you can install the Live HTTP Headers plugin for Firefox and access a static file through Firefox (e.g. an image). In the Live HTTP Headers output, you should now see an Expires header and a Cache-Control header with a max-age directive (max-age contains a value in seconds, for example 604800 is one week in the future):


Share this page:

Suggested articles

0 Comment(s)

Add comment