How to Configure Apache Mod_deflate, Mod_brotli, and Mod_expires for HTTP Compression and Browser Cache Control on Ubuntu Server
Learning how to configure Apache Mod_deflate, Mod_brotli, and Mod_expires for HTTP compression and browser cache control on Ubuntu Server is one of the best performance upgrades you can make for any website. These three Apache modules work together to compress outgoing content and tell browsers how long to cache static files. The result is faster page loads, lower bandwidth usage, and a better experience for your visitors. In this tutorial, you’ll enable and configure all three modules on Ubuntu Server. You’ll set up Gzip compression with Mod_deflate, add Brotli compression with Mod_brotli, and control browser caching with Mod_expires. By the end, your Apache server will serve compressed, cache-optimized responses to every client that supports them.
Prerequisites for Configuring Apache HTTP Compression and Cache Control
Before you start, make sure you have the following in place.
Required access and software:
- Ubuntu Server 20.04 or 22.04 (fresh or existing install)
- Apache 2.4 installed and running
- Root or sudo access to the server
- A basic understanding of the Linux command line
- SSH access to your server
Estimated time: 20–30 minutes.
You should already have Apache installed. If you don’t, run sudo apt install apache2 -y before continuing. This tutorial assumes Apache is serving at least one virtual host. The steps below apply whether you’re running a WordPress site, a static site, or any other web application. Check that Apache is active before you begin.
sudo systemctl status apache2
You should see active (running) in the output. If Apache isn’t running, start it with sudo systemctl start apache2.
Step-by-Step Guide to Configure Apache Mod_deflate, Mod_brotli, and Mod_expires
See also: How to Configure Haproxy Rate Limiting with Stick Tables and Acls on Ubuntu
Follow these steps carefully. Each step builds on the last.
Step 1: Enable the required Apache modules
Apache ships with Mod_deflate and Mod_expires built in. Mod_brotli requires an extra package on Ubuntu. Run the following commands to install it and enable all three modules.
sudo apt update
sudo apt install brotli libapache2-mod-brotli -y
sudo a2enmod deflate
sudo a2enmod brotli
sudo a2enmod expires
sudo a2enmod headers
sudo systemctl restart apache2
The headers module is needed for setting cache-control headers later. Enabling it now saves you a second restart.
Step 2: Open your Apache configuration file
You can add compression and cache settings to your main Apache config or to a virtual host file. For a global setup, edit the main config directly.
sudo nano /etc/apache2/apache2.conf
Scroll to the bottom of the file. You’ll add your configuration blocks there.
Step 3: Configure Mod_deflate for Gzip compression
Paste the following block at the bottom of apache2.conf. This tells Apache to compress common file types before sending them to the browser.
# Enable Gzip compression with mod_deflate
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/json
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE image/svg+xml
AddOutputFilterByType DEFLATE font/woff2
# Don't compress already-compressed files
SetEnvIfNoCase Request_URI .(?:gif|jpe?g|png|zip|gz|bz2|rar)$ no-gzip dont-vary
# Add Vary header for proxies
Header append Vary Accept-Encoding
The SetEnvIfNoCase line prevents Apache from trying to compress files that are already compressed. That would waste CPU cycles and could corrupt the response.
Step 4: Configure Mod_brotli for Brotli compression
Brotli typically achieves better compression than Gzip. Modern browsers support it. Add this block directly below the Deflate block.
# Enable Brotli compression with mod_brotli
AddOutputFilterByType BROTLI_COMPRESS text/html
AddOutputFilterByType BROTLI_COMPRESS text/plain
AddOutputFilterByType BROTLI_COMPRESS text/xml
AddOutputFilterByType BROTLI_COMPRESS text/css
AddOutputFilterByType BROTLI_COMPRESS application/javascript
AddOutputFilterByType BROTLI_COMPRESS application/json
AddOutputFilterByType BROTLI_COMPRESS application/xml
AddOutputFilterByType BROTLI_COMPRESS image/svg+xml
AddOutputFilterByType BROTLI_COMPRESS font/woff2
BrotliCompressionQuality 6
A quality setting of 6 is a solid balance between compression ratio and CPU usage. You can raise it to 11 for maximum compression, but that increases server load. See the official Apache Mod_brotli documentation for all available directives.
Step 5: Configure Mod_expires for browser cache control
This block sets expiry times for different file types. Browsers will cache these files locally and won’t re-download them on repeat visits.
# Browser cache control with mod_expires
ExpiresActive On
# Images
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/gif "access plus 1 year"
ExpiresByType image/webp "access plus 1 year"
ExpiresByType image/svg+xml "access plus 1 year"
ExpiresByType image/x-icon "access plus 1 year"
# Fonts
ExpiresByType font/woff2 "access plus 1 year"
ExpiresByType font/woff "access plus 1 year"
# CSS and JavaScript
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
# HTML
ExpiresByType text/html "access plus 1 hour"
# Default
ExpiresDefault "access plus 1 week"
Images and fonts rarely change, so a one-year cache is safe. CSS and JavaScript change more often, so one month is more appropriate. HTML should have a short cache time to ensure users always see fresh content.
Step 6: Test the configuration and restart Apache
Before restarting, always test your Apache config for syntax errors.
sudo apachectl configtest
You should see Syntax OK. If you see any errors, go back and check your configuration blocks for typos. Once the test passes, restart Apache.
sudo systemctl restart apache2
Step 7: Verify compression and caching are working
Use curl to check that compression headers are present in the response.
curl -H "Accept-Encoding: br, gzip" -I http://yourdomain.com
Look for Content-Encoding: br or Content-Encoding: gzip in the output. Also check for Expires and Cache-Control headers. You can also use the Google PageSpeed Insights tool to confirm your server is sending compressed, cached responses correctly.
Troubleshooting Common Apache Compression and Caching Issues
Brotli module not found after install: Run sudo a2enmod brotli again and check that the package installed without errors. Run sudo apache2ctl -M | grep brotli to confirm it’s loaded.
Compression not showing in headers: Make sure the mod_headers module is enabled. Run sudo a2enmod headers and restart Apache. Also confirm the file type you’re testing is listed in your AddOutputFilterByType directives.
Cache headers missing: Check that ExpiresActive On is inside the block. A missing directive here will silently disable the whole block.
Config test fails with “Invalid command”: This usually means a module isn’t enabled. Double-check that you ran all the a2enmod commands in Step 1.
Brotli and Deflate both firing: Apache negotiates based on the client’s Accept-Encoding header. Modern browsers prefer Brotli. Older browsers fall back to Gzip. This is expected behavior.
