Sblurp

TLS and reverse proxies

The server speaks plain HTTP. Put a proxy in front of it for TLS. The app keeps one long stream open to the server, Subscribe, for live events. Most proxy problems come from that stream.

What the proxy must do

  • Pass HTTP/2 streams. Talk cleartext HTTP/2 (h2c) to the server, so Connect and gRPC streams work. HTTP/1.1 works for Connect too.
  • Not buffer. Send each event at once.
  • Not compress. Connect compresses by itself. Proxy compression holds back stream frames.
  • Allow long requests. A stream stays open for hours. The server sends a heartbeat every 25 seconds, so an idle timeout of a minute or more is enough.

Caddy

Caddy gets the certificate by itself.

chat.example.com {
	# h2c keeps Connect and gRPC streams working; flush_interval -1 sends
	# each live event at once. No `encode`: it would hold back stream frames.
	reverse_proxy h2c://127.0.0.1:8080 {
		flush_interval -1
	}
}

The Compose setup uses this file, with server:8080 in place of 127.0.0.1:8080.

Cloudflare

If your DNS is on Cloudflare, set the record to DNS only (grey cloud). Caddy or Fly must get the certificate itself, and Cloudflare's proxy is not needed in front of the stream.

Fly.io

Fly's proxy needs h2_backend = true and a high request concurrency limit. See Fly.io.

Other proxies

Any proxy works if it does the four things above. Turn off response buffering and compression for the server's address, and raise the read timeout.

Check it

  1. Open the app and join your community.
  2. Post a message from a second browser or a phone.
  3. It should appear at once in the first. If it appears only after a reload, the proxy is buffering the stream.

curl https://chat.example.com/healthz answers ok when the proxy reaches the server.