HAProxy is a high-performance load balancer and proxy for TCP and HTTP. It’s the engine behind many large websites’ traffic distribution, known for reliability, detailed health checks and excellent observability. If you need to spread traffic across several application servers — or databases — HAProxy is a strong choice.
Install
sudo apt update
sudo apt install -y haproxy
haproxy -v
Ubuntu’s version is fine for most uses; the HAProxy team publishes PPAs with newer LTS branches if you need recent features.
Configuration lives in /etc/haproxy/haproxy.cfg.
Configuration structure
global → process-wide settings (logging, limits, TLS defaults)
defaults → defaults for all frontends/backends (mode, timeouts)
frontend → where clients connect (bind address, ACLs, routing)
backend → server pools traffic is sent to
listen → frontend + backend combined (handy for simple services)
A basic HTTP load balancer
global
log /dev/log local0
maxconn 20000
user haproxy
group haproxy
daemon
defaults
mode http
log global
option httplog
option forwardfor
timeout connect 5s
timeout client 30s
timeout server 30s
frontend http_in
bind *:80
default_backend app_servers
backend app_servers
balance roundrobin
option httpchk GET /health
http-check expect status 200
server app1 10.0.0.11:3000 check
server app2 10.0.0.12:3000 check
server app3 10.0.0.13:3000 check backup
option forwardforadds the client IP inX-Forwarded-For.option httpchk+checkenables active health checks: HAProxy polls/healthon each server and removes failing ones automatically.backupservers receive traffic only when all others are down.
Validate and reload:
sudo haproxy -c -f /etc/haproxy/haproxy.cfg
sudo systemctl reload haproxy
Reloads are seamless: existing connections continue on the old process.
Balancing algorithms
balance |
Behaviour |
|---|---|
roundrobin |
In turn, respecting weights (default) |
leastconn |
Fewest active connections — good for long requests, WebSockets, databases |
source |
Same client IP → same server |
uri / url_param / hdr(name) |
Hash on request parts (caches, sharding) |
random |
Random with optional “power of two choices” |
Weights: server app1 10.0.0.11:3000 check weight 3.
TLS termination
Combine certificate and key into one PEM file per domain:
sudo mkdir -p /etc/haproxy/certs
sudo sh -c 'cat /etc/letsencrypt/live/example.com/fullchain.pem /etc/letsencrypt/live/example.com/privkey.pem > /etc/haproxy/certs/example.com.pem'
sudo chmod 600 /etc/haproxy/certs/*.pem
frontend https_in
bind *:443 ssl crt /etc/haproxy/certs/ alpn h2,http/1.1
bind *:80
http-request redirect scheme https unless { ssl_fc }
http-request set-header X-Forwarded-Proto https if { ssl_fc }
default_backend app_servers
Pointing crt at a directory loads all certificates and selects by SNI. Automate renewals with a Certbot deploy hook that rebuilds the PEM files and reloads HAProxy (or use the HTTP-01 challenge via a backend that forwards /.well-known/acme-challenge/ to Certbot’s standalone server).
Routing by host or path
frontend https_in
bind *:443 ssl crt /etc/haproxy/certs/
acl is_api hdr(host) -i api.example.com
acl is_static path_beg /static/
use_backend api_servers if is_api
use_backend static_servers if is_static
default_backend app_servers
Sticky sessions
If an app keeps sessions in memory:
backend app_servers
balance roundrobin
cookie SRV insert indirect nocache
server app1 10.0.0.11:3000 check cookie a1
server app2 10.0.0.12:3000 check cookie a2
Better long-term: store sessions in Redis so any server can handle any request.
TCP mode (databases, other protocols)
listen postgres_read
bind 10.0.0.5:5433
mode tcp
balance leastconn
option pgsql-check user haproxy
server db1 10.0.0.21:5432 check
server db2 10.0.0.22:5432 check
Stats page
listen stats
bind 127.0.0.1:8404
stats enable
stats uri /
stats refresh 10s
Open via SSH tunnel (ssh -L 8404:127.0.0.1:8404 user@lb). It shows each server’s status, sessions, errors and response times. A Prometheus exporter endpoint is built in too (http-request use-service prometheus-exporter if { path /metrics }).
Logging
HAProxy logs to syslog; on Ubuntu, the package configures rsyslog to write /var/log/haproxy.log. Logs include timings for each phase of the request — invaluable for spotting slow backends.
High availability for HAProxy itself
Run two HAProxy servers with a floating IP managed by keepalived — see keepalived floating IP.
HAProxy vs Nginx
Nginx is a web server that also load-balances; HAProxy is a dedicated load balancer with richer health checks, stickiness options and statistics. For a simple setup, Nginx load balancing is enough; for serious traffic engineering, HAProxy shines. See also load balancer types.