How To Enable Brotli Compression In Apache 2.4

Web servers have been able to compress the content they serve for quite a while now. When they receive a request for an asset that lends itself to compression, usually a text file such as HTML or CSS it will compress it before sending it to the browser. The browser will then decompress the file and load it. This process cuts down on the amount of data that is served and also speeds up website loading.

The compression tool that has been used for this has been gzip. This is a solid compression algorithm but is getting quite old now. Google have developed a newer algorithm called Brotli that can be used in place of gzip.

Brotli has the advantage that for the same amount of CPU work a smaller compressed file is created. This magnifies the advantages of using compression to serve site content.

All the major browser - Chrome, Firefox, Safari, Edge - support brotli so lets configure Apache to use it.

Note, Apache is able to continue serving pages with gzip in addition to brotli and will only serve brotli compressed files to browsers that support it.

Install Brotli

This is usually a single package. On Debian and Ubuntu the following will work:

apt install brotli

And your done.

Configure Apache

Apache ships with the brotli module and so it just needs enabling:

a2enmod brotli

Now we need to add the configuration so that Apache knows when to use brotli. You can put this configuration in either the VirtualHost file of a particular website or into the main configuration for all your sites:

    <IfModule mod_brotli.c>
    AddOutputFilterByType BROTLI_COMPRESS text/html text/plain text/xml text/css text/javascript application/x-javascript application/javascript application/json application/x-font-ttf application/vnd.ms-fontobject image/x-icon
    </IfModule>

The long line tells Apache which file types to compress.

Here is a complete, example VirtualHost file:

<VirtualHost 1.2.3.4:443>

    DocumentRoot /var/www/
    ServerName example.com

    SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
    Include /etc/letsencrypt/options-ssl-apache.conf

    CustomLog /var/log/apache2/example.com.access.log common
    ErrorLog /var/log/apache2/example.com.error.log

    <IfModule mod_brotli.c>
    AddOutputFilterByType BROTLI_COMPRESS text/html text/plain text/xml text/css text/javascript application/x-javascript application/javascript application/json application/x-font-ttf application/vnd.ms-fontobject image/x-icon
    </IfModule>

</VirtualHost> 

Finally, reload Apache:

systemctl restart apache2.service

Testing

The last step in any server configuration is testing. This confirms that your changs are working as you expected.

We will use curl to make a tell the server that we want brotli compression -H 'Accept-Encoding: br' and then to only print the connection headers -I of the server’s response:

$ curl -I -H 'Accept-Encoding: br' https://elliotcooper.com

This prints the following reply:

HTTP/2 200 
date: Thu, 23 Apr 2020 12:45:55 GMT
server: Apache/2.4.38 (Debian)
strict-transport-security: max-age=15552000; includeSubDomains
last-modified: Wed, 08 Apr 2020 14:53:30 GMT
etag: "15e8-5a2c8a9d7bf77-br"
accept-ranges: bytes
vary: Accept-Encoding
content-encoding: br
content-length: 1539
content-type: text/html

This line:

content-encoding: br

indicates that the server supports serving pages with brotli.