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
name=nginx repo

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 an independent software developer ⌨️ & Linux sysadmin πŸ‘¨β€πŸ’», a general web geek & public speaker. Currently working on DNS Spy & Oh Dear! Follow me on Twitter as @mattiasgeniar 🐦.

πŸ”₯ If you're stuck with a technical problem, I'm available for hire to help you fix it!

Share this post

Did you like this post? Help me share it on social media! Thanks. πŸ€—

Have feedback?

New comments have been disabled on this blog, existing comments will remain as-is. Want to give feedback? Is there a mistake in the post?

Send me a tweet on @mattiasgeniar!


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!

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

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

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.

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.


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: 80]

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

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

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.

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. :)

Faizan Wednesday, August 30, 2017 at 08:17 -

Thanks for the tutorial. Will this enable on all the domains?

    Mattias Geniar Wednesday, August 30, 2017 at 16:58 -

    Thanks for the tutorial. Will this enable on all the domains?

    You enable this per server definition, where you add domains (server_name) that are valid for that particular configs. So yes, that HTTP/2 part applies to all domains in your config.

Luis Tacon Tuesday, March 13, 2018 at 12:09 -

Thanks Mattias. You just save me a lot of time !!

Markus Monday, October 29, 2018 at 22:16 -

Thanks for the tutorial. Now im ready for the future :D

Inbound links