Table of Contents
Was this article helpful?

0  out of  1 found this helpful

Try Vultr Today with

$50 Free on Us!

Want to contribute?

You could earn up to $600 by adding new articles.

How to Enable TLS 1.3 in Nginx on Debian 9

Last Updated: Fri, Aug 16, 2019
Linux Guides Security Web Servers
Archived content

This article is outdated and may not work correctly for current operating systems or software.


TLS 1.3 is a version of the Transport Layer Security (TLS) protocol published in 2018 as a proposed standard in RFC 8446. It offers security and performance improvements over its predecessors.

This guide explains how to enable TLS 1.3 using the Nginx web server on Debian 9.


  • Nginx version 1.13.0 or greater.

  • OpenSSL version 1.1.1 or greater.

  • Vultr Cloud Compute (VC2) instance running Debian 9 x64 (stretch).

  • A valid domain name and properly configured A/AAAA/CNAME DNS records for your domain.

  • A valid TLS certificate. We will get one from Let's Encrypt.

Before you begin

Check the Debian version.

lsb_release -ds

# Debian GNU/Linux 9.9 (stretch)

Ensure that your system is up to date.

apt update && apt upgrade -y

Install the necessary packages.

apt install -y git unzip curl sudo socat build-essential

Create a new non-root user account with sudo access and switch to it.

adduser johndoe --gecos "John Doe"

usermod -aG sudo johndoe

su - johndoe

NOTE: Replace johndoe with your username.

Set up the timezone.

sudo dpkg-reconfigure tzdata

Install the client and obtain a TLS certificate from Let's Encrypt

Download and install

sudo mkdir /etc/letsencrypt

sudo git clone


sudo ./ --install --home /etc/letsencrypt --accountemail

cd ~

source ~/.bashrc

Check the version.

/etc/letsencrypt/ --version

# v2.8.2

Obtain RSA and ECDSA certificates for your domain.

# RSA 2048

sudo /etc/letsencrypt/ --issue --standalone --home /etc/letsencrypt -d --ocsp-must-staple --keylength 2048


sudo /etc/letsencrypt/ --issue --standalone --home /etc/letsencrypt -d --ocsp-must-staple --keylength ec-256

NOTE: Replace with your domain name.

After running the previous commands, your certificates and keys are accessible in the following locations:

  • RSA: /etc/letsencrypt/

  • ECC/ECDSA: /etc/letsencrypt/example.com_ecc

Build Nginx from Source

Nginx added support for TLS 1.3 in version 1.13.0. On most Linux distributions, including Debian 9, Nginx is built with the older OpenSSL version, which does not support TLS 1.3. Consequently, we need our own custom Nginx build linked to the OpenSSL 1.1.1 release, which includes support for TLS 1.3.

Download the latest mainline version of the Nginx source code and extract it.

wget && tar zxvf nginx-1.17.0.tar.gz

Download the OpenSSL 1.1.1c source code and extract it.

# OpenSSL version 1.1.1c

wget && tar xzvf openssl-1.1.1c.tar.gz

Delete all .tar.gz files, as they are not needed anymore.

rm -rf *.tar.gz

Enter the Nginx source directory.

cd ~/nginx-1.17.0

Configure, compile, and install Nginx. For simplicity's sake, we will compile only essential modules that are required for TLS 1.3 to work. If you need a full Nginx build, you can read this Vultr guide about Nginx compilation.

./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/ \

            --lock-path=/var/run/nginx.lock \

            --user=nginx \

            --group=nginx \

            --build=Debian \

            --builddir=nginx-1.17.0 \

            --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-compat \

            --with-http_ssl_module \

            --with-http_v2_module \

            --with-openssl=../openssl-1.1.1c \

            --with-openssl-opt=no-nextprotoneg \

            --without-http_rewrite_module \



sudo make install

Create an Nginx system group and user.

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

Symlink /usr/lib/nginx/modules to /etc/nginx/modules. The latter is a standard place for Nginx modules.

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

Create Nginx cache directories and set the proper permissions.

sudo mkdir -p /var/cache/nginx/client_temp /var/cache/nginx/fastcgi_temp /var/cache/nginx/proxy_temp /var/cache/nginx/scgi_temp /var/cache/nginx/uwsgi_temp

sudo chmod 700 /var/cache/nginx/*

sudo chown nginx:root /var/cache/nginx/*

Check the Nginx version.

sudo nginx -V

# nginx version: nginx/1.17.0 (Debian)

# built by gcc 6.3.0 20170516 (Debian 6.3.0-18+deb9u1)

# built with OpenSSL 1.1.1c  28 May 2019

# TLS SNI support enabled

# configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx . . .

# . . .

Create an Nginx systemd unit file.

sudo vim /etc/systemd/system/nginx.service

Populate the file with the following configuration.


Description=nginx - high performance web server





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


Start and enable Nginx.

sudo systemctl start nginx.service

sudo systemctl enable nginx.service

Create conf.d, sites-available and sites-enabled directories in /etc/nginx.

sudo mkdir /etc/nginx/{conf.d,sites-available,sites-enabled}

Run sudo vim /etc/nginx/nginx.conf and add the following two directives to the end of the file, just before the closing }.

    . . .

    . . .

    include /etc/nginx/conf.d/*.conf;

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


Save the file and exit with :+W+Q.

Configure Nginx for TLS 1.3

Now that we have successfully built Nginx, we are ready to configure it to start using TLS 1.3 on our server.

Run sudo vim /etc/nginx/conf.d/ and populate the file with the following configuration.

server {

  listen 443 ssl http2;

  listen [::]:443 ssl http2;

  # RSA

  ssl_certificate /etc/letsencrypt/;

  ssl_certificate_key /etc/letsencrypt/;


  ssl_certificate /etc/letsencrypt/example.com_ecc/fullchain.cer;

  ssl_certificate_key /etc/letsencrypt/example.com_ecc/;

  ssl_protocols TLSv1.2 TLSv1.3;


  ssl_prefer_server_ciphers on;


Save the file and exit with :+W+Q.

Notice the new TLSv1.3 parameter of the ssl_protocols directive. This parameter is necessary to enable TLS 1.3.

Check the configuration.

sudo nginx -t

Reload Nginx.

sudo systemctl reload nginx.service

To verify TLS 1.3, you can use browser dev tools or SSL Labs service. The screenshots below show Chrome's security tab that indicates that TLS 1.3 is working.

Congratulations! You have successfully enabled TLS 1.3 on your Debian 9 server.

Want to contribute?

You could earn up to $600 by adding new articles.