How to enable Brotli compression in Apache

Mon, 2016-12-19 13:18

Google's Brotli compression algorithm is currently available in Chrome and Firefox, and it is supposed to give about 25% more compression without additional CPU or memory use. For Nginx, there is a implementation from Google themselves. My favorite web server, Apache, still lacks Brotli compression support in its stable branch.

There is, however, a third party Apache module kjdev/apache-mod-brotli that I could get working, and so far the results are promising.

Below is a comparison of file sizes in uncompressed, gzipped, and Brotli-compressed formats:

Brotli vs GZip vs Uncompressed comparison

Compared to the gzip results, all the text-based assets had their size reduced between 8.84% - 23.52%, and average of about 10% for that page! The difference is not dramatic at first, but considering over 50% of the browsers support Brotli, and the CPU/Memory difference is about the same, it is worth implementing Brotli support.

Prerequisites

I'm not sure if there is a technical reason behind this, but all the browsers I tested with require HTTPS in order to enable Brotli support. I have written a small post about more reasons to switch to HTTPS as well. Other than that, you will need to build the Apache module yourself (I have mine available to download at the bottom of this page).

  • Apache installed.
  • HTTPS enabled.
  • Access to your Apache installation (so no shared hosts)
  • Brotli binary installed

To install the Brotli binary, simply run apt-get install brotli (or equivalent package manager command).

Build the module

I have the compiled .so file at the bottom of this post. However, I strongly encourage you to compile it yourself. Shouldn't take more than a few minutes. Note that these instructions are for Debian/Ubuntu based systems. CentOS/RHEL folks should be able to get this working as well; just swap the package manager commands with yum or whatever package manager you use.

FIrst, install the Apache2-dev package.

apt-get install apache2-dev

This will install a bunch of tools that you need to compile the module.

git clone --depth=1 --recursive https://github.com/kjdev/apache-mod-brotli.git
cd apache-mod-brotli
./autogen.sh
./configure
make

This will clone the module from Github, and build the module. The .so file will be available inside the .libs folder. Now, lets put the module where other Apache modules are installed:

install -D .libs/mod_brotli.so /usr/lib/apache2/modules/mod_brotli.so -m 644


Install the module

Now with the module built, and moved among the other modules, it is time to enable the module!

Recent Apache versions come with the handy a2enmod program to enable modules (and a2dismod to disable). In order for it to detect our new module, we need to create a .load file with the module load information.

cd /etc/apache2/mods-available
echo "LoadModule brotli_module /usr/lib/apache2/modules/mod_brotli.so" > brotli.load

This will create and add the module path to a brotli.load file. Next, we need to create a configuration file for Brotli to work.

nano brotli.conf

This will open up nano with the new file brotli.conf. As a base configuration, put the following:

<IfModule brotli_module>
  # Compression
  ## BrotliCompressionLevel: 0-11 (default: 11)
  BrotliCompressionLevel 10

  ## BrotliWindowSize: 10-24 (default: 22)
  BrotliWindowSize 22

  # Logging
  # Filter note
  BrotliFilterNote Input  brotli_in
  BrotliFilterNote Output brotli_out
  BrotliFilterNote Ratio  brotli_ratio

  #LogFormat '"%r" %{brotli_out}n/%{brotli_in}n (%{brotli_ratio}n)' brotli
  #CustomLog ${APACHE_LOG_DIR}/brotli_access.log brotli

  # Output filter
  AddOutputFilterByType BROTLI text/html text/plain text/css text/xml
  AddOutputFilterByType BROTLI text/css
  AddOutputFilterByType BROTLI application/x-javascript application/javascript
  AddOutputFilterByType BROTLI application/rss+xml
  AddOutputFilterByType BROTLI application/xml
  AddOutputFilterByType BROTLI application/json

  # Global output filer if necessary.
  # SetOutputFilter BROTLI
  # SetEnvIfNoCase Request_URI \.txt$ no-br

</IfModule>

You can configure the Brotli compression level between 1 and 11. The module developers recommend setting is 10. There is a paper on the compression level and their performance compared if you would like to change this value.

Optionally, you can also log the Brotli-served Logs with their information to a custom log file. Uncomment as necessary.

Under Output filters, we enable Brotli compression for a bunch of common content types.Again, modify them as necessary. Do note that you will not gain any improvements on file formats that are already compressed for obvious reasons. Most of the content types in the configuration above are the same types used with mod_deflate (gzip). I added application/json of my own.

Enable the module

a2enmod brotli
service apache2 restart

You should have Brotli running with Apache. Inspect the browser request headers that have Accept-encoding: ... br, and make sure that the response contains Content-encoding: br header.


Silly Silicon Valley reference

Compiled module

For those who don't want to build the module yourself, you can download the module and configuration files below. It was built for my Ubuntu 16.10 VPS running Apache 2.4.23. YMMV.

  1. mod_brotli.so
  2. brotli.conf
  3. brotli.load

Your thoughts