ABOUT / USE CASES

If you are running a Raspberry Pi LEMP server, running Ubuntu or Raspberry Pi OS, you may have the official Nginx repositories installed, and are running the official Nginx Stable or Nginx Mainline versions of Nginx. If this is the case, those repositories don’t include modules in their apt downloads. Therefore, you will have to build the modules as dynamic modules on your own.

Today, we are going to be building the Nginx Brotli Module (ngx_brotli) from source on a Raspberry Pi 4. This tutorial is compatible and will work with either Raspberry Pi OS, or Ubuntu (server) for the Raspberry Pi. This assumes you are using an arm 64 bit (aarch64) OS on your Raspberry Pi.

1) Add the Nginx Mainline repository and corresponding signing keys, then install nginx

Set up the apt repository for Nginx Mainline by copying and pasting this line exactly into your terminal:

echo -e "Nginx Mainline Official Repository for Ubuntu\ndeb [arch=arm64 signed-by=/etc/apt/keyrings/nginx-archive-keyring.gpg] \
http://nginx.org/packages/mainline/ubuntu `lsb_release -cs` nginx\ndeb-src [arch=arm64 signed-by=/etc/apt/keyrings/nginx-archive-keyring.gpg] \
http://nginx.org/packages/mainline/ubuntu `lsb_release -cs` nginx" \
    | sudo tee /etc/apt/sources.list.d/nginx.list

Don’t forget to press enter after you paste it.

Add the Official Nginx Signing Key to your keychain:

curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
    | sudo tee /etc/apt/keyrings/nginx-archive-keyring.gpg >/dev/null

Verify that the downloaded file contains the proper key:

gpg --dry-run --quiet --no-keyring --import --import-options import-show /etc/apt/keyrings/nginx-archive-keyring.gpg

It should return the following:

pub   rsa2048 2011-08-19 [SC] [expires: 2024-06-14]
      573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62
uid                      nginx signing key <signing-key@nginx.com>

If It doesn’t match, redownload the key and try again. Be sure the fingerprints573B FD6B 3D8F BC64 1079 A6AB ABF5 BD82 7BD9 BF62 match.

Then, proceed to update, upgrade, and finally install Nginx Mainline:

sudo apt update && sudo apt upgrade && sudo apt install nginx

Once installed you can check and be sure your version of Nginx is 1.25.4 with nginx -v. Then proceed to the next step.

2) Install build dependancies

sudo apt install libpcre2-dev zlib1g-dev libssl-dev cmake

3) Download nginx source package and dependancies

Modify this line by changing “yourusername” to your real Ubuntu login user name. Then copy the rest of the line and paste it in your linux terminal.

sudo chown yourusername:yourusername -R /usr/local/src/ && cd /usr/local/src/ && sudo apt install dpkg-dev && sudo apt source nginx && ls

The final “ls” command should show the following output:

nginx-1.25.4
nginx_1.25.4-1~focal.debian.tar.xz
nginx_1.25.4-1~focal.dsc
nginx_1.25.4.orig.tar.gz

4) Download the Nginx Brotli source package

cd /usr/local/src/ && git clone --recurse-submodules -j8 https://github.com/google/ngx_brotli

5) Prepare Dependancies “brotlienc” and “brotlicommon”. NOTE: You should run this entire command twice. Do so now.

cd /usr/local/src/ngx_brotli/deps/brotli && mkdir -p out && cd out && cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DCMAKE_C_FLAGS="-Ofast -march=armv8-a -mtune=cortex-a72 -flto -funroll-loops -ffunction-sections -fdata-sections -Wl,--gc-sections" -DCMAKE_CXX_FLAGS="-Ofast -march=armv8-a -mtune=cortex-a72 -flto -funroll-loops -ffunction-sections -fdata-sections -Wl,--gc-sections" -DCMAKE_INSTALL_PREFIX=./installed .. && cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DCMAKE_C_FLAGS="-Ofast -march=armv8-a -mtune=cortex-a72 -flto -funroll-loops -ffunction-sections -fdata-sections -Wl,--gc-sections" -DCMAKE_CXX_FLAGS="-Ofast -march=armv8-a -mtune=cortex-a72 -flto -funroll-loops -ffunction-sections -fdata-sections -Wl,--gc-sections" -DCMAKE_INSTALL_PREFIX=./installed ..

6) Build Dependancies

cmake --build . --config Release --target brotlienc && cd ../../../..

after that, you will have brotlienc & brotlicommon.

7) Compile the ngx_brotli module dynamically

CD into the Nginx directory and install the build dependancies. Dont forget to change the Nginx version number to your version of Nginx, i.e. nginx-1.25.4 might be nginx-1.25.5.

