HAProxy Load Balancer Setup on VPS Linux
HAProxy (High Availability Proxy) is one of the world's most widely-used production-grade load balancer and reverse proxy. It handles extremely high throughput with minimal resource consumption, includes intelligent health checks, and provides a real-time stats dashboard for monitoring. This article will set up HAProxy on a single VPS to distribute HTTP/HTTPS traffic across 2-3 backend servers.
Install HAProxy
sudo apt update
# Install HAProxy latest version from official PPA
sudo add-apt-repository ppa:vbernat/haproxy-2.8 -y
sudo apt install haproxy -y
# Check version
haproxy -v
HAProxy Configuration Structure
The configuration file /etc/haproxy/haproxy.cfg is divided into 4 main sections:
- global — Set daemon-level options: logging, user, limits
- defaults — Default settings applied to all frontends and backends
- frontend — Receive connections from clients (bind port)
- backend — Group of servers that receive forwarded traffic
Configure HTTP Load Balancer
sudo nano /etc/haproxy/haproxy.cfg
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
maxconn 50000
defaults
log global
mode http
option httplog
option dontlognull
option forwardfor
option http-server-close
timeout connect 5s
timeout client 30s
timeout server 30s
errorfile 400 /etc/haproxy/errors/400.http
errorfile 503 /etc/haproxy/errors/503.http
# Receive HTTP traffic on port 80
frontend http_front
bind *:80
default_backend web_servers
# Group of backend servers
backend web_servers
balance roundrobin
option httpchk GET /health
http-check expect status 200
server web1 192.168.1.10:80 check inter 5s rise 2 fall 3
server web2 192.168.1.11:80 check inter 5s rise 2 fall 3
server web3 192.168.1.12:80 check inter 5s rise 2 fall 3 backup
SSL Termination on HAProxy
HAProxy receives HTTPS itself and forwards HTTP to backends — reducing SSL load on backend servers:
# Combine certificate and key into a single file (HAProxy requirement)
cat /etc/ssl/certs/example.com.crt /etc/ssl/private/example.com.key \
> /etc/haproxy/certs/example.com.pem
chmod 600 /etc/haproxy/certs/example.com.pem
# Add HTTPS frontend to haproxy.cfg
frontend https_front
bind *:443 ssl crt /etc/haproxy/certs/example.com.pem
# Redirect HTTP to HTTPS
http-request redirect scheme https unless { ssl_fc }
# Security headers
http-response set-header Strict-Transport-Security "max-age=31536000"
default_backend web_servers
# Adjust http_front to redirect to HTTPS
frontend http_front
bind *:80
http-request redirect scheme https code 301
Traffic Distribution Algorithms
Choose a balance algorithm that matches your use case:
roundrobin— Round-robin through servers equally (default, suitable for general use)leastconn— Send to server with fewest active connections (good for long-lived connections)source— Hash based on client IP so the same user always goes to the same server (good for session stickiness)uri— Hash based on URL so identical requests go to the same server (good for caching)
Stats Dashboard
# Add stats frontend to haproxy.cfg
frontend stats
bind *:8404
stats enable
stats uri /stats
stats refresh 10s
stats auth admin:SecurePassword123
stats hide-version
# Open port 8404 in firewall
sudo ufw allow 8404/tcp
# Access dashboard at
# http://YOUR_VPS_IP:8404/stats
ssh -L 8404:localhost:8404 user@VPS_IP then access http://localhost:8404/stats
For high-availability deployments with quality VPS services, asiagb.com provides VPS in Thailand and Singapore that can run HAProxy immediately. They support private networking between VPS in the same network, allowing backend servers to stay off the public internet. For domain health checks and DNS inspections, try dnsxray.com — a free tool for checking SSL, DNS, and HTTP headers.
Verify HAProxy is Working Correctly
# Check configuration syntax before every reload
haproxy -c -f /etc/haproxy/haproxy.cfg
# Reload config without dropping connections
sudo systemctl reload haproxy
# View status of all servers via socket
echo "show servers state" | sudo socat stdio /run/haproxy/admin.sock
# Test load balancing
for i in {1..6}; do curl -s http://YOUR_VPS_IP/ | grep "Server:"; done
option log-health-checks in defaults or backend to log every health check pass/fail. This helps tremendously when debugging backend server issues.
Common Issues & Troubleshooting
Error: "backend has no server available!" in logs
All backend servers failed health checks. Verify that the endpoint specified in option httpchk returns 200:
# Test health endpoint directly from haproxy server
curl -sv http://192.168.1.10:80/health
# View backend server status
echo "show servers state web_servers" | sudo socat stdio /run/haproxy/admin.sock
# If endpoint doesn't exist, use TCP check instead
option tcp-check # instead of httpchk
Error: "cannot bind socket" on startup
The desired port is already in use by another process (e.g., Nginx or Apache). Stop that service first:
# Check which process is using port 80/443
sudo ss -tlnp | grep ':80\|:443'
# Stop nginx temporarily
sudo systemctl stop nginx
# To run HAProxy alongside Nginx on the same machine,
# have HAProxy listen on 80/443 and proxy to Nginx on port 8080
Client IP shows as HAProxy IP in backend logs
Enable option forwardfor in defaults/frontend, and the backend app must read the X-Forwarded-For header:
# Verify forwardfor is set
grep "forwardfor" /etc/haproxy/haproxy.cfg
# In Nginx backend, log X-Forwarded-For instead of $remote_addr
log_format main '$http_x_forwarded_for - $remote_user [$time_local] ...';
HAProxy reload drops connections
Use systemctl reload haproxy instead of restart. HAProxy gracefully reloads using socket handoff, keeping existing connections alive:
# Graceful reload (preserves connections)
sudo systemctl reload haproxy
# Never use restart in production unless necessary
# sudo systemctl restart haproxy ← drops all connections
Frequently Asked Questions
How is HAProxy different from Nginx upstream load balancing?
Nginx is a web server with load balancing added. HAProxy was designed specifically as a load balancer. HAProxy has richer features like per-server weight, advanced health checks, connection draining, ACL-based routing, and stats socket for detailed operation. For very high production traffic, HAProxy often performs better and is easier to debug.
Does HAProxy support WebSocket?
Yes. Use option http-server-close and ensure the backend supports WebSocket. HAProxy detects HTTP Upgrade requests and forwards the connection directly to the backend without breaking the connection mid-stream.
What happens if a backend server crashes?
HAProxy runs health checks on the interval specified (e.g., inter 5s = every 5 seconds). If a check fails the number of times specified by fall, HAProxy marks that server DOWN and stops sending traffic to it. When the server recovers and passes health checks the number of times specified by rise, it is automatically marked UP and receives traffic again.