Get Rewarded! We will reward you with up to €50 credit on your account for every tutorial that you write and we publish!

Installing NGINX with Brotli and Gzip compression on Ubuntu

profile picture
Author
Martin Sholev
Published
2019-07-08
Time to read
7 minutes reading time

Introduction

NGINX is an open-source project created by Igor Sysoev and was released back in 2004. NGINX is commonly used for load balancing, reverse proxying and as a web server.

gzip is a lossless data compression utility. When a user visits a website, resources like images, javascript, stylesheets, and others are commonly compressed with gzip.

Brotli is a new compression algorithm, using a pre-defined dictionary with common keywords and phrases on both client and server side. It is supported by all major browsers.

Prerequisites

  • A server running Ubuntu 16.04/18.04/18.10/19.04.
  • Root access
  • Preinstalled NGINX (optional)

Step 1 - Install and Configure NGINX

Step 1.1 - Pre-installation steps

Check Ubuntu version:

root@example-server:~# lsb_release -ds
Ubuntu 18.04.2 LTS

Update operating system’s packages:

apt update && apt upgrade -y

Step 1.2 - Build NGINX from source

NGINX is written in C, so we need to install compiler tools.

apt install -y build-essential git tree

Now download the latest version of NGINX source.

wget https://nginx.org/download/nginx-1.17.0.tar.gz && tar zxvf nginx-1.17.0.tar.gz

In order to compile NGINX from a source, we need to download NGINX dependencies.

PCRE
wget https://ftp.pcre.org/pub/pcre/pcre-8.43.tar.gz && tar xzvf pcre-8.43.tar.gz
Zlib
wget https://www.zlib.net/zlib-1.2.11.tar.gz && tar xzvf zlib-1.2.11.tar.gz
OpenSSL
wget https://www.openssl.org/source/openssl-1.1.1c.tar.gz && tar xzvf openssl-1.1.1c.tar.gz
Brotli
#Before downloading Brotli you can check and this repo: https://github.com/yverry/ngx_brotli.git, both of the repositories are maintained, you can choose which of the repo to use.
git clone https://github.com/eustas/ngx_brotli.git
cd ngx_brotli
git submodule update --init --recursive

Note: In newer versions of Ubuntu, apt update is executed after adding the repository.

add-apt-repository -y ppa:maxmind/ppa
apt update && apt upgrade -y
apt install -y perl libperl-dev libgd3 libgd-dev libgeoip1 libgeoip-dev geoip-bin libxml2 libxml2-dev libxslt1.1 libxslt1-dev

Step 1.3 - Compile NGINX with Brotli

Enter NGINX folder.

cd ~/nginx-1.17.0

Configure NGINX and build it. Build time takes about 5 min, depending on the system configuration.

./configure --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 --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --user=nginx --group=nginx --build=Ubuntu --builddir=nginx-1.17.0 --with-select_module --with-poll_module --with-threads --with-file-aio --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_addition_module --with-http_xslt_module=dynamic --with-http_image_filter_module=dynamic --with-http_geoip_module=dynamic --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_auth_request_module --with-http_random_index_module --with-http_secure_link_module --with-http_degradation_module --with-http_slice_module --with-http_stub_status_module --with-http_perl_module=dynamic --with-perl_modules_path=/usr/share/perl/5.26.1 --with-perl=/usr/bin/perl --http-log-path=/var/log/nginx/access.log --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-mail=dynamic --with-mail_ssl_module --with-stream=dynamic --with-stream_ssl_module --with-stream_realip_module --with-stream_geoip_module=dynamic --with-stream_ssl_preread_module --with-compat --with-pcre=../pcre-8.43 --with-pcre-jit --with-zlib=../zlib-1.2.11 --with-openssl=../openssl-1.1.1c --with-openssl-opt=no-nextprotoneg --with-debug --add-module=../ngx_brotli --sbin-path=/usr/sbin/nginx

make && make install

After building NGINX, we should create a symlink with the new modules.

ln -s /usr/lib/nginx/modules /etc/nginx/modules-enabled

Check the NGINX version and the parameters.

nginx -V

Output:

nginx version: nginx/1.17.0 (Ubuntu)
built by gcc 8.3.0 (Ubuntu 8.3.0-6ubuntu1)
built with OpenSSL 1.1.1c  28 May 2019
TLS SNI support enabled
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 --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --user=nginx --group=nginx --build=Ubuntu --builddir=nginx-1.17.0 --with-select_module --with-poll_module --with-threads --with-file-aio --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_addition_module --with-http_xslt_module=dynamic --with-http_image_filter_module=dynamic --with-http_geoip_module=dynamic --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_auth_request_module --with-http_random_index_module --with-http_secure_link_module --with-http_degradation_module --with-http_slice_module --with-http_stub_status_module --with-http_perl_module=dynamic --with-perl_modules_path=/usr/share/perl/5.26.1 --with-perl=/usr/bin/perl --http-log-path=/var/log/nginx/access.log --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-mail=dynamic --with-mail_ssl_module --with-stream=dynamic --with-stream_ssl_module --with-stream_realip_module --with-stream_geoip_module=dynamic --with-stream_ssl_preread_module --with-compat --with-pcre=../pcre-8.43 --with-pcre-jit --with-zlib=../zlib-1.2.11 --with-openssl=../openssl-1.1.1c --with-openssl-opt=no-nextprotoneg --with-debug --add-module=../ngx_brotli --sbin-path=/usr/sbin/nginx

Step 1.4 - Create a user and group

User is created with no home directory and with disabled login and password.

adduser --system --home /nonexistent --shell /bin/false --no-create-home --disabled-login --disabled-password --gecos "nginx user" --group nginx

Check NGINX for any errors:

service nginx configtest

OR

nginx -t

On fresh Ubuntu installation you will see this error:

nginx: [emerg] mkdir() "/var/cache/nginx/client_temp" failed (2: No such file or directory)

Create NGINX cache directories, default directories and set permissions.

mkdir /var/cache/nginx/client_temp
mkdir /var/cache/nginx/fastcgi_temp
mkdir /var/cache/nginx/proxy_temp
mkdir /var/cache/nginx/scgi_temp
mkdir /var/cache/nginx/uwsgi_temp

chmod 700 /var/cache/nginx/*
chown nginx:root /var/cache/nginx/*

mkdir /etc/nginx/conf.d
mkdir /etc/nginx/snippets
mkdir /etc/nginx/sites-available
mkdir /etc/nginx/sites-enabled

chmod 640 /var/log/nginx/*
chown nginx:root /var/log/nginx/access.log /var/log/nginx/error.log

Re-check for errors.

nginx -t

OR

service nginx configtest

Step 1.5 Enable NGINX to start on boot

First, create a systemd file.

nano /etc/systemd/system/nginx.service

Copy and paste the whole content:

[Unit]
Description=Nginx - high performance web server
Documentation=https://nginx.org/en/docs/
After=network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target

[Service]
Type=forking
PIDFile=/var/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t -c /etc/nginx/nginx.conf
ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID

[Install]
WantedBy=multi-user.target

Enable the service so it will start on boot.

systemctl enable nginx.service
systemctl start nginx.service

Afterward, your web server is installed.

To check if NGINX is running, you can visit your IP address via the browser.

Open in a web browser:

http://server_domain_name_or_IP/

How To Find Your Server's Public IP Address

If you don't know what your server's public IP address is, there are many ways to find out your public IP address.

From the command line, you can use the ip tools to get your address by typing this:

ip addr show dev eth0 | grep "inet" | awk '{ print $2 }'

Step 2 - Configure NGINX to use Brotli and Gzip

Gzip is used for browsers that don't support Brotli.

Now, we have all of the required components installed.

Edit the NGINX configuration file and add the following lines to NGINX:

nano /etc/nginx/nginx.conf

Currently, with the comments removed, the NGINX http block looks like this:

http {
        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 65;
        types_hash_max_size 2048;

        include /etc/nginx/mime.types;
        default_type application/octet-stream;

        ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
        ssl_prefer_server_ciphers on;

        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;

        gzip on;

        include /etc/nginx/conf.d/*.conf;
        include /etc/nginx/sites-enabled/*;
}

Find where gzip on; is and add the following configuration:

http {
        ....
        gzip on;

        # Compression level (1-9).
        gzip_comp_level 5;

        # Don't compress anything that's already small
        gzip_min_length 256;

        # Compress data even for clients that are connecting to us via proxies
        gzip_proxied any;

        # Tell proxies to cache both the gzipped and regular version of a resource
        # whenever the client's Accept-Encoding capabilities header varies;
        gzip_vary on;

        # Compress all output labeled with one of the following MIME-types.
        gzip_types
          application/atom+xml
          application/geo+json
          application/javascript
          application/json
          application/ld+json
          application/manifest+json
          application/rdf+xml
          application/rss+xml
          application/vnd.ms-fontobject
          application/wasm
          application/x-web-app-manifest+json
          application/xhtml+xml
          application/xml
          font/otf
          image/bmp
          image/svg+xml
          text/cache-manifest
          text/calendar
          text/css
          text/javascript
          text/markdown
          text/plain
          text/vcard
          text/vnd.rim.location.xloc
          text/vtt
          text/x-component
          text/x-cross-domain-policy;


        #Brotli documentation https://github.com/eustas/ngx_brotli#configuration-directives
        brotli on;

        #Because brotli_static is like gzip_static before it, is only for files served via nginx - it will only detect .br files when served via the filesystem
        brotli_static on;

        # For static files, we gonna use 11, but if there is dynamic content we should use 4(smaller response and less time to compress)        
        brotli_comp_level 11;

        #Brotli is used only for some file types, because files like jpeg, png,mp4 are already compressed, if we use Brotli on jpeg/png, the jpeg/png is already compressed, and it will get bigger rather than smaller.
        brotli_types
         application/atom+xml
         application/geo+json
         application/javascript
         application/json
         application/ld+json
         application/manifest+json
         application/rdf+xml
         application/rss+xml
         application/vnd.ms-fontobject
         application/wasm
         application/x-font-opentype
         application/x-font-truetype
         application/x-font-ttf
         font/eot
         font/opentype
         font/otf
         image/bmp
         image/svg+xml
         image/vnd.microsoft.icon
         image/x-icon
         image/x-win-bitmap
         text/cache-manifest
         text/css
         text/javascript
         text/markdown
         text/plain
         text/x-component
         text/x-cross-domain-policy
         text/xml
         application/x-javascript
         application/x-web-app-manifest+json
         application/xhtml+xml
         application/xml
         application/xml+rss;
        ....


}

Save and close the file.

Restart NGINX to make the necessary changes:

service nginx restart

Conclusion

If you have followed the above steps successfully, you should now have NGINX installed on your server with Brotli and Gzip compression enabled. You are now able to upload your sites files to the /var/www/html directory and make a test with the new compression algorithms.

License: MIT
Want to contribute?

Get Rewarded: Get up to €50 in credit! Be a part of the community and contribute. Do it for the money. Do it for the bragging rights. And do it to teach others!

Report Issue
Try Hetzner Cloud

Get 20€ free credit!

Valid until: 31 December 2024 Valid for: 3 months and only for new customers
Get started
Want to contribute?

Get Rewarded: Get up to €50 credit on your account for every tutorial you write and we publish!

Find out more