HAProxy Load Balancer
Install and configure HAProxy as a TCP/HTTP load balancer and reverse proxy on Linux
HAProxy is a high-performance TCP/HTTP load balancer and proxy. It's widely used to distribute traffic across multiple backend servers, handle health checks, and terminate SSL.
Use cases
- Load balance web servers (Nginx/Apache/Node.js)
- TCP load balancing for databases or game servers
- SSL/TLS termination
- High-availability failover between backends
Installation
sudo apt update
sudo apt install haproxy -y
haproxy -vConfiguration file
The main config is at /etc/haproxy/haproxy.cfg. Back it up first:
sudo cp /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.bakBasic HTTP load balancing
Replace the default config with:
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5s
timeout client 50s
timeout server 50s
errorfile 400 /etc/haproxy/errors/400.http
errorfile 503 /etc/haproxy/errors/503.http
frontend http_front
bind *:80
default_backend web_servers
backend web_servers
balance roundrobin
option httpchk GET /health
server web1 10.0.0.1:80 check
server web2 10.0.0.2:80 check
server web3 10.0.0.3:80 checkTest the configuration:
sudo haproxy -c -f /etc/haproxy/haproxy.cfgApply:
sudo systemctl restart haproxyLoad balancing algorithms
| Algorithm | Config | Description |
|---|---|---|
| Round Robin | balance roundrobin | Requests distributed in turn |
| Least Connections | balance leastconn | Send to server with fewest active connections |
| Source IP hash | balance source | Same client always goes to same server |
| URI hash | balance uri | Same URL always goes to same server (cache-friendly) |
SSL termination
Install Certbot and obtain a certificate, then combine the files:
sudo cat /etc/letsencrypt/live/yourdomain.com/fullchain.pem \
/etc/letsencrypt/live/yourdomain.com/privkey.pem \
| sudo tee /etc/haproxy/certs/yourdomain.com.pem
sudo chmod 600 /etc/haproxy/certs/yourdomain.com.pemUpdate the frontend:
frontend https_front
bind *:443 ssl crt /etc/haproxy/certs/yourdomain.com.pem
http-request set-header X-Forwarded-Proto https
default_backend web_servers
frontend http_front
bind *:80
http-request redirect scheme https unless { ssl_fc }Health checks
HAProxy removes servers from the pool if they fail health checks:
backend web_servers
option httpchk GET /health HTTP/1.1\r\nHost:\ yourdomain.com
http-check expect status 200
server web1 10.0.0.1:80 check inter 5s fall 3 rise 2
server web2 10.0.0.2:80 check inter 5s fall 3 rise 2inter 5s: check every 5 secondsfall 3: mark down after 3 consecutive failuresrise 2: mark up again after 2 consecutive successes
Sticky sessions
Keep a user on the same backend server using a cookie:
backend web_servers
balance roundrobin
cookie SERVERID insert indirect nocache
server web1 10.0.0.1:80 check cookie web1
server web2 10.0.0.2:80 check cookie web2TCP load balancing
For non-HTTP protocols (databases, game servers, SMTP):
frontend mysql_front
bind *:3306
mode tcp
default_backend mysql_servers
backend mysql_servers
mode tcp
balance leastconn
option mysql-check user haproxy
server db1 10.0.0.10:3306 check
server db2 10.0.0.11:3306 check backupThe backup keyword means db2 only receives traffic if db1 is down.
Statistics dashboard
Enable the built-in stats page:
frontend stats
bind *:8404
stats enable
stats uri /stats
stats refresh 10s
stats auth admin:StrongPassword123!
stats hide-versionAccess at http://your-server:8404/stats.
Restrict the stats port with a firewall rule, never expose it publicly without authentication.
Rate limiting
Block clients sending too many requests:
frontend http_front
bind *:80
stick-table type ip size 100k expire 30s store conn_rate(10s)
http-request track-sc0 src
http-request deny deny_status 429 if { sc_conn_rate(0) gt 50 }
default_backend web_serversThis denies clients making more than 50 connections per 10 seconds.
Useful commands
# Reload config without dropping connections
sudo systemctl reload haproxy
# Check config syntax
sudo haproxy -c -f /etc/haproxy/haproxy.cfg
# Live status via socket
echo "show info" | sudo socat stdio /run/haproxy/admin.sock
echo "show servers state" | sudo socat stdio /run/haproxy/admin.sock
# View logs
journalctl -u haproxy -fDisable a backend server temporarily
echo "disable server web_servers/web1" | sudo socat stdio /run/haproxy/admin.sock
# Re-enable:
echo "enable server web_servers/web1" | sudo socat stdio /run/haproxy/admin.sock