How to Install HTTP/3 quic on Nginx Server for Ubuntu

Currently, there are three protocol used in today’s web browser, the first one is the http/1, followed with http/2 and the upcoming protocol, the http/3. The latter is quite promising as it improves the http/2 more because it uses the UDP instead of TCP to load your webpages and assets. It also fixes some problems on previous protocols.

Looking for resources on installing http/3 in the internet is either outdated or end up with errors when installing additional module, especially to those who are not familiar with repo compilation.

Table of Content

  1. NGINX Source Code
  2. Installing NGINX quic
  3. Installing BoringSSL
  4. Adding BoringSSL and HTTP/3 to NGINX Source
  5. Installing other modules
    1. Pagespeed
    2. Brotli
    3. Adding Pagespeed and Brotli to NGINX
  6. Compiling NGINX quic
  7. Setting up NGINX quic

The only problem with implementing the current status of http/3 into your server is, there are still many bugs like random 404 errors on some content of your website (jpeg, fonts, script files).

NGINX Source Code

Looking for source code compiler that allows you to create a deb package for the NGINX quic is hard and you need to manually create it. In this guide, we will teach you how to create a deb package installer for your NGINX quic using the NGINX source code which has similar file structure.

So first, login to your SSH server and make sure you’re at the User’s directory.

cd ~/

Make sure your server is up to date with the latest patches.

sudo apt-get update
sudo apt-get upgrade

Now, we have to install the dev tool for us to compile the NGINX source.

sudo apt-get install dpkg-dev
sudo apt-get install uuid-dev

We need to create a key signature so we can download repo from NGINX packages.

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

After that, we have to edit the /etc/apt/sources/list and add the NGINX repositories.

vim /etc/apt/sources.list

At the bottom, add the following lines. The example below is for Ubuntu 18.04.5 LTS.

deb https://nginx.org/packages/mainline/ubuntu bionic nginx
deb-src https://nginx.org/packages/mainline/ubuntu bionic nginx

If you’re using other version of Ubuntu, just replace bionic with the following:

  • 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

In case you get an error that says “Skipping acquire of configured file ‘nginx/binary-i386/Packages’ as repository ‘https://nginx.org/packages/mainline/ubuntu bionic InRelease’ doesn’t support architecture ‘i386”, you just need to add [arch-amd64] to the deb line.

deb [arch=amd64] https://nginx.org/packages/mainline/ubuntu bionic nginx
deb-src https://nginx.org/packages/mainline/ubuntu bionic nginx

Next is we have to update so that we can get the NGINX repo.

sudo apt-get update
sudo apt-get upgrade

We can now then build dependencies for NGINX and pull the source code to our user’s directory.

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

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

Installing NGINX quic

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

Let’s overwrite all content of our nginx-quic directory to the nginx source code folder.

rsync -r nginx-quic/ nginx-1.19.6

Installing BoringSSL

Last thing we need to do is to add the BoringSSL as our module for our SSL, it is a forked from OpenSSL from Google that add a quic support. Currently, it is only the available OpenSSL that we can use, if we find one in the future, we will also add them on this guide.

But first, we have to install these dependencies to compile BoringSSL.

sudo apt-get install golang
sudo apt-get install libunwind-dev

We can now pull a copy of boringssl from the official repo Github page.

cd ~/
git clone https://github.com/google/boringssl

Then, let’s compile BoringSSL with cmake and make.

cd boringssl/
mkdir build
cd build
cmake ../
make -j 8

Adding BoringSSL and HTTP/3 to NGINX

After that, we have to add important configuration for our NGINX quic, we can add inside the rules file at NGINX source code folder.

vim  ~/nginx-1.19.6/debian/rules

Then add the following lines that says config.env.nginx and config.env.nginx_debug, you can find it at line 41 and line 46. Then add the following after –with-stream_ssl_preread_module:

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

Then we need to add -Wno-ignored-qualifiers at the CFLAGS = “” to disable compiler from throwing qualifiers error. It should be:

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 bottom of the config, or else you’ll get an saying, “./auto/configure: error: certain modules require OpenSSL QUIC support. You can either do not enable the modules, or install the OpenSSL library into the system, or build the OpenSSL library statically from the source with nginx by using –with-openssl= option.”. See the final rules for reference.

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

The final rules should look like below:

config.status.nginx: config.env.nginx
    cd $(BUILDDIR_nginx) && \
    CFLAGS="-Wno-ignored-qualifiers" ./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 --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-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-http_v3_module --with-http_quic_module --with-stream_quic_module --with-cc-opt="-I../modules/boringssl/include $(CFLAGS)" --with-ld-opt="-L../modules/boringssl/build/ssl -L../modules/boringssl/build/crypto $(LDFLAGS)"

Make sure you do the same changes on both line config.env.nginx and config.env.nginx_debug.

Installing other modules

If you need to add important optimization module for your http/3 server like Pagespeed and Brotli, you can also follow the quick guide below. If you need detailed guide for this, you can check our separate post.

This step requires unzip, if you haven’t have this yet on your server, you can install it with this command:

sudo apt-get install unzip

Once done adding the unzip on your server, you can now proceed on installing Pagespeed and Brotli

Pagespeed

For adding pagespeed, we have to get the official Github repository and unzip it on the debian/modules directory.

mkdir ~/nginx-1.19.6/debian/modules
cd ~/nginx-1.19.6/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 inside ngx_pagespeed folder, we have to add the libraries for pagespeed, the PSOL.

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

