27th June, 2016 | Tutorials |

How to Setup Nginx with HTTP2 Support on Ubuntu 16.04

Want your very own server? Get our 1GB memory, Xeon V4, 25GB SSD VPS for £10.00 / month.

Get a Cloud Server


Nginx (pronounced "engine x") is a web server. It can act as a reverse proxy server for HTTP, HTTPS, SMTP, POP3, and IMAP protocols, as well as a load balancer and an HTTP cache. Nginx was created by Igor Sysoev in 2002 which runs on UNIX, Linux, BSD variants, OS X, Solaris, AIX, HP-UX, and Windows. NGINX, Inc. was founded in July 2011 by Sysoev to provide commercial products and support for the software.

NGINX is high-performance HTTP server and reverse proxy, as well as an IMAP/POP3 proxy server. NGINX is known for its high performance, stability, rich feature set, simple configuration, and low resource consumption.

NGINX is one of a handful of servers written to address the C10K problem. Unlike traditional servers, NGINX doesn't rely on threads to handle requests. Instead it uses a much more scalable event-driven (asynchronous) architecture. This architecture uses small, but more importantly, predictable amounts of memory under load. Even if you don't expect to handle thousands of simultaneous requests, you can still benefit from NGINX's high-performance and small memory footprint. NGINX scales in all directions: from the smallest Virtual Private Server (VPS) all the way up to large clusters of servers. NGINX is the world's most popular open source web server and load balancer for high-traffic sites, powering over 140 million properties.

HTTP/2 is a replacement for how HTTP is expressed "on the wire." It is not a ground-up rewrite of the protocol; HTTP methods, status codes and semantics are the same, and it should be possible to use the same APIs as HTTP/1.x (possibly with some small additions) to represent the protocol. The focus of the protocol is on performance; specifically, end-user perceived latency, network and server resource usage. One major goal is to allow the use of a single connection from browsers to a Web site. It is based on the SPDY (pronounced speedy) protocol, originally developed by Google. HTTP/2 was developed by the Hypertext Transfer Protocol working group (httpbis, where bis means "second") of the Internet Engineering Task Force.

HTTP/2 is the first new version of HTTP since HTTP 1.1, which was standardized in RFC 2068 in 1997. The Working Group presented HTTP/2 to Internet Engineering Steering Group (IESG) for consideration as a Proposed Standard in December 2014, and IESG approved it to publish as Proposed Standard on February 17, 2015. The HTTP/2 specification was published as RFC 7540 in May 2015. The standardization effort was supported by Chrome, Opera, Firefox, Internet Explorer 11, Safari, Amazon Silk and Edge browsers. Most major browsers added HTTP/2 support by the end of 2015. According to W3Techs, as of April 2016, 7.1% of the top 10 million websites supported HTTP/2.

Differences Between HTTP 1.1 and HTTP/2

The proposed changes do not require any changes to how existing web applications work, but new applications can take advantage of new features for increased speed. HTTP/2 leaves most of HTTP 1.1's high-level syntax, such as methods, status codes, header fields, and URIs, the same. The element that is modified is how the data is framed and transported between the client and the server. Websites that are efficient minimize the number of requests required to render an entire page by minifying (reducing the amount of code and packing smaller pieces of code into bundles, without reducing its ability to function) resources such as images and scripts. Additional performance improvements in the first draft of HTTP/2 (which was a copy of SPDY) come from multiplexing of requests and responses to avoid the head-of-line blocking problem in HTTP 1 (even when HTTP pipelining is used), header compression, and prioritization of requests. HTTP/2 solves below problem because it brings a few fundamental changes:

Even though HTTP/2 does not require encryption, developers of two most popular browsers, Google Chrome and Mozilla Firefox, stated that for the security reasons they will support HTTP/2 only for HTTPS connections. Hence, if you decide to set up servers with HTTP/2 support, you must also secure them with HTTPS.

HTTP2 Features

In this tutorial, we will learn how to install and setup Nginx with HTTP2 support on Ubuntu-16.04.


A server running Ubuntu-16.04 A static IP Address for your server A non-root user account with sudo privilege set up on your server

Install Nginx

Support of the HTTP/2 protocol was introduced in Nginx 1.9.5. Fortunately, the default repository in Ubuntu 16.04 contains a version higher than this, so we don't have to add a third party repository. Before starting, you will need to update your system. You can do this by running the following command:

sudo apt-get update -y sudo apt-get upgrade -y

When you are finished, install Nginx by running the following command:

sudo apt-get install nginx

