Skip to content

HAProxy

HAProxy load balancer with automatic backend discovery and optional Let's Encrypt SSL.

Configuration

yaml
services:
  web:
    package: nginx
    replicas: 3

  lb:
    package: haproxy
    config:
      backends: web

With SSL:

yaml
services:
  lb:
    package: haproxy
    config:
      backends: web
      domain: myapp.com
      ssl: true
      ssl_email: [email protected]

Parameters

ParameterRequiredDefaultDescription
backendsYesService name to load balance (must match a key in services:)
backend_portNo80Port on backend servers to forward traffic to
domainNoDomain name for SSL certificate (Let's Encrypt)
sslNofalseEnable automatic SSL via Let's Encrypt
ssl_emailNoEmail for Let's Encrypt notifications
balanceNoroundrobinAlgorithm: roundrobin, leastconn, or source
health_check_pathNo/HTTP path for backend health checks
stats_enabledNotrueEnable stats page on port 8404

Backend Discovery

HAProxy discovers backends automatically by looking up the service name from backends. When you set backends: web, HAProxy finds all servers running the web service and routes traffic to them using their internal IPs (provider VPC when available).

You do not need to list backend IPs manually. When you add or remove replicas and run managed apply, HAProxy detects the change and reconfigures itself.

SSL

When ssl: true and domain are set:

  • HAProxy acquires a Let's Encrypt certificate using certbot
  • HTTPS is served on port 443 with modern TLS settings
  • HTTP on port 80 redirects to HTTPS automatically
  • Certificates are renewed automatically every 12 hours (certbot only renews near expiry)

Make sure your domain's DNS A record points to the HAProxy server's IP before running managed apply.

Scaling

When backend servers are added or removed:

  1. On managed apply: HAProxy's verify step detects the backend list changed and regenerates the config automatically
  2. Between applies: A scheduled job checks for backend changes every 5 minutes

HAProxy uses health checks (check inter 5s fall 3 rise 2) on each backend. If a backend is down or still starting up, HAProxy marks it as unavailable and routes traffic to healthy backends.

Commands

CommandDescription
managed service <name> refreshRediscover backends and reload config now
managed service <name> statusShow backend health status

Connection

HAProxy listens on:

  • Port 80 (HTTP, or redirect to HTTPS if SSL enabled)
  • Port 443 (HTTPS, if SSL enabled)
  • Port 8404 (stats page, private network only)

Firewall

HAProxy's ports 80 and 443 are open to the public. The stats page on 8404 is only accessible from private IPs.

Backend services should scope their ports to only allow traffic from the load balancer. For example, an nginx service behind HAProxy would declare:

yaml
ports:
  - port: 80
    from: lb

This ensures backend servers are not directly accessible from the internet.

How it works

The service installs HAProxy from the default Ubuntu repositories. The configure script:

  1. Discovers all backend servers via the managed state API
  2. Acquires an SSL certificate with certbot if configured
  3. Generates /etc/haproxy/haproxy.cfg with the backend list
  4. Validates the config with haproxy -c before applying
  5. Starts or reloads HAProxy

HAProxy forwards X-Forwarded-For on every request and X-Forwarded-Proto on the HTTPS frontend. Health checks probe the configured health_check_path and expect a 2xx or 3xx response.