Our repository for Pagespeed is done.

Brotli

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

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

Brotli file is now added, the last thing we have to do is to include it on the NGINX configuration.

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.

vim  ~/nginx-1.19.6/debian/rules

At the ./configure of config.env.nginx and config.env.nginx_debug, add the following lines right after --sbin-path=/usr/sbin/nginx:

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

Your final configuration rules should look like below.

config.status.nginx: config.env.nginx
    cd $(BUILDDIR_nginx) && \
    CFLAGS="-Wno-ignored-qualifiers" ./configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --add-module="$(CURDIR)/debian/modules/ngx_pagespeed" --add-module="$(CURDIR)/debian/modules/ngx_brotli" --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-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-http_v3_module --with-http_quic_module --with-stream_quic_module --with-cc-opt="-I../modules/boringssl/include $(CFLAGS)" --with-ld-opt="-L../modules/boringssl/build/ssl -L../modules/boringssl/build/crypto $(LDFLAGS)"

Everything is now set for other module, we can now proceed on compiling NGINX.

Compiling NGINX quic

Before we compile, we have to add some finishing touch so we distinguish we are using mod build for NGINX.

First, we have to edit the changelog file.

vim ~/nginx-1.19.6/debian/changelog

Then add +pagespeed+brotli+http3+quic on the first line.

nginx (1.19.6-1~bionic+pagespeed+brotli+http3+quic) bionic; urgency=low

  * 1.19.6-1

 -- YOUR_NAME <your_name@domain.com>  Tue, 24 Nov 2020 16:02:03 +0300

After that, we can now compile our NGINX.

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

Once it started compiling, it will asked if you want to include PSOL debug version, just type yes. After it completes, it will create the deb file at the parent directory. You can then use those to install nginx.

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

From here we can now check if our new NGINX quic is now running.

nginx -t

Setting up Nginx quic

The last thing we need to do in order for our HTTP/3, quic and other modules to run smoothly on our server is to make few changes to its configuration files and file system needed.

First, we have to fixed the default configuration of NGINX and apply the server block directory. We to remove the default configuration and have to edit the nginx.conf.

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

Then replace all content with the following:

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/*;

    
}

Then let’s setup our www directory.

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

Now we can now make the server block directory.

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

Then let’s create a configuration for our website.

vim /etc/nginx/sites-available/yourdomain.com

For now, let’s just add basic configuration.

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

    root /var/www/yourdomain.com;
}

Then make sure to add SSL on your website, by running certbot. If you don’t how certbot, you can do the following:

sudo apt-get update
sudo apt-get install python3-certbot-nginx

If you’re using Ubuntu below 20.04.2 LTS, just add the repository below and repeat above command:

sudo add-apt-repository ppa:certbot/certbot

Then, create an SSL for your website.

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

After that, certbot will edit your configuration file and add the SSL, we can now edit the file and add the following:

server{
    listen 443 http3 quic reuseport;
    listen 443 ssl http2;

    quic_retry on;
    ssl_early_data on;

    http3_max_field_size 5000;
    http3_max_table_capacity 50;
    http3_max_blocked_streams 30;
    http3_max_concurrent_pushes 30;
    http3_push 10;
    http3_push_preload on;

    add_header alt-svc '$quic=":443"; ma=3600';

    index index.html index.nginx-debian.html;
    server_name yourdomain.com www.yourdomain.com

    root /var/www/yourdomain.com;

    ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; 

}
server{
    if ($host = http3.codefaq.org) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    listen 80;

    server_name yourdomain.com;
    return 404; # managed by Certbot


}

The add_header alt-svc is need to make sure that web browser will know that your server supported http/3. Other settings also needs to setup in order for the NGINX quic not to produce 404 error on your file assets, which are the following:

  • http3_max_field_size 5000;
  • http3_max_table_capacity 50;
  • http3_max_blocked_streams 30;
  • http3_max_concurrent_pushes 30;
  • http3_push 10;
  • http3_push_preload on;

I’ll try to add some explanation on this later on and check the source code as for now, there are no explanation about these on the documentation. But after implementing above configuration, the 404 error on the website was fixed.

After the changes don’t forget to restart the nginx.

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:

OCSP is disabled on BoringSSL which uses quic

If you are implementing OCSP on your NGINX server, unfortunately, the OCSP was removed from BoringSSL and the only way to bring it back is using a patch (https://github.com/kn007/patch/issues/4) from a third party developer. But it only supports SSL stapling file which needs an additional task like Cron job to produce this file.

You’ll get the following warning when you have ssl_stapling on your nginx conf.

nginx: [warn] "ssl_stapling" ignored, not supported

If you’re receiving the following errors, just follow the step above.

./auto/configure: error: certain modules require OpenSSL QUIC support. You can either do not enable the modules, or install the OpenSSL library into the system, or build the OpenSSL library statically from the source with nginx by using --with-openssl=<path> option.

2 Comments

  • Lemonol
    Posted February 19, 2021 6:22 am 0Likes

    I am getting the error “./auto/configure: error: certain modules require OpenSSL QUIC support. You can either do not enable the modules, or install the OpenSSL library into the system, or build the OpenSSL library statically from the source with nginx by using –with-openssl= option.”

    But I’m not sure which “step” to follow above. You don’t clarify. I’m stuck now thanks.

Leave a Comment

trabzon escort yalova escort Samsun escort izmit escort nazilli escort