Where to start First steps track · 15 stages
Linux Labs

HAProxy — load balancer

4 min Ubuntu 24.04 · HAProxy 2.x

Load balancing and proxying TCP/HTTP — backends, health checks, statistics.

Cheat sheet

3 commands Printable version
  • haproxy -c -f /etc/haproxy/haproxy.cfg check the config
  • sudo systemctl reload haproxy apply it (graceful)
  • :8404/stats — backend UP/DOWN status
  • frontend bind (ssl crt) → backend: balance + server ... check + option httpchk/forwardfor
  • echo "show stat" | sudo socat stdio /run/haproxy/admin.sock runtime

Overview

HAProxy distributes connections across several backends (servers) and checks their health. It works at L4 (TCP) and L7 (HTTP). It's often placed in front of a pool of web servers (nginx) or a database.

bash
systemctl status haproxy
haproxy -c -f /etc/haproxy/haproxy.cfg    # check the config BEFORE reload

Configuration

/etc/haproxy/haproxy.cfg (a frontend accepts, a backend serves):

frontend web
    bind *:80
    bind *:443 ssl crt /etc/haproxy/site.pem      # TLS termination
    http-request redirect scheme https unless { ssl_fc }
    default_backend servers

backend servers
    balance roundrobin                 # or leastconn / source (sticky by IP)
    option httpchk GET /health         # an L7 health check
    option forwardfor                  # X-Forwarded-For (the client's real IP)
    cookie SRV insert indirect nocache # session stickiness via a cookie
    server s1 10.0.0.11:8000 check cookie s1
    server s2 10.0.0.12:8000 check cookie s2 backup   # a backup server

listen stats                           # a statistics page
    bind *:8404
    stats enable
    stats uri /stats
bash
haproxy -c -f /etc/haproxy/haproxy.cfg
sudo systemctl reload haproxy          # graceful, no dropped connections

Recipes

1

Balancing and routing

balance When
roundrobin evenly, in turn (the default)
leastconn the least-loaded server (long sessions, databases)
source sticky by the client's IP

Routing by path/host via an ACL:

frontend web
    acl is_api path_beg /api
    use_backend api_servers if is_api
    default_backend web_servers

The runtime API (no restart needed — take a server out of rotation):

bash
echo "disable server servers/s1" | sudo socat stdio /run/haproxy/admin.sock
echo "show stat" | sudo socat stdio /run/haproxy/admin.sock

Troubleshooting

5

503 Service Unavailable

No "live" backends: the health check failed for every server. Open :8404/stats to see each one's UP/DOWN status. Check that the backend responds: curl http://10.0.0.11:8000/health.

All requests go to one server

balance isn't set, or cookie/source stickiness is enabled. Check the backend section.

The config doesn't apply

haproxy -c -f ... shows the error (with a line number). Use reload (graceful) instead of restart so connections aren't dropped.

Can't see the client's real IP on the backend

Add option forwardfor and read X-Forwarded-For on the backend/nginx (real_ip). For TLS passthrough without termination, use mode tcp plus send-proxy.

Timeouts/disconnects under load

Tune timeout connect/client/server in defaults and maxconn. Too-small server timeouts cut off long responses; check ss on the backend.

See also

  • nginx — Web server and reverse proxy. Config is checked with nginx -t; reload with no downtime.
  • keepalived — High availability via a virtual IP — VRRP failover between nodes.
  • ss — Who's listening on ports and what connections are open — the modern replacement for netstat.
Loading…