Enable HTTP/2 in Nginx

Mattias Geniar, Tuesday, September 22, 2015 - last modified: Thursday, October 27, 2016

As of nginx 1.9.5, there is experimental support for HTTP/2. This article will show you how to enable HTTP/2 support in your Nginx configuration. This can be enabled or disabled per vhost, it does not have to be enabled server-wide.

Warning: you will need at least OpenSSL 1.0.2 if you want to support HTTP/2 on Google Chrome, since they now require ALPN support for HTTP/2. If after this tutorial HTTP/2 isn't working in Chrome, check your OpenSSL version.

HTTP/2 in Nginx on CentOS / Red Hat

If you're on Red Hat or CentOS, make sure to enable the mainline repository for nginx. This is considered an experimental release, which could break things.

Here's what your yum repository should look like.

$ cat /etc/yum.repos.d/nginx.repo
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=0
enabled=1

If you already had nginx installed, update via yum clean all && yum update nginx or install nginx (if you hadn't already) by yum install nginx.

HTTP/2 in Nginx on Ubuntu / Debian

If you're on Debian or Ubuntu, make sure the mainline sources are added to your /etc/apt/sources.list file.

$ cat /etc/apt/sources.list
...
deb http://nginx.org/packages/mainline/debian/ codename nginx
deb-src http://nginx.org/packages/mainline/debian/ codename nginx

Next, update your nginx installation with apt-get clean && apt-get install nginx.

HTTP/2 on Nginx requires at least 1.9.5

Verify that your nginx version is at least 1.9.5.

$ nginx -v
nginx version: nginx/1.9.5

Anything lower will not yet have HTTP/2 support and you'll 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

Enable HTTP/2 in Nginx

Now, in order to enable HTTP/2, you need to have an SSL/TLS enabled vhost. In other words: you need an SSL certificate, as HTTP/2 is only implemented over TLS.

Enabling HTTP/2 is just as simple as enabling SPDY, it's a flag in the listen directive in your virtual host config.

Add the http2 keywords to your virtualhost configuration.

server {
  listen        443 ssl http2;
  server_name   your.fqdn.tld;

  access_log    access.log main;
  error_log     error.log error;

  # Start the SSL configurations
  ssl                   on;
  ssl_certificate       /etc/nginx/conf.d/certificate.crt;
  ssl_certificate_key   /etc/nginx/conf.d/certificate.key;

  # Add any other TLS optimisations like strong ciphers etc ... 
  # ...
}

Enabling really is this simple, just change your current ssl-line from this:

server {
  listen        443 ssl;
  ...
}

to this:

server {
  listen        443 ssl http2;
  ...
}

Please note: you can not mix SPDY and HTTP/2. If you try to enable both, you'll get an error on startup of nginx.

nginx: [warn] invalid parameter "spdy": ngx_http_spdy_module was superseded by ngx_http_v2_module in /etc/nginx/conf.d/vhost.conf:12

If you just want to play around with HTTP/2, you can create a self-signed SSL certificate and implement that in your vhost.

Lack of server side push

As of yet, Nginx does not support one of the most powerful features of HTTP/2: server side push. Only nghttp2 seems to support it at this time.

But HTTP/2 brings a lot of improvements to the table, like TCP multiplexing, header compression, less domain sharding, ... that make it a worthwhile upgrade already.

Testing HTTP/2

There are already a couple of HTTP/1.1 vs HTTP2 benchmarks out there, but the best test is the one you can do yourself.

Since Nginx now makes it really easy to enable HTTP/2, we activated it on our corporate website as well: www.nucleus.be. Want test HTTP/2? Just browse to nucleus.be.

If you're curious to know how you can detect if you're on HTTP/1.1 or HTTP2, you can view the HTTP/2 protocol in your Chrome Inspector.

More reading material on HTTP/2

Want to know more about HTTP/2? Here are a few suggestions:



Hi! My name is Mattias Geniar. I'm a Support Manager at Nucleus Hosting in Belgium, a general web geek, public speaker and podcaster. Currently working on DNS Spy. Follow me on Twitter as @mattiasgeniar.

I respect your privacy and you won't get spam. Ever.
Just a weekly newsletter about Linux and open source.

SysCast podcast

In the SysCast podcast I talk about Linux & open source projects, interview sysadmins or developers and discuss web-related technologies. A show by and for geeks!

cron.weekly newsletter

A weekly newsletter - delivered every Sunday - for Linux sysadmins and open source users. It helps keeps you informed about open source projects, Linux guides & tutorials and the latest news.

Share this post

Did you like this post? Will you help me share it on social media? Thanks!

Comments

Luciano Mammino Friday, September 25, 2015 at 22:22

Great article. I’m really looking forward to experiment with HTTP2 and check the performance gains that the new version of the protocol should provide!

Reply


Jaideep Padhye Thursday, October 1, 2015 at 00:07

I was wondering if NGINX can be configured for HTTP/2 (h2c only) mode?

Reply


    Mattias Geniar Thursday, October 1, 2015 at 04:28

    As far as I know, you can’t at the moment: HTTP2 is only implemented over TLS.

    Reply


Jaideep Padhye Friday, October 2, 2015 at 20:52

Thanks. Really appreciate your response. You might want to contact the maintainer of this wiki page: https://github.com/http2/http2-spec/wiki/Implementations

It claims that NGINX supports h2c mode.

Reply


John Sunday, October 4, 2015 at 13:04

HTTP/2 support in nginx is working fine as expected, also created a small website to check the HTTP/2 support on webservers.

http://h2.nix-admin.com/

Reply


Chris Thursday, October 8, 2015 at 17:43

On Ubuntu i get that the repo does not exist

W: Failed to fetch http://nginx.org/packages/mainline/debian/dists/codename/nginx/source/Sources 404 Not Found [IP: 206.251.255.63 80]

W: Failed to fetch http://nginx.org/packages/mainline/debian/dists/codename/nginx/binary-amd64/Packages 404 Not Found [IP: 206.251.255.63 80]

W: Failed to fetch http://nginx.org/packages/mainline/debian/dists/codename/nginx/binary-i386/Packages 404 Not Found [IP: 206.251.255.63 80]

Reply


Web Developer Thursday, November 5, 2015 at 04:58

I also enabled http2 on my nginx server however the chrome dev tools protocol column shows http/1.1, same on your corporate website.

Reply


    Mattias Geniar Thursday, November 5, 2015 at 10:11

    Is your site configured to use SSL certificates? Right now, HTTP/2 will only work if the site has a valid HTTPS/SSL configuration.

    Reply


      Mattias Geniar Monday, November 16, 2015 at 15:12

      Update: are you running Chrome Canary (version 47 or higher)? As of version 47, Chrome disabled NPN in favor of ALPN, which causes the Nginx HTTP/2 configuration to stop working. I’ve modified the blogpost to more accurately reflect this.

      Reply


Fred Harris Sunday, February 19, 2017 at 18:51

Thank you for this great article. I will now try and implement your instructions on my server and hopefully I won’t have to bother the Rosehosting crew to fix the mistakes caused by my botness. (yeah i invented a word)

HTTP2 with Nginx here I come. :)

Reply


Leave a Reply

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

Inbound links