nghttp2: an excellent alternative to an NGINX proxy
Recently at work, I had a very strange problem with an NGINX reverse proxy I was using: it was truncating static files at seemingly arbitrary places. To this day, I don't know what caused it.
On the plus side, a colleague of mine (thanks Mark!) pointed me towards an alternative I could test with: nghttp2.
To be clear: nghttp2 is not a complete NGINX replacement. It does, however, make for a stunningly easy HTTP/2 compliant reverse proxy alternative.
The nghttp2 project actually includes quite a few components: a client (
nghttp
), server (nghttpd
) and a proxy (nghttpx
). I'm only looking at the proxy today!
Previously, using NGINX as a reverse proxy required a slightly obtuse (but very powerful) config file and restarting the nginx server. Using nghttpx
allows you to directly run the server on-demand, then easily swap it to a system service later.
Running the proxy
Once you've got it installed (packages are available in EPEL for RHEL/CentOS, or in the mainline repos for Fedora), you can run the proxy component directly with the nghttpx
command. The syntax can be a little dizzying at first, but is super-easy to tweak and adjust. For example, here's the command my app ended up needing:
nghttpx -s -f'*,443' -b127.0.0.1,9442 /etc/ssl/cert.key /etc/ssl/cert.pem
That starts up a HTTP/2 proxy (-s
) on port 443 (-f'*,443'
) proxying a local HTTP app on port 9442 (-b127.0.0.1,9442
) using the cert and key from /etc/ssl
. If your upstream is HTTPS-enabled, just change it up slightly:
nghttpx -s -f'*,443' -b'127.0.0.1,9442;;tls' /etc/ssl/cert.key /etc/ssl/cert.pem
The
man
page includes a lot of info on the various ways to use the-b
/--backend
option!
It also supports the same -k
behaviour as curl if your upstream is using a self-signed cert.
Running as a service
To run it as a service, you'll want to use a config file. Like many other tools nghttpx
uses a key-value config file that reflects the same options as the command line switches. Here's the above command as a config file:
frontend=0.0.0.0,443
backend=127.0.0.1,9443;/;tls
insecure=yes
private-key-file=/etc/ssl/cert.key
certificate-file=/etc/ssl/cert.pem
add-x-forwarded-for=yes
accesslog-file=/var/log/nghttpx/access.log
errorlog-file=/var/log/nghttpx/error.log
You may have to create the directories for your log files before starting the service.
Put that config file in the default location of /etc/nghttpx/nghttpx.conf
and you're one easy command away from running proxy:
systemctl start nghttpx.service
# or for a start-at-boot server:
systemctl enable --now nghttpx.service
Seriously, if you need to use a reverse proxy for anything you're running (non-production-grade apps, containers, older servers etc), take a look at nghttp2: there's plenty of docs on GitHub and the man
page is really detailed and easy to understand.
For anyone who doesn't realise: HTTP/2 is SSL/TLS-only so make sure you've got a cert before you try and jump on the new hotness!