Introduction

Nginx is a popular web server and load-balancing tool with broad usage in the technology industry. Its appeal ranges from solo developers handling personal tasks to big corporations launching essential applications. The technology's effectiveness, ability to grow, and a strong set of features have made it a top pick for both young and experienced professionals in the software development industry.

You've probably already encountered a site hosted with nginx (PS: This article is also being served via nginx). Nginx is found in the repos of most of the Linux distributions and can be easily installed and configured. You can get started within minutes of installing the nginx binary in your system.

In its open-source version, Nginx is widely available and used. Nevertheless, this only showcases some of its potential. A more extensive and full-featured version called Nginx Plus is available.

Nginx Plus is the premium version provided by F5, the company that owns the trademarks for Nginx. F5 is a well-known company that focuses on network hardware and software technologies, offering a variety of products including firewalls, load balancers, Nginx web servers, and software-based security solutions.

The enhanced version offers features like virtual host visualization, HTTP/3 support, and Brotli compression that are not found in the free version. Although some features can be added to the community version with extra setup, it usually demands a lot of time and knowledge.

In many scenarios, the free Nginx version is usually satisfactory. Nevertheless, groups that have particular needs that match Nginx Plus's features might see benefits in the premium package. Before thinking about investing in Nginx Plus, it is recommended to thoroughly evaluate your requirements.

In this blog article, I would like to share with you the way I added the features I wanted in the community version of nginx (mainly http3 support).

So without further ado, let's get started.

Compilation

First of all, let's look at the extra tools that we would like to add to our nginx install. Here are a few of those that I plan on adding to my demonstration.

  • http3 protocol
    • The HTTP3 protocol is the next generation of the http protocol after http2. It offers faster data transfer more securely.
  • brotli compression
    • Just like gzip but better, better compression will enable us to save bandwidth and increase load speeds
  • virtual host visualization
    • Just a vanity feature, useful to see all virtual hosts visualized in one place and make decisions accordingly (like traffic filtering, host blocking, etc)

Build Machine

Next, we'll also need to consider our build machine, it needs to have all the required tools for building nginx and also needs to have a capable CPU (otherwise we're in for a long wait time)

I'll be using a 2 VCPU 4 GB RAM instance with Debian 12 as the distro.

Use the command below to install the build essentials:

sudo apt install -y build-essential libpcre3 libpcre3-dev zlib1g zlib1g-dev libssl-dev git gcc

Nginx and its modules

To build our own nginx we will need the source code to nginx. I'll use the latest available version of nginx community edition.

git clone https://github.com/nginx/nginx.git

We now have a repository, let's now download the modules for the features we require.

Brotli

git clone https://github.com/google/ngx_brotli.git

Quiche and BoringSSL for HTTP/3

Clone the repository and build the modules using the commands below

Quiche

git clone --recursive https://github.com/cloudflare/quiche

Boring SSL

git clone https://boringssl.googlesource.com/boringssl

Inside the boringssl directory run the commands below to build the module.

mkdir build && cd build
cmake ..
make

Now we'll need to configure nginx to use these modules. Go inside the nginx directory and run the following command to configure the nginx build.

./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 \
    --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-cc-opt='-I /home/build-server/boringssl/include' \
    --with-ld-opt='-L /home/build-server/boringssl/build/ssl -L /home/build-server/boringssl/build/crypto' \
    --with-http_v2_module \
    --with-http_v3_module \
    --with-stream_quic_module \
    --with-http_ssl_module \
    --with-http_v3_module \
    --with-stream_quic_module \
    --with-http_ssl_module \
    --add-module=/home/build-server/ngx_brotli \
    --add-module=/home/build-server/quiche

Now, to compile and install nginx run the command below

make && make install
💡
Using the -j flag in the make command will make the builds multi-threaded which will make the builds faster but will require a lot of CPU time and may end up causing the system to hang (due to a lack of resources).
💡
If you encounter permissions errors then prefix the make install command with sudo eg: sudo make install

Now, we have successfully built our own nginx binary with the http3 and brotli support. The nginx binary is installed at /usr/sbin/nginx and modules will be available at /usr/lib/nginx/modules

Testing new features in nginx

Now that we have a nginx installation with http3 and brotli we can host a website and have a client device test it out for us.

For a simple test site, use the configs provided below.

http {
    
    brotli on;
    brotli_comp_level 6;
    brotli_static on;
    brotli_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
    
    server {
        listen 443 http3 reuseport;
        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_certificate /etc/nginx/self-signed/cert.pem;
        ssl_certificate_key /etc/nginx/self-signed/private-key.pem;

        location / {
          try_files index.html;
        }
    }
}

Once the configuration files are in place, test the nginx config and push changes.

nginx -t
nginx -s reload

Conclusion

In this article, we learned to compile our own nginx binary with http3, virtual hosts visualization and brotli. More features can be added as there is a big community around nginx and its modules so you can find the features that you are looking for.

Thank You for reading, please comment below if you have any queries.