cd /usr/local/src/nginx-1.25.4 && sudo apt build-dep nginx

Finally, we need to configure the environment with the exact same arguments that are already in your currently installed Nginx. To do that, you have to first check your nginx arguments with the following command:

nginx -V

Should return:

configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --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 --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-http_v3_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-g -O2 -fdebug-prefix-map=/data/builder/debuild/nginx-1.25.4/debian/debuild-base/nginx-1.25.4=. -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie'

If the “--with-compat” argument is not in there, then you must be sure to add them to the next command or your module won’t be compatible with your Nginx. If “--with-compat” is in the above set of arguments, then just continue to copy and paste the above arguments in the next command. Either way, the argument “--with-compatMUST be in the next command. Lastly, since we are compiling Brotli as a dynamic module, we must also include the argument--add-dynamic-module=../ngx_brotli

To summarize, the new arguments look like this:

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

Running my final “configure” COMMAND LOOKS LIKE THIS (adjust according your output of the nginx -V command):

sudo ./configure --add-dynamic-module=../ngx_brotli--with-compat (output of nginx -V goes here)

Be sure to not include the parentheses surrounding “output of nginx -V“. Just put the output of that command after “–with-compat”.

So in my case, since I am compiling for the latest Mainline version of Nginx v1.21.6, my entire configure command, including arguments (with the NEW Additional Arguments first) would be as follows:

sudo ./configure --add-dynamic-module=../ngx_brotli --with-compat --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --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 --user=nginx --group=nginx --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-http_v3_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-g -O2 -fdebug-prefix-map=/data/builder/debuild/nginx-1.25.4/debian/debuild-base/nginx-1.25.4=. -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie'

So to complete this step, just copy and paste the following:

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

before the rest of the output of nginx -V and then hit enter to start configuring! Don’t forget to check for an already existing --with-compat argument in your nginx -V output before you paste the above line.

8) Build the Brotli module!

cd /usr/local/src/nginx-1.25.4/ && sudo make modules

Then copy your newly created module to the Nginx modules directory.

cp objs/*.so /etc/nginx/modules/

9) – (Recommended) – Copy the pagespeed module to your production server

If you built this module on an alternate copy of ubuntu rather than your main production server (which you should have), then you should copy your newly created Nginx Brotli module to a usb stick from your development server, and then from your usb stick to your production server.

First insert your ext4 or dos formatted usb stick into your development server. Then make a mount directory for it.

sudo mkdir /mnt/usb1

Next, Check your device name for your usb stick

lsblk

It should show up as /dev/sda or /dev/sdb. Mount it (depending on what is shows up as in lsblk):

sudo mount /dev/sda /mnt/usb1

then copy your module to your mounted usb stick:

sudo cp /usr/local/src/nginx/nginx-1.25.4/objs/*.so /mnt/usb1/

Unmount your usb with sudo umount /dev/sda then insert your usb into your production server, mount it, and copy the .so files to your modules folder in /etc/nginx/modules/.

10) Load the module

sudo nano /etc/nginx/nginx.conf

Then add the following lines to the beginning of the file:

load_module modules/ngx_http_brotli_filter_module.so;
load_module modules/ngx_http_brotli_static_module.so;

Underneath the lines…

user www-data;
worker_processes auto;
pid /run/nginx.pid;
load_module modules/ngx_http_brotli_filter_module.so;
load_module modules/ngx_http_brotli_static_module.so;

Save and quit nano.

11) DONATE! If this tutorial it worked for you (which it should have), you could spread the love back and donate some change to my paypal, bitcoin address, or altcoin addresses.

PAYPAL:

BITCOIN (BTC) ADDRESS:

bc1qxsqy0nl8f2rqsgpzzr8eh3c67vz7kjr2djyku4

BITCOIN CASH (BCH) ADDRESS:

qzdkv8sz8zf57urafd8urhg7jdej6u892v3z088nvr

ETHEREUM (ETH) ADDRESS:

0x8C33CD44a083D605DBb65Ba4eC201f30Af88705c

ZCASH (ZEC) ADDRESS:

t1dxu9KN1pSYNoMNxYMzCNhcHJhGZmwPW9n

MONERO (XMR) ADDRESS:

4A2p4k6vSGviUxoZvwQkAX8VBQE6tQncmZUS5mZ8YS9cZ2BQ4cc2CZXdMVg4vtFoxh3XrXQECWm95Gq2FpyRtvFz2yNZuYy

12) FINISHED! You are all done! Now you have a working Nginx Brotli module for your 64 bit ARM Raspberry Pi 4!