After the installation process finishes, you can check the version of Nginx by typing:

sudo nginx –v

The output should be similar to the following:

    nginx version: nginx/1.10.0 (Ubuntu)

Changing the Listening Port and Enabling HTTP/2

The first change we will make will be to change the listening port from 80 to 443.

Let's open the configuration file:

sudo nano /etc/nginx/sites-available/default

By default, Nginx is set to listen to port 80, which is the standard HTTP port:

    server {

listen 80 default_server;

listen [::]:80 default_server;

As you can see, we have two different listen variables. The first one is for all IPv4 connections. The second one is for IPv6 connections. We will enable encryption for both.

Modify the listening port to 443, which is used by the HTTPS protocol:

    server {

listen 443 ssl http2 default_server;

listen [::]:443 ssl http2 default_server;

Notice that in addition to ssl, we also added http2 to the line. This variable tells Nginx to use HTTP/2 with supported browsers.

Changing the Server Name

The next line after listen is server_name. Here is where we specify which domain should be associated with the configuration file. By default, server_name is set to _ (underscore), which means the config file is responsible for all incoming requests. Change _ to your actual domain, like this:

sudo nano /etc/nginx/sites-available/default
    server_name server-ip-address;

Save the configuration file, and exit the text editor.

Check the configuration for syntax errors:

sudo nginx -t

If the syntax is error-free, you will see the following output:

    nginx: the configuration file /etc/nginx/nginx.conf syntax is ok

nginx: configuration file /etc/nginx/nginx.conf test is successful

Generate a Self-signed Certificate

TLS/SSL works by using a combination of a public certificate and a private key. The SSL key is kept secret on the server. It is used to encrypt content sent to clients. The SSL certificate is publicly shared with anyone requesting the content. It can be used to decrypt the content signed by the associated SSL key. We can create a self-signed key and certificate pair with OpenSSL in a single command:

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/nginx-selfsigned.key -out /etc/ssl/certs/nginx-selfsigned.crt

The entirety of the prompts will look something like this:

    Generating a 2048 bit RSA private key



writing new private key to '/etc/ssl/private/nginx-selfsigned.key'


You are about to be asked to enter information that will be incorporated

into your certificate request.

What you are about to enter is what is called a Distinguished Name or a DN.

There are quite a few fields but you can leave some blank

For some fields there will be a default value,

If you enter '.', the field will be left blank.


Country Name (2 letter code) [AU]:IN

State or Province Name (full name) [Some-State]:GJ

Locality Name (eg, city) []:AHMEDABAD

Organization Name (eg, company) [Internet Widgits Pty Ltd]:HOSTPRESTO

Organizational Unit Name (eg, section) []:IT

Common Name (e.g. server FQDN or YOUR name) []:HITESH

Email Address []

Fill out the prompts appropriately. The most important line is the one that requests the Common Name (e.g. server FQDN or YOUR name). You need to enter the domain name associated with your server or, more likely, your server's public IP address.

Both of the files you created will be placed in the appropriate subdirectories of the /etc/ssl directory.

While we are using OpenSSL, we should also create a strong Diffie-Hellman group, which is used in negotiating Perfect Forward Secrecy(In cryptography, forward secrecy (FS is a property of secure communication protocols in which compromise of long-term keys does not compromise past session keys.) with clients.

You can do this by typing:

sudo openssl hitesh -out /etc/ssl/certs/hitesh.pem 2048

This may take a few minutes, but when it's done you will have a strong DH group at /etc/ssl/certs/hitesh.pem that we can use in our configuration by entering below command -

cat /etc/ssl/certs/hitesh.pem










Adding the SSL Certificates

Next, you need to configure Nginx for your SSL certificate. Create a directory to store your SSL certificates inside the Nginx configuration directory:

Create a directory to store your SSL certificates inside the Nginx configuration directory:

sudo mkdir /etc/nginx/ssl

Copy your certificate and the private key to this location. We will also rename the files to show which domain they are associated. (It will come in handy in the future, when you will have more than one domain.) You can give any hostname according to your requirement:

sudo cp /etc/ssl/certs/nginx-selfsigned.crt /etc/nginx/ssl/ubuntu.crt sudo cp /etc/ssl/private/nginx-selfsigned.key /etc/nginx/ssl/ubuntu.key

Now, let's open our configuration file once again and configure SSL.

`sudo nano /etc/nginx/sites-available/default

On new lines inside the server block, define the location of your certificates:

    ssl_certificate /etc/nginx/ssl/ubuntu.crt;
    ssl_certificate_key /etc/nginx/ssl/ubuntu.key;

Save the file, and exit the text editor.

Avoiding Old Cipher Suites

HTTP/2 has a huge blacklist of old and insecure ciphers, so we must avoid them. Cipher suites are a bunch of cryptographic algorithms, which describe how the transferring data should be encrypted. We will use a really popular cipher set, whose security was approved by Internet giants like CloudFlare. It does not allow the usage of MD5 encryption (which was known as insecure since 1996, but despite this fact, its use is widespread even to this day). Open the following configuration file:

sudo nano /etc/nginx/nginx.conf

Add this line after ssl_prefer_server_ciphers on;


Increasing Key Exchange Security

By default, Nginx uses a 1028-bit DHE (Ephemeral Diffie-Hellman) key, which is relatively easy to decrypt. To provide maximum security, we should build our own, more secure DHE key.

To do so, issue the following command:

sudo openssl hitesh -out /etc/nginx/ssl/hitesh.pem 2048

The variable after the file path (in our case it is 2048) specifies the length of the key. A key with a 2048-bit length is secure enough and recommended by the Mozilla Foundation, but if you are looking for even more encryption, you can change it to 4096.

The generation process will take about 5 minutes. Once it is complete, open the default Nginx configuration file again:

sudo nano /etc/nginx/sites-available/default

On a new line inside server block, define the location of your custom DHE key:

    ssl_hitesh  /etc/nginx/ssl/hitesh.pem;

Redirecting all HTTP Requests to HTTPS

Since we are interested in serving the content through HTTPS only, we should tell Nginx what it should do if the server receives an HTTP request.

At the bottom of our file, we will create a new server block for redirecting all HTTP requests to HTTPS (be sure to replace the server name with your actual domain name):

    server {

listen 80; listen [::]:80; server_name; return 301 https://$server_name$request_uri;


Save the file, and exit the configuration file.

Reloading Nginx

That's it for all the Nginx configuration changes. Since we checked for syntax errors with each change, you should be ready to restart Nginx and test your changes.

To summarize, ignoring commented out lines, your configuration file should now look similar to this:

cat /etc/nginx/sites-available/default | egrep -v "^s*(#|$)"
    server {
      listen 443 ssl http2 default_server;
      listen [::]:443 ssl http2 default_server;
      root /var/www/html;
      index index.html index.htm index.nginx-debian.html;
      server_name server-ip-address;
      location / {
        try_files $uri $uri/ =404;
      ssl_certificate /etc/nginx/ssl/ubuntu.crt;
            ssl_certificate_key /etc/nginx/ssl/ubuntu.key;
            ssl_hitesh  /etc/nginx/ssl/hitesh.pem;
    server {
           listen         80;
           listen    [::]:80;
           server_name    server-ip-address;
           return         301 https://$server_name$request_uri;


To apply the changes, restart the Nginx server.

sudo systemctl restart nginx

Verifying the Changes

Let's check that our server is up and running. Open your web browser and type the URL http://server-ip-address.

You will get "Your connection is not private". This is expected and normal. We are only interested in the encryption aspect of our certificate, not the third party validation of our host's authenticity. Click "ADVANCED" and then click on Proceed to

HP_NO_IMG/data/uploads/users/fd35bf73-10f3-43bf-b753-4edc26228307/1656586230.png" alt="" /> HP_NO_IMG/data/uploads/users/fd35bf73-10f3-43bf-b753-4edc26228307/1116049004.png" alt="" /> HP_NO_IMG/data/uploads/users/fd35bf73-10f3-43bf-b753-4edc26228307/1568843501.png" alt="" />

If everything was configured properly, you should be automatically redirected to HTTPS. Now, let's check that HTTP/2 is working: open the Chrome Developer Tools (View -> Developer -> Developer Tools) and reload the page (View -> Reload This Page). Then navigate to the Network tab, click on table header row that starts with Name, right-click on it, and select the Protocol option. Now you should see h2 (which stands for HTTP/2) in a new column for your website serving HTTP/2 content.

HP_NO_IMG/data/uploads/users/fd35bf73-10f3-43bf-b753-4edc26228307/243110035.png" alt="" />

##Conclusion In this tutorial, you have learned how to set up nginx with HTTP-2 protocol support on Ubuntu 16.04. By using nginx over HTTP-2, we will get more speed and accuracy on our web server. Feel free to comment if you have any questions.

Want your very own server? Get our 1GB memory, Xeon V4, 25GB SSD VPS for £10.00 / month.

Get a Cloud Server