Internet, IT and Technology

Nginx add support for Brotli on Debian and Ubuntu

nginx debian ubuntu brotli

In this guide I will be explaining how to compile the Brotli module for Nginx, a compression algorithm developed by Google, as an alternative to GZIP and Deflate. The reason for compiling the module is that Nginx has not officially supported the open source version, and in its Nginx Plus version it is supported.

Tested with systems:

  • Debian 10 Buster
  • Debian 11 Bullseye
  • Ubuntu 20.04 Focal Fossa
  • Ubuntu 22.04 LTS Jammy Jellyfish

Using Nginx versions:

  • Nginx 1.14
  • Nginx 1.18

Install Nginx

The first thing we need to do is install Nginx. If we are going to compile the module locally, we must use exactly the same distribution with the same repositories. Since we can simply copy it to production, but the environments must be the same. If in the final system we will use the nginx-full, nginx-extras or any other package, it is not a bad idea to install them as well, a small detail like this can take up many hours.

We install with:

sudo apt -y install nginx

Install dependencies

We update packages that have pending updates:

sudo apt update
sudo apt -y upgrade

We install the following packages:

sudo apt -y install git libpcre3 libpcre3-dev zlib1g zlib1g-dev libxslt1-dev openssl libssl-dev apt-src

Before the next step we edit our /etc/apt/sources.list, and remove the # symbol from the lines that have deb-src, only from the repositories that are being used.

sudo nano /etc/apt/sources.list

In an Ubuntu installation, the repositories come like this:

deb http://archive.ubuntu.com/ubuntu focal main restricted
# deb-src http://archive.ubuntu.com/ubuntu focal main restricted

We have to uncomment each repository that we find under each deb.

After editing it it should look like this:

deb http://archive.ubuntu.com/ubuntu focal main restricted
deb-src http://archive.ubuntu.com/ubuntu focal main restricted

Then update the apt and apt-src cache:

sudo apt update && sudo apt-src update

Download Nginx and Brotli source code

We create a directory to save everything in our user's home directory:

cd ~ && mkdir nginx-brotli && cd nginx-brotli

We start by downloading the Nginx source code with apt-src so that it matches the installed version of the system:

sudo apt-src install nginx

Then we download the Brotli source code from the official Google repository:

cd ~/nginx-brotli
git clone https://github.com/google/ngx_brotli.git
cd ngx_brotli
git submodule update --init

Compile Brotli as a dynamic module

We change the directory to that of Nginx:

cd ~/nginx-brotli/nginx-*/

We execute the following:

sudo ./configure --with-compat --add-dynamic-module=../ngx_brotli

If no error appears, we run:

sudo make modules

And if everything went well, we go to the Nginx Configuration section.

In case of error using configure

When we get error while executing ./configure above. We follow the following steps.

We run the following command to see the build options that the installed version of Nginx uses:

sudo nginx -V

We copy all the options after the text configure arguments:, we remove all the options that begin with --add-dynamic-module and we add them to the end separated with a space:

--add-dynamic-module=../ngx_brotli

At the beginning, we add sudo ./configure and a space to separate the options. It should be something similar to the following:

sudo ./configure OPCIONES_DEL_COMANDO --add-dynamic-module=../ngx_brotli

The resulting command is usually several lines long, I summarized it with "COMMAND_OPTIONS" to make it more understandable. We execute it as a command.

We can use the following command to generate the complete command instead of doing it manually:

sudo nginx -V 2>&1 | grep '^configure arguments:' | sed -r 's/--add-dynamic-module=(\S)+(\s|$)//g; s/$/\-\-add\-dynamic\-module=\.\.\/ngx_brotli/g; s/configure arguments:/sudo \.\/configure/g'

The above command modifies the output of nginx -V and turns it into the command we need to compile Nginx. We copy it and execute.

Copy from where it says sudo ./configure....

Lastly, we run:

sudo make modules

Nginx configuration

