Skip to main content
Advertisement

Apache Static File Serving and Cache Control

This chapter covers efficient static file serving and proper browser cache control in Apache. Using mod_expires, mod_deflate, and ETag settings can dramatically improve web performance.


Apache Static File Serving Basics

Apache maps requested URLs to the filesystem by combining them with DocumentRoot.

<VirtualHost *:80>
ServerName example.com
DocumentRoot /var/www/html

<Directory /var/www/html>
Options -Indexes +FollowSymLinks
AllowOverride None
Require all granted
</Directory>
</VirtualHost>

mod_expires — Cache Expiry Headers

sudo a2enmod expires
sudo systemctl reload apache2
<IfModule mod_expires.c>
ExpiresActive On
ExpiresDefault "access plus 1 week"

ExpiresByType text/html "access plus 0 seconds"
ExpiresByType text/css "access plus 1 year"
ExpiresByType application/javascript "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 month"
ExpiresByType image/png "access plus 1 month"
ExpiresByType image/webp "access plus 1 month"
ExpiresByType image/svg+xml "access plus 1 month"
ExpiresByType image/x-icon "access plus 1 year"
ExpiresByType font/woff "access plus 1 year"
ExpiresByType font/woff2 "access plus 1 year"
ExpiresByType application/json "access plus 0 seconds"
</IfModule>

mod_headers — Fine-Grained Cache-Control

sudo a2enmod headers
sudo systemctl reload apache2
<IfModule mod_headers.c>
# Hashed JS/CSS — 1 year strong cache (immutable)
<FilesMatch "\.[0-9a-f]{8,}\.(js|css)$">
Header set Cache-Control "max-age=31536000, public, immutable"
</FilesMatch>

<FilesMatch "\.(js|css)$">
Header set Cache-Control "max-age=31536000, public"
</FilesMatch>

<FilesMatch "\.(png|jpg|jpeg|gif|webp|ico|woff|woff2|ttf|svg)$">
Header set Cache-Control "max-age=2592000, public"
</FilesMatch>

<FilesMatch "\.html$">
Header set Cache-Control "no-cache, no-store, must-revalidate"
Header set Pragma "no-cache"
Header set Expires "0"
</FilesMatch>

<LocationMatch "^/api/">
Header set Cache-Control "no-cache, no-store, must-revalidate"
</LocationMatch>
</IfModule>

ETag Configuration

# Default ETag (includes inode — problematic in distributed servers)
FileETag MTime Size

# Recommended for distributed/load-balanced environments
FileETag MTime Size
# or disable completely:
FileETag None

Distributed environment warning: Default ETag includes inode numbers, which differ across servers. Use FileETag MTime Size or FileETag None to avoid cache mismatches.


mod_deflate — Gzip Compression

sudo a2enmod deflate
sudo systemctl reload apache2
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/css
AddOutputFilterByType DEFLATE application/javascript application/json
AddOutputFilterByType DEFLATE image/svg+xml font/woff font/woff2
SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|webp|zip|gz|bz2)$ no-gzip dont-vary
Header append Vary Accept-Encoding
DeflateCompressionLevel 6
</IfModule>

Comprehensive Configuration Example

<VirtualHost *:443>
ServerName static.example.com
DocumentRoot /var/www/static

SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/static.example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/static.example.com/privkey.pem

<Directory /var/www/static>
Options -Indexes -MultiViews +FollowSymLinks
AllowOverride None
Require all granted
</Directory>

<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/css application/javascript application/json image/svg+xml font/woff font/woff2
DeflateCompressionLevel 6
Header append Vary Accept-Encoding
</IfModule>

<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType text/html "access plus 0 seconds"
ExpiresByType text/css "access plus 1 year"
ExpiresByType application/javascript "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 month"
ExpiresByType image/png "access plus 1 month"
ExpiresByType font/woff2 "access plus 1 year"
</IfModule>

<IfModule mod_headers.c>
<FilesMatch "\.(js|css)$">
Header set Cache-Control "max-age=31536000, public, immutable"
</FilesMatch>
<FilesMatch "\.html$">
Header set Cache-Control "no-cache"
</FilesMatch>
</IfModule>
</VirtualHost>

Summary

OptimizationModuleEffect
Cache expiry headersmod_expiresFewer requests from repeat visitors
Fine-grained Cache-Controlmod_headersImmutable and precise cache policies
Gzip compressionmod_deflate50–80% reduction in text transfer size
ETag adjustmentFileETagPrevents unnecessary revalidation in distributed environments
Disable directory listingOptions -IndexesSecurity hardening
Advertisement