Skip to content

Instantly share code, notes, and snippets.

@andrewchilds
Last active June 27, 2023 13:03
Show Gist options
  • Save andrewchilds/2393d6017c0b4a6e79d635243804fd12 to your computer and use it in GitHub Desktop.
Save andrewchilds/2393d6017c0b4a6e79d635243804fd12 to your computer and use it in GitHub Desktop.
How to configure HAProxy to proxy h2 (encrypted http2) to h2c (plain text http2) connections

How to configure HAProxy to support end-to-end (e2e) connections that switch from h2 to h2c

This was tested to work using HAProxy 2.8 on Ubuntu 20.04.

Use case

This lets you run a cluster of API servers configured to use HTTP/2 (for example, Fastify using { http2: true }), behind a HAProxy LB, so that you can serve typical REST API requests as well as SSE (Server Side Events) streaming connections, so that you can do fancy real-time page updates in your app.

Using HTTP/2 resolves the "6 concurrent HTTP connections" limit imposed by Chrome/Firefox/etc, which means the web app would become unresponsive if the user has 6+ tabs open with the app simultaneously.

frontend http_front
mode http
bind *:80
bind *:443 ssl crt /etc/haproxy/ssl/YOURDOMAIN.pem alpn h2,http/1.1
redirect scheme https if !{ ssl_fc }
default_backend http_back
backend http_back
mode http
balance roundrobin
server api1 1.2.3.4:4000 proto h2 check
server api2 1.2.3.5:4000 proto h2 check
@andrewchilds
Copy link
Author

What follows is GPT-4's explanation of the config file:

This configuration sets up an HAProxy load balancer with SSL termination and HTTP/2 support. Let's break it down:

Frontend configuration:

  • frontend http_front defines a new frontend named http_front.

  • mode http sets the proxy mode to HTTP. This mode enables all the HTTP-specific options, like manipulating HTTP headers.

  • bind *:80 and bind *:443 ssl crt /etc/haproxy/ssl/YOURDOMAIN.pem alpn h2,http/1.1 are listening for connections on ports 80 and 443 (HTTP and HTTPS, respectively). The second bind statement also sets up SSL termination with the specified SSL certificate and supports both HTTP/1.1 and HTTP/2 protocols (with preference for HTTP/2 because it's listed first).

  • redirect scheme https if !{ ssl_fc } redirects all HTTP traffic (non-SSL traffic coming on port 80) to HTTPS.

  • default_backend http_back specifies that all traffic should be forwarded to the backend named http_back.

Backend configuration:

  • backend http_back defines a new backend named http_back.

  • mode http sets the proxy mode to HTTP for the backend.

  • balance roundrobin sets the load balancing algorithm to round-robin. This means that HAProxy will distribute incoming requests evenly among the available servers, one after the other.

  • server api1 1.2.3.4:4000 proto h2 check and server api2 1.2.3.5:4000 proto h2 check define two backend servers with their IP addresses and the ports they're listening on. The proto h2 option is trying to enforce the use of HTTP/2 protocol for communication with these servers. However, as of my knowledge cutoff in September 2021, HAProxy does not fully support HTTP/2 communication on the backend side.

    The check option enables health checking. If a server goes down or becomes unresponsive, HAProxy will stop sending traffic to it until it becomes healthy again.

I would like to reiterate that as of my knowledge cutoff in September 2021, while HAProxy can accept and understand incoming HTTP/2 requests from clients, it doesn't fully support HTTP/2 when communicating with backend servers and downgrades those connections to HTTP/1.1. You might want to double-check this piece of information for the most up-to-date support details.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment