How to Disable Static File Caching in Lighttpd When Files Are Modified On Disk


2 views

During my recent work with Lighttpd (version 1.4.67), I encountered a particularly stubborn caching behavior where modified static files weren't being served with their updated content despite having new modification timestamps and changed file sizes. The web server would persistently return outdated versions until I renamed files, which clearly indicated an aggressive caching mechanism at play.

Through network analysis and server logs, I confirmed:

  • Browser requests were reaching the server (200 OK responses)
  • ETag and Last-Modified headers weren't reflecting disk changes
  • Content-Length headers showed correct new sizes but served old content
  • The issue didn't affect files processed by mod_compress

Here are the most effective approaches to solve this:

Option 1: Disable sendfile Kernel Optimization

Add to your lighttpd.conf:

server.network-backend = "writev"

This prevents Lighttpd from using the Linux sendfile() system call which can cause caching issues.

Option 2: Force Stat Checking

Configure Lighttpd to check files more frequently:

server.stat-cache-engine = "simple"
server.max-stat-cache-size = 128
server.max-worker = 2

Option 3: Add Cache-Control Headers

For specific directories (e.g., /images):

$HTTP["url"] =~ "^/images/" {
  setenv.add-response-header = (
    "Cache-Control" => "no-cache, must-revalidate",
    "Pragma" => "no-cache"
  )
}

Create a simple test case:

# Create test file
echo "version1" > /var/www/html/test.txt

# After config changes
curl -I http://localhost/test.txt
# Should show current timestamp

# Modify file
echo "version2" > /var/www/html/test.txt

# Verify
curl http://localhost/test.txt
# Should immediately show "version2"

For Linux systems, you can implement a more robust solution using inotify:

# Install inotify-tools
apt-get install inotify-tools

# Create monitoring script
#!/bin/bash
while inotifywait -r -e modify,attrib,close_write,move,create,delete /var/www/html; do
  lighty-enable-mod expire
  sleep 1
  lighty-disable-mod expire
done

Remember that disabling caching entirely will impact performance. For production systems, consider:

  • Implementing versioned filenames (file_v123.jpg)
  • Using query strings (?v=timestamp)
  • Setting appropriate Cache-Control headers

When deploying Lighttpd as a static file server, many developers encounter unexpected caching behavior where modified files aren't served with updated content. This occurs even when:

  • File modification timestamps change
  • Content length differs
  • Browser cache is cleared

The key indicators of this issue include:

# Typical problematic response headers
HTTP/1.1 200 OK
Content-Type: image/png
Last-Modified: Wed, 01 Jan 2020 00:00:00 GMT # Stale timestamp
Content-Length: 1024 # New file size

Option 1: Disable Kernel-level Caching

Add to lighttpd.conf:

server.stat-cache-engine = "disable"

Option 2: Force ETag Validation

etag.use-mtime = "enable"
etag.use-inode = "enable"
static-file.etags = "enable"

Option 3: Cache Control Headers

For specific directories:

$HTTP["url"] =~ "^/dynamic-content/" {
  setenv.add-response-header = (
    "Cache-Control" => "no-cache, must-revalidate",
    "Pragma" => "no-cache"
  )
}

Verify your configuration with:

lighttpd -tt -f /etc/lighttpd/lighttpd.conf
curl -vI http://yourserver/static/file.png | grep -iE 'last-modified|etag'

While disabling caching improves development workflow, consider these production alternatives:

  • Implement versioned filenames (file_v123.jpg)
  • Use query string versioning (file.jpg?v=123)
  • Configure proper Cache-Control max-age headers

For an image gallery that updates frequently:

# lighttpd.conf snippet
$HTTP["url"] =~ "^/gallery/" {
  server.stat-cache-engine = "disable"
  etag.use-mtime = "enable"
  setenv.add-response-header = (
    "Cache-Control" => "public, max-age=60"
  )
}