Adding Brotli support to nginx

Last year, Google released a successor to the deflate compression algorithm, Brotli. Chrome adopted it in version 51, and Firefox in version 44 (see Can I use…). That said, from the webserver side, nginx doesn’t support it natively, so Google provides the ngx_brotli module, making it just a matter of compiling nginx.

Compiling a custom nginx build is not as daunting as it sounds. I described the process back in June, when I desired to preserve http/2 support so needed to switch to OpenSSL 1.0.2: https://ethitter.com/2016/06/nginx-openssl-1-0-2-http-2-alpn/.

Getting Brotli

First, we need the nginx module and the Brotli library checked out where we’ll build nginx. I use /usr/local/src when building from sources, but the directory can be almost anything you’d like.

cd /usr/local/src
git clone https://github.com/google/ngx_brotli.git
cd ngx_brotli
git submodule update --init --recursive

Now it’s time to compile an updated nginx.

Updating the nginx build configuration

Using the configuration from my earlier post, compiling nginx with Brotli is a matter of adding one additional flag to the ./configure call:

--add-module=/usr/local/src/ngx_brotli

In my case, the full command is now:

./configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --with-openssl=/usr/local/src/openssl --user=www-data --group=www-data --with-http_ssl_module --with-http_realip_module --with-http_addition_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_stub_status_module --with-http_auth_request_module --with-threads --with-stream --with-stream_ssl_module --with-http_slice_module --with-mail --with-mail_ssl_module --with-file-aio --with-http_v2_module --add-module=/usr/local/src/ngx_brotli

Note that starting with 1.11.5, the --with-ipv6 flag was removed because the support is now added by default.

nginx can now be compiled and installed as noted in my previous post.

Enabling Brotli

Now that nginx supports Brotli, its nginx.conf needs a small update to enable the new compression.

http {
…
	brotli on;
	brotli_static on;
	brotli_types *;
…
}

Run nginx -t to confirm the configuration and binary, then restart nginx to enable Brotli for all supported requests.

Two flavors of Brotli

In the above configuration, two types of Brotli were enabled: brotli and brotli_static. Given the name of the latter, one can probably figure out that brotli enables the compression when each request is processed. brotli_static allows pre-compressed versions of files to be served automatically when they’re present.

Creating the pre-compressed versions requires the Brotli command-line tool, which Scott Helme discusses in https://scotthelme.co.uk/brotli-compression/. Once .br files are present, nginx will serve them instead of dynamically compressing the sources.

Since the bulk of my server’s requests are fronted by a CDN that doesn’t support Brotli (it falls back to gzip, fortunately), or are dynamic and served by WordPress, I only make use of on-the-fly compression. GitLab doesn’t support a CDN, so I may create static versions of its public assets; my installation is a manual upgrade anyway, so recreating the Brotli versions with each update would be trivial.

Final Thoughts

In addition to Scott Helme’s post, I found Sam Saffron’s review of Brotli to be very insightful: https://samsaffron.com/archive/2016/06/15/the-current-state-of-brotli-compression.

One thought on “Adding Brotli support to nginx”

Leave a Reply

Your email address will not be published. Required fields are marked *