Copy the resulting files ngx_http_brotli_filter_module.so and ngx_http_brotli_static_module.so to the /etc/nginx/modules-available directory:

sudo cp objs/ngx_http_brotli_filter_module.so /etc/nginx/modules-available
sudo cp objs/ngx_http_brotli_static_module.so /etc/nginx/modules-available

We create the file /etc/nginx/modules-enabled/50-brotli.conf:

sudo nano /etc/nginx/modules-enabled/50-brotli.conf

And we add the following references to the modules:

load_module /etc/nginx/modules-available/ngx_http_brotli_filter_module.so;
load_module /etc/nginx/modules-available/ngx_http_brotli_static_module.so;

We test the configuration and modules with:

sudo nginx -t

If everything is fine it will appear:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok   
nginx: configuration file /etc/nginx/nginx.conf test is successful

Otherwise, if there is any problem, the output will be:

nginx: [emerg] module ngx_http_brotli_filter_module.so is not binary compatible in nginx.conf...

If we do not know why we have errors, we must pay attention to the command, configure and review all the errors that appear at the end. It would also not hurt to check if we are using the same version, and if the target system is different, even more so. As long as we do not restart Nginx, there would be no problem because the last command only reviews the configuration without making any changes.

To end the mess left behind, delete the used source files:

sudo rm -R ~/nginx-brotli/

Use in other production or development systems

Since everything is checked and the versions of the operating system and software match, we can copy the files that were left in /etc/nginx/modules-available. Taking into account that every time there is an update, no matter how minimal, we have to recompile the modules to make them compatible. It wouldn't hurt to rename them so that they have the format, module-1.14-2.so referring to the version of Nginx for which they were compiled. In addition to copying them, we have to perform the previous steps, such as re-editing the Nginx configuration file to load the modules and double-checking the configuration before rebooting.

Block Nginx package update

If we want to avoid accidents, we can use the apt-mark utility to force the package manager not to update Nginx, but to update the rest of the packages.

Block installed version:

sudo apt-mark hold nginx

To unlock the package after placing new modules and checking your new configuration:

sudo apt-mark unhold nginx

Restart Nginx if there is no problem

To restart Nginx after checking that the modules are working, use:

sudo systemctl restart nginx

Activation and use of modules

At this point Nginx already has the modules loaded, we just need to activate and configure them, and at the end we will check if they are working.

We edit the nginx.conf file:

nano /etc/nginx/nginx.conf

Exactly, below gzip on; we place on a new line:

brotli on;

Then we look for a line that has gzip_types, if it starts with "#" we remove it, copy it completely and place the new one below it, the result will be something similar:

gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
brotli_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

Both lines must have the same arguments to take full advantage of the new compression algorithm.

We check that the configuration works with sudo nginx -t and restart the service:

sudo systemctl restart nginx

For the ngx_http_brotli_static_module.so module you have to use it the same as the gzip_static option, we can check the directive in the Google repository, or the gzip_static directive in Nginx.

Checking the operation of the compression algorithm

For this we will need to use Firefox, Chrome, or any browser that supports this algorithm. If it is the same system where we have the package installed, we open 127.0.0.1 in the browser and open the developer tools with F12, and go to the Network tab. We click on the URL and verify that in Response Headers in Content-Encoding it appears "br", in Request Headers and Accept-Encoding we verify that it appears "gzip, deflate, br" in any order. If "br" does not appear in Content-Encoding, it means that the server did not send the content with the new algorithm, and if "br" does not appear in Accept-Encoding, it may be that the browser does not support it, or it is simply not activated for the type of document.

navegador dev tools brotli test

If we have problems with Firefox it could be because Brotli is not supported on connections without SSL, and since in this case we use localhost it may not work locally. To test without SSL, we can use Chrome, which at least in version 84 supports it without HTTPS.

I relied on this post from the Website for Students, although I had problems in the binary compatibility step. In the official Brotli repository comes little information about the build.

Related content