Using Brotli Compression in NGINX

Using Brotli Compression in NGINX

PERFORMANCE

Brotli is gaining steam as the compression algorithm du jour for high performance websites. Created back in 2013 by Google to decrease the size of WOFF files, Brotli was standardized in 2016 as part of RFC 7932. The sales pitch for Brotli is better compression than Gzip – with similar CPU usage. Better compression leads to faster performance, but how much better is it?

Using Brotli in NGINX

To find out, we need to enable Brotli compression. Gzip has been available in NGINX for some time. It’s a bit fiddly to ensure you’re compressing all the appropriate mime types, but mostly it’s easy to setup and get going.

Unfortunately, Brotli is not part of the default NGINX package at this time, so you have to load it as a dynamic or static module. The Brotli NGINX module is currently developed and maintained by the folks at Google.

The Easy (but Expensive) Way

NGINX Plus has official support for the Brotli module. They’ve done all the hard work of packaging the module in to the NGINX Plus repository for you. It’s just an apt-get install away! That is – if you’re a paying customer.

The Hard Way

Since we’re cheap, we don’t have access to the NGINX Plus repository. We only have the open source version of NGINX, which means we need to load the module by hand. The process is roughly this:

  • Install a load of pre-reqs
  • Compile the module for your system (groan)
  • Configure NGINX to use the newly compiled module

Installing Dependencies

Even though you’ve likely installed NGINX via some kind of package manager (apt, yum, whatever) you’re still going to need the source for the version you’ve installed. Even worse, you’re going to need all the dependencies that the source was originally compiled against. From the horse’s mouth:

Dynamic modules must be compiled against the same version of NGINX they are loaded into.

And from the Google Brotli module installation docs:

You will need to use exactly the same ./configure arguments as your Nginx configuration and append –with-compat –add-dynamic-module=/path/to/ngx_brotli to the end, otherwise you will get a “module is not binary compatible” error on startup. You can run nginx -V to get the configuration arguments for your Nginx installation.

So that all sounds complicated and terrible, but fortunately it’s not too bad if you are OK with some blind faith and a little copy/pasting. In all the following examples, we’re using Ubuntu 20.04.

Installing all the Pre-Reqs

apt-get install build-essential libpcre3 libpcre3-dev zlib1g zlib1g-dev \
libssl-dev libgd-dev libxml2 libxml2-dev uuid-dev libxslt-dev

Once you’ve got those, you’re going to need the NGINX source and the Brotli module source.

nginx -v
# nginx version: nginx/1.18.0 (Ubuntu)

Ok, so we need 1.18.0 since that’s what’s installed on our system. We also need to clone the Brotli module from Github. There are Git submodules in play, so make sure when you clone the Brotli module repository you use the --recursive flag!

wget http://nginx.org/download/nginx-1.18.0.tar.gz
tar -xzvf nginx-1.18.0.tar.gz

# Ensure you use the --recursive flag
git clone https://github.com/google/ngx_brotli.git --recursive

Getting the Configuration Arguments Right

So remember all that talk about binary compatability? When NGINX was originally compiled for your system, it was compiled with a whole slew of configure arguments. When we compile the module, we need to make sure they are exactly the same, plus we need to add a few more! To see the original configure arguments we can use the -V flag (note the capital letter this time)

All the configure arguments.
All the configure arguments.

Copy that huge list of configure arguments and paste it somewhere for safekeeping. Now comes the fun part.

Compile Time, Baby

cd nginx-1.18.0
# Paste in the configure arguments and then add the second line
# If your system is different, ./configure may spit out
# additional dependencies you need to install
./configure [ALL THE CONFIGURE ARGUMENTS] \
--with-compat --add-dynamic-module=../ngx_brotli

# If ./configure finishes successfully, you can make the module!
make modules

The compiled modules will be emitted to the obj/ folder within the source directory once compilation is successful. We need to move the .so files to a place NGINX can find them.

cp objs/ngx_http_brotli_filter_module.so /usr/lib/nginx/modules
cp objs/ngx_http_brotli_static_module.so /usr/lib/nginx/modules

Huzzah! Now we’re ready to configure NGINX. Having fun yet?

Configuring NGINX

This is the easy part. In nginx.conf you need to load the module. This needs to be the very first thing in the file.

# for compressing responses on-the-fly
load_module modules/ngx_http_brotli_filter_module.so;
# for serving pre-compressed files
load_module modules/ngx_http_brotli_static_module.so;

And then we need to turn it on! You can enable Brotli in specific location blocks, or at the server level.

Brotli Settings

    brotli on;
brotli_comp_level 6;
    brotli_types application/javascript application/x-javascript application/xml application/xml+rss 
    application/json text/javascript image/x-icon image/vnd.microsoft.icon image/bmp image/svg+xml text/xml text/css text/plain;

And finally, we need to test our configuration to make sure we did everything right, and then reload NGINX

systemctl restart nginx.service

Step 6 – Verify Brotli Module

At this point, The Nginx will be successfully installed and configured with Brotli support. You can verify whether the Brotli module is enabled or not by running the command:

curl -H 'Accept-Encoding: br' -I http://localhost

You will get the “Content-Encoding: br” in the output:

HTTP/1.1 200 OK
Server: nginx/1.18.0
Date: Sat, 31 Oct 2020 06:30:24 GMT
Content-Type: text/html
Last-Modified: Tue, 21 Apr 2020 14:09:01 GMT
Connection: keep-alive
ETag: W/"5e9efe7d-264"
Content-Encoding: br

Leave a Reply

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

RELATED POST

How to automatically restart Linux services with Systemd

Getting your Linux deployments working reliably is of paramount concern for production applications. One way to guarantee that a service…

How to Install SFTPGo on Ubuntu 22.04

Setup UFW Firewall For security reasons, it is recommended to install and configure the UFW firewall in your system. First,…

Executing Bash Scripts at Startup in Ubuntu Linux

Creating a Bash script in Ubuntu To create a Bash script in Ubuntu, you can use any text editor of…

How To Clear PHP’s Opcache

PHP can be configured to store precompiled bytecode in shared memory, called Opcache. It prevents the loading and parsing of PHP…