67 docs indexed
HAProxy configuration for TLS termination, round-robin load balancing across obleth pods, and streaming support.
HAProxy is the reference TLS terminator and load balancer for obleth. It ships in the Docker Compose stack under the edge profile. The Helm chart does not deploy HAProxy — on Kubernetes the same role is filled by a Service plus the chart's optional Ingress.
cd deploy/docker
docker compose --profile edge up -d
The shipped image is haproxy:3.2. It starts on port 80 with the obleth data
plane as the backend; TLS is not enabled by default.
This is deploy/docker/haproxy.cfg as it ships:
global
log stdout format raw local0
maxconn 50000
# Re-resolve backend hostnames at runtime via Docker's embedded DNS, so
# recreating the obleth container (new IP) does not leave HAProxy health-checking
# a dead address. Kubernetes Services track pod IPs natively, so this is a
# Compose-only concern.
resolvers docker
nameserver dns 127.0.0.11:53
resolve_retries 3
timeout resolve 1s
timeout retry 1s
hold valid 10s
defaults
mode http
log global
option httplog
timeout connect 5s
timeout client 300s # must be >= OBLETH_UPSTREAM_TIMEOUT_SECS
timeout server 300s
# streaming responses: don't buffer
option http-no-delay
frontend obleth_front
bind *:80
default_backend obleth_pods
backend obleth_pods
balance roundrobin
# one pod in compose; in prod this is the obleth fleet
server obleth1 obleth:8080 check resolvers docker init-addr last,libc,none
# server obleth2 obleth2:8080 check resolvers docker init-addr last,libc,none
The shipped frontend is plaintext :80 only, on the assumption that a managed
edge load balancer terminates TLS in front of it. To make HAProxy the TLS edge
instead, mount your certificate (PEM format, certificate + private key in a
single file) and enable TLS on the frontend:
frontend obleth_front
bind *:443 ssl crt /etc/ssl/private/obleth.pem
bind *:80
http-request redirect scheme https unless { ssl_fc }
default_backend obleth_pods
For Docker Compose, mount the cert and publish 443:
haproxy:
ports: ["80:80", "443:443"]
volumes:
- ./certs/obleth.pem:/etc/ssl/private/obleth.pem:ro
obleth uses HTTP/1.1 streaming for text/event-stream (SSE) responses. HAProxy must not buffer streaming responses. Key settings:
timeout client 300s and timeout server 300s (must be >= OBLETH_UPSTREAM_TIMEOUT_SECS)option http-no-delay — forwards each chunk as it arrives instead of coalescing itcompression — it buffers the responseHAProxy can health-check obleth pods using the /health endpoint:
backend obleth_pods
option httpchk GET /health
http-check expect string "ok"
server obleth1 obleth:8080 check inter 5s fall 3 rise 2
The data plane's /health route needs no authentication and returns the literal
body ok.
The Compose edge profile also exposes HAProxy's built-in Prometheus exporter
and human stats UI on :8404 (/metrics and /stats). The /stats page is
protected with HTTP basic auth so it can't be browsed anonymously if the port is
ever published:
frontend stats
bind *:8404
mode http
http-request use-service prometheus-exporter if { path /metrics }
stats enable
stats uri /stats
stats refresh 10s
stats realm obleth\ stats
stats auth ${HAPROXY_STATS_USER}:${HAPROXY_STATS_PASSWORD}
Set the credentials in deploy/docker/.env:
HAPROXY_STATS_USER=admin
HAPROXY_STATS_PASSWORD=... # change from the dev example
The /metrics endpoint is left unauthenticated so Prometheus can scrape it; keep
:8404 on the internal network and do not publish it publicly.
The admin API (:9180) should not be exposed via HAProxy. Keep it on the internal network only and use Kubernetes NetworkPolicy or firewall rules to restrict access.