HTTP/3 & QUIC

Experiment with HTTP3 using NGINX and Quiche-Ubuntu – HTTP3 is the third and upcoming major version of the Hypertext Transfer Protocol used to exchange information on the World Wide Web, alongside HTTP/1.1 and HTTP/2

Time needed: 45 minutes.

How to Build NGINX with HTTP/3 & QUIC Support

  1. Install & Update Ubuntu

    Install Ubuntu server and update to the latest patch release

  2. Download NGINX & QUIC source code

    Get NGINX distribution & QUIC from NGINX official Site

  3. Install Development Tools

    Need to install development tools required to build NGINX

  4. Install BoringSSL

    Download & build boring SSL

  5. Add additional Modules to NGINX

    Download PageSpeed & Brotli modules (Optional)

  6. Modify NGINX rules

    Modify NGINX rules to add HTTP/3, QUIC. Brotli & PageSpeed

  7. Build NGINX

    Build NGINX with HTTP/3, QUIC, Brotli & PageSpeed Support

  8. Install NGINX

    Install NGINX on Ubuntu Server

  9. Configure NGINX Web Server with SSL

    Configure nginx.conf & server block

Install Ubuntu Server

Install Ubuntu server & add Nginx Repository. Please follow steps to modify “/etc/apt/sources/list” & Repository to Ubuntu distribution

nano /etc/apt/sources.list

Add below lines to end of the list

deb [arch=amd64] https://nginx.org/packages/mainline/ubuntu focal nginx
deb-src https://nginx.org/packages/mainline/ubuntu focal nginx
sudo apt-get update
sudo apt-get upgrade
  • Ubuntu 20.10: groovy
  • Ubuntu 20.04.1 LTS: focal
  • Ubuntu 18.04.5 LTS: bionic
  • Ubuntu 16.04.7 LTS: xenial
  • Ubuntu 14.04.6 LTS: trusty
  • Ubuntu 12.04.5 LTS: precise

Based on your Ubuntu version please change code name according to above list. After repository change we need to add Nginx keys to the Ubuntu. Execute below Commands to add keys

sudo wget https://nginx.org/keys/nginx_signing.key
sudo apt-key add nginx_signing.key
sudo apt-get update
sudo apt-get upgrade

Download NGINX & QUIC source code

Next we need to download Nginx source code from Nginx official distribution & build dependencies.

sudo apt-get build-dep nginx
sudo apt-get source nginx

After executing code above, it will create a folder named nginx_XXXXX. XXXXX and it is the version number of Nginx.

Since we have now the NGINX source code, what we need to do now is to replace the code with NGINX quic. But before that, we have to install mercurial as this is needed to compile the NGINX.

sudo apt-get install mercurial

Then we will clone the latest NGINX repo from https://hg.nginx.org/nginx-quic.

cd ~/
hg clone -b quic https://hg.nginx.org/nginx-quic

Now we need to overwrite all content of our nginx-quic directory to the Nginx source code folder.

rsync -r nginx-quic/ nginx-1.21.0

Install Development Tools

Now we need to install other development tools require to build Nginx. Please execute below commands to install required dev tools.

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install dpkg-dev
sudo apt-get install uuid-dev
sudo apt-get install cmake
sudo apt-get install mercurial
sudo apt-get install golang
sudo apt-get install libunwind-dev
sudo apt-get install unzip

Next we are going to download BoringSSL, Brotli & PageSpeed modules. All modules should under /debian/modules directory.

First we need to create /debian/modules folder. Make sure to change “nginx-1.21.0” according to your version.

mkdir ~/nginx-1.21.0/debian/modules

We can now pull a copy of BoringSSL (Google) from the official repo Github page.

cd ~/nginx-1.21.0/debian/modules
git clone https://github.com/google/boringssl
cd boringssl/
mkdir build
cd build
cmake ../
make -j 8

Add additional Modules to NGINX

