Nginx – Enable HTTP/2


To totally unlock this section you need to Log-in

Hypertext Transfer Protocol Version 2 (HTTP/2) is the latest version of the HTTP protocol, published as an IETF standard in RFC 7540 in 2015. The focus of the protocol is on performance; specifically, end-user perceived latency, network and server resource usage.

In 2015, Internet Engineering Task Force (IETF) release HTTP/2, the second major version of the most useful internet protocol, HTTP. It was derived from the earlier experimental SPDY protocol. Main goals of developing HTTP/2 was:

  • Protocol negotiation mechanism — protocol electing, eg. HTTP/1.1, HTTP/2 or other.
  • High-level compatibility with HTTP/1.1 — methods, status codes, URIs and header fields.
  • Page load speed improvements trough:
  • Compression of request headers
  • Binary protocol
  • HTTP/2 Server Push
  • Request multiplexing over a single TCP connection
  • Request pipelining
  • HOL blocking (Head-of-line) — Package blocking
  • Request multiplexing

HTTP/2 can send multiple requests for data in parallel over a single TCP connection. This is the most advanced feature of the HTTP/2 protocol because it allows you to download web files asynchronously from one server. Most modern browsers limit TCP connections to one server.

Nginx - Enable HTTP/2

HTTP/2 compress a large number of redundant header frames. It uses the HPACK specification as a simple and secure approach to header compression. Both client and server maintain a list of headers used in previous client-server requests.

HPACK compresses the individual value of each header before it is transferred to the server, which then looks up the encoded information in a list of previously transferred header values to reconstruct the full header information.

One major goal is to allow the use of a single connection from browsers to a Web site. The protocol is backward compatible, so HTTP methods, status codes and semantics are the same as for previous versions of the protocol. Nginx has HTTP/2 support since version 1.9.5.

In this article, we are going to assume that you already have a working TLS configuration, and that you have required Nginx version installed on your Linux distribution of choice, and that you know how to use Let's Encrypt, or you know how to issue a self-signed certificate.

Requirements

To enable HTTP/2 in Nginx you will need to fulfill the following requirements:

  • Nginx version 1.9.5 or greater. You can check your Nginx version by running (nginx -v) command.
  • OpenSSL version 1.0.2 or greater. You can check your OpenSSL version by running (OpenSSL version) command.
  • SSL/TLS certificate from Let's Encrypt or a self-signed certificate.
  • TLS 1.2 or higher protocol enabled. Otherwise, you will not be able to use HTTP/2. Implementations of HTTP/2 must use TLS version 1.2 or higher for HTTP/2 over TLS.

Anything lower than version 1.9.5 of Nginx will not yet have HTTP/2 support and you will be greeted with the following error message:

nginx: [emerg] invalid parameter "http2" in /etc/nginx/conf.d/ssl.conf:2
nginx: configuration file /etc/nginx/nginx.conf test failed

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.

Enable HTTP/2 in Nginx

To enable HTTP/2 in Nginx, we have to add the http2 parameter to the listen directive in our virtual host:

listen 443 ssl http2;

And reload your Nginx configuration:

sudo systemctl reload nginx.service

Here is the minimal virtual server configuration that can be used to enable HTTP/2 in some virtual host:

server {

  listen 443 ssl http2;
  listen [::]:443 ssl http2;

  server_name example.com;
  root /path/to/public;

  ssl_certificate /path/to/certificate.crt;
  ssl_certificate_key /path/to/private.key;

  ssl_protocols TLSv1.2;

}

To check if your server supports HTTP/2, you can use your browser dev tools or Nginx log files. The below is a screenshot from Google Chrome browser that shows HTTP/2 in action on https://example.com domain.

You can also use Nginx $http2 embedded variable to see negotiated protocol. This variable will log: “h2” for HTTP/2 over TLS, “h2c” for HTTP/2 over cleartext TCP, or an empty string otherwise in the Nginx access log if configured to do so.

And that's all there is to enabling HTTP/2 on your Nginx server.

The location of the Nginx block file is the only difference between CentOS and Ubuntu and it depends also if Nginx has been built from source or not with custom paths.

To edit the default Nginx server block on CentOS you should look into the /etc/nginx/conf.d, for example, directory.

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

OR
nano /etc/nginx/conf/nginx.conf
OR
nano /etc/nginx/nginx.conf

Once again, check if there are errors with the configuration, save and close the file, then restart the Nginx service using the command below:

systemctl restart nginx.service

Testing If HTTP/2 is enabled

Now let's test whether HTTP/2 is running and enabled on our Nginx web server. In your terminal, execute the command below:

curl -I -L https://your_domain

In our case, it shall be:

curl -I -L https://example.org

To check your site using the Developer tool in Google Chrome, you will need to add the protocol column to the Network tab. To do this, open the Developer toolkit by hitting F12 or right clicking and inspect element in Chrome. Then navigate to the Network tab and right click on one of the headings, then click protocol in the drop down menu.

Nginx - Enable HTTP/2

This will add a new protocol column to the Network tab and let you know which HTTP protocol version each resource (HTML, CSS, JS, font, etc.) is being served on.

Nginx - Enable HTTP/2

From there you will be able to identify if any of your own internal resources are being served over HTTP/2. As you can see from the screenshot above, the website is on HTTP/2, but some of the CSS and JS files from Google are still on SPDY.