HTTP/2 with Nginx and HAProxy

The HTTP/2 protocol (Wikipedia link) has been around for a while, but the website operators have been waiting for the server and browser software to implement it. HTTP/2 should significantly improve browser page load times (see the details in the Wikipedia article link). Browsers now support it, but what about servers? Apache has it all built in since 2.4.17 (2015-10). Nginx supports it since version 1.9.5 (2015-09). And HAProxy ... well, if you're simply using HAProxy to redirect to HTTP/2 backends, that will work as it can pass the requests (I haven't tried this). But the current version 1.7.9 (2017-08) can't terminate or respond to an HTTP/2 request, and the author has been vague about the likelihood of HTTP/2 being in the upcoming version 1.8.

Another major advance from my point of view was Debian's recent release of stretch aka Debian 9 (2017-06) because it included version 1.10 of Nginx (oldstable/jessie had 1.6, which doesn't support HTTP/2) so it suddenly became possible to support HTTP/2 without using backports (which I prefer to avoid). Not only is it possible, with Nginx it's insanely easy:

server {
    listen 443 ssl;
    ...
}

Becomes:

server {
    listen 443 http2 ssl;
    ...
}

And you're done. Okay, not always that simple - you should read the short list of disclaimers and instructions in the Nginx blog post about the release, but for me (across several servers so far) it really was that simple. The best news is that if the connecting client doesn't understand HTTP/2, the handshake fails and the server immediately falls back to HTTP 1.1, silently and without problem.

The HAProxy problem could of course be solved by putting Nginx in front of HAProxy ... but I've been there and don't want to do it again. Not only have you increased your complexity by a factor of two (and thus your potential for failure), but you have to maintain DNS name lists in both servers so they recognize and respond correctly. It's entirely possible, but I don't recommend it.

The easiest way to determine if HTTP/2 is working on your server is to install the HTTP/2 and SPDY indicator plugin (this is for Firefox, but I think there's one for Chrome as well). There are comments on the page that indicate the plugin doesn't work with the newest FF - I'm assuming this means the betas in which they've completely changed the plugin architecture, because the plugin is working fine for me on both Linux and Mac. A friend showed me that Chrome's "Inspect Element -> Network tab" can be made to show the protocol, so that could also work.

So ... if you're using Nginx, what are you waiting for? There's no down-side, and it'll take you 15 minutes. It only takes that long because you'll want to do some cautious checking afterwards!