So we are done with BoringSSL & next we need to download & extract additional modules to the /modules directory.

Change to the modules directory and download PageSpeed module from Google Git.

PageSpeed

cd ~/nginx-1.21.0/debian/modules
wget https://github.com/apache/incubator-pagespeed-ngx/archive/v1.13.35.2-stable.zip
unzip v1.13.35.2-stable.zip
sudo mv incubator-pagespeed-ngx-1.13.35.2-stable ngx_pagespeed

Then go inside to the ngx_pagespeed folder, we need to add the PSOL libraries for pagespeed.

cd ngx_pagespeed
sudo wget https://dl.google.com/dl/page-speed/psol/1.13.35.2-x64.tar.gz
sudo tar -xzvf 1.13.35.2-x64.tar.gz

Brotli

For Brotli, we have just to download the repository from Github to the debian/modules folder.

cd ~/nginx-1.21.0/debian/modules
git clone --recursive https://github.com/google/ngx_brotli

Modify NGINX rules

Hooray, we are done with all dev tools and libraries to build Nginx with HTTP/3, QUIC, Brotli & Pagespeed support

Adding BoringSSL and HTTP/3 to NGINX

Now we need to modify Nginx rules file to add BoringSSL & HTTP/3 support & qualifiers error of BoringSSL. Please edit rule file according to below instructions.

nano ~/nginx-1.21.0/debian/rules

You can see two lines starts with config.env.nginx and config.env.nginx_debug. Make sure to add below code to both of the lines end of the ssl_preread_module

--with-http_v3_module --with-http_quic_module --with-stream_quic_module 

Add below to both lines to ignore qualifier issue of BoringSSL

-Wno-ignored-qualifiers

Example : CFLAGS=”-Wno-ignored-qualifiers”

Next we have to add the BoringSSL module to –with-cc-opt and –with-ld-opt with the following values. You need to replace the existing option at the end of the config, or else you’ll get an error saying, “./auto/configure: error: certain modules require OpenSSL QUIC support“.

--with-cc-opt="-I../modules/boringssl/include $(CFLAGS)" --with-ld-opt="-L../modules/boringssl/build/ssl -L../modules/boringssl/build/crypto $(LDFLAGS)"

You must remove –with-cc-opt & –with-ld-opt completely from existing rule file & replace with above one.

Adding PageSpeed and Brotli to NGINX

To add PageSpeed and Brotli to NGINX, similar to adding BoringSSL and http/3 on our NGINX, we have to add it on the debian/rules compile configuration.

cd ~/
nano ~/nginx-1.21.0/debian/rules

Same as previous, you may see two lines starts with config.env.nginx and config.env.nginx_debug. Make sure to add below code to both of the lines end of the --sbin-path=/usr/sbin/nginx

--add-module="$(CURDIR)/debian/modules/ngx_pagespeed" --add-module="$(CURDIR)/debian/modules/ngx_brotli" 

Compiling NGINX QUIC

Finally you are ready to compile Nginx with HTTP/3, QUIC, Brotli & PageSpeed support. First yo need to change changelog according to your build information.

nano ~/nginx-1.21.0/debian/changelog

Add below lines to of the change file and change according to your preferences.

nginx (nginx_1.21.0.1~bionic+pagespeed+brotli+http3+quic) bionic; urgency=low

  * nginx_1.21.0.1

 -- YOUR_NAME <your_name@domain.com>  Sat, 10 Jul 2021 16:02:03 +0300

After that, we can compile NGINX.

cd ~/nginx-1.21.0
sudo dpkg-buildpackage -b

Once you done with the build process please install newly build Ngix package using below command

sudo dpkg -i nginx_1.21.0.1~bionic+pagespeed+brotli_amd64.deb

Check your Nginx configuration using below command.

nginx -t

Configure NGINX Web Server with SSL

We need to remove default .conf file and replace nginx.conf file with below config.

rm /etc/nginx/conf.d/default.conf
nano /etc/nginx/nginx.conf

Remove all content of nginx.conf and replace with;

user www-data;
worker_processes auto;
include /etc/nginx/modules-enabled/*.conf;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


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


    ##
    # PageSpeed Settings
    ##

    pagespeed on;
    pagespeed FileCachePath /var/ngx_pagespeed_cache;
    
    ##
    # Access/Error Log Settings
    ##

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

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

    ##
    # Http Core Module Settings
    ##

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

    ##
    # Gzip Settings
    ##

    pagespeed FetchWithGzip off;
    pagespeed HttpCacheCompressionLevel 0;
    #gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/x-font-ttf application/x-web-app-manifest+json application/xml+rss text/javascript image/svg+xml image/x-icon;

    ##
    # Brotli Settings
    ##

    brotli on;
    brotli_comp_level 6;
    brotli_static on;
    brotli_types application/octec-stream text/xml image/svg+xml application/x-font-ttf image/vnd.microsoft.icon application/x-font-opentype application/json font/eot application/vnd.ms-fontobject application/javascript font/otf application/xml application/xhtml+xml text/javascript application/x-javascript text/plain application/x-font-trutype application/xml+rss image/x-icon font/opentype text/css image/x-win-bitmap application/x-web-app-manifest+json;
    
    ##
    # SSL Configuration
    ##

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


    ##
    # FastCGI Cache Settings
    ##

    fastcgi_cache_path /etc/nginx-cache levels=1:2 keys_zone=phpcache:100m inactive=60m;
    fastcgi_cache_key "$scheme$request_method$host$request_uri";
    fastcgi_ignore_headers Cache-Control Expires;

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

    
}

Create web root directory & change permission to www-data (Nginx user group)

mkdir /var/www
sudo chown -R www-data:www-data /var/www

Now we need to make the server block directory according to above config “include /etc/nginx/sites-enabled/*;

mkdir /etc/nginx/sites-available
ln -s /etc/nginx/sites-available /etc/nginx/sites-enabled

Then let’s create a configuration for our first HTTP/3 website.

nano /etc/nginx/sites-available/example.com.conf

Add below code to the above file

server{
    listen 80;
    index index.html index.nginx-debian.html;
    server_name yourdomain.com www.yourdomain.com

    root /var/www/yourdomain.com;
}

Now we need to install SSL from free SSL authority to enable HTTP/3 & QUIC support.

Ready to install letsencrypt free SSL cert using certbot.

sudo add-apt-repository ppa:certbot/certbot

Then, create an SSL for your website. Replace example.com with your domain

sudo certbot --nginx -d example.com -d www.example.com

Certbot will automatically add SSL config to above file and finally we need to enable HTTP/3 & QUIC. Modify your config according to below code.

server {
    listen 443 ssl;              # TCP listener for HTTP/1.1
    listen 443 http3 reuseport;  # UDP listener for QUIC+HTTP/3

    ssl_protocols       TLSv1.3; # QUIC requires TLS 1.3
    ssl_certificate     ssl/www.example.com.crt;
    ssl_certificate_key ssl/www.example.com.key;

    add_header Alt-Svc 'h3=":443"';   # Advertise that HTTP/3 is available
    add_header QUIC-Status $quic;     # Sent when QUIC was used
}

For more information please visit official Nginx QUIC and HTTP/3 page

Introducing a Technology Preview of NGINX Support for QUIC and HTTP/3

Restart Nginx Server

sudo service nginx restart

Check your website and you should now see h3-29 on the protocol header when checking it on Web browser’s Developer tools. You can also check your website at the following http/3 checker tools:

If you need OCSP support please visit Github issue page and try yourself to enable.

Patch that enables OCSP stapling for nginx with **BoringSSL**

Thanks you for your time and please comment if you have any concerns.

Related Articles : How To Install Nginx Web Server on Ubuntu 18.04

Join the Conversation

1 Comment

Leave a comment

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