OBLETHdocs

HAProxy

The HAProxy front door shipped with the Docker Compose stack: its configuration, TLS, streaming settings and stats page.

1 min readUpdated for v2.4.0Edit on GitHub

HAProxy runs in the Compose stack under the edge profile, from the image haproxy:3.2, with deploy/docker/haproxy.cfg mounted read-only. The Helm chart does not deploy it; on Kubernetes the obleth Service and the chart's optional Ingress fill the same role (see Helm values).

Run it

.env.example already lists edge in COMPOSE_PROFILES. Otherwise:

cd deploy/docker
docker compose --profile edge up -d

HAProxy publishes port 80 on the host and forwards to the obleth data plane. Keep the Management API (9180) off HAProxy and on the internal network.

Shipped configuration

deploy/docker/haproxy.cfg, with its comments removed:

global
    log stdout format raw local0
    maxconn 50000

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
    timeout server  300s
    option http-no-delay

frontend obleth_front
    bind *:80
    default_backend obleth_pods

backend obleth_pods
    balance roundrobin
    server obleth1 obleth:8080 check resolvers docker init-addr last,libc,none

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}

The docker resolver re-resolves obleth through Docker's DNS, so a recreated gateway container with a new IP is picked up. To balance across several gateways, add a server line per instance to obleth_pods.

TLS termination

The shipped frontend is plaintext, on the assumption that a load balancer in front of it terminates TLS. To terminate TLS in HAProxy, put the certificate and private key in one PEM file and change 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

Then mount the file and publish 443 in a Compose override:

services:
  haproxy:
    ports: ["80:80", "443:443"]
    volumes:
      - ./certs/obleth.pem:/etc/ssl/private/obleth.pem:ro

Streaming

Streamed responses (text/event-stream) must pass through unbuffered:

  • option http-no-delay sends each chunk as it arrives.
  • timeout client and timeout server (300 s) bound silence on a connection. A non-streaming request is silent until the model answers, so keep them at or above OBLETH_UPSTREAM_TIMEOUT_SECS.
  • Do not turn on compression; it buffers responses.

Health checks

The shipped check is a TCP connect check. For an HTTP check, use the data plane's /health, which needs no token and returns the body ok:

backend obleth_pods
    option httpchk GET /health
    http-check expect string ok
    server obleth1 obleth:8080 check inter 5s fall 3 rise 2

Stats page

The stats frontend on 8404 serves the Prometheus exporter at /metrics, without a password so Prometheus can scrape it, and the stats UI at /stats behind basic auth. Compose exposes 8404 to its own network only. Set the sign-in in deploy/docker/.env; Compose falls back to admin / admin:

HAPROXY_STATS_USER=admin
HAPROXY_STATS_PASSWORD=...   # change the development value