HAProxy Load Balancer: Complete Configuration Guide
In this tutorial, you'll learn about HAProxy Load Balancer: Complete Configuration Guide. We cover key concepts, practical examples, and best practices.
HAProxy is a high-performance TCP/HTTP load balancer and proxy server widely used to distribute traffic across multiple backend servers. It powers some of the busiest websites on the internet with sub-millisecond latency and minimal resource overhead.
In this tutorial, you will learn to configure HAProxy frontends and backends, write ACL rules for traffic routing, set up SSL termination, configure health checks, enable session persistence, and monitor HAProxy metrics. DodaTech uses HAProxy to distribute load across Durga Antivirus Pro update servers and Doda Browser sync infrastructure.
What You'll Learn
By the end of this guide, you will deploy HAProxy as a load balancer, route traffic based on domain names and URL paths with ACLs, terminate SSL, configure active health checks, and monitor HAProxy stats through its built-in dashboard.
Why Load Balancing Matters
A single server has limits. Load balancing distributes traffic across multiple servers to improve availability, scalability, and fault tolerance. If one server fails, HAProxy automatically routes traffic to healthy servers. This is essential for Web Servers serving production traffic and DevOps infrastructure managing high-availability deployments.
HAProxy Learning Path
flowchart LR
A[Installation] --> B[Frontend & Backend]
B --> C[ACL Rules]
C --> D[SSL Termination]
D --> E[Health Checks]
E --> F[Session Persistence]
F --> G{You Are Here}
style G fill:#f90,color:#fff
Installation
# Ubuntu / Debian
sudo apt update && sudo apt install haproxy -y
# RHEL / CentOS / Fedora
sudo dnf install haproxy -y
# Verify
sudo systemctl start haproxy
sudo systemctl enable haproxy
sudo systemctl status haproxy --no-pager
Expected output
haproxy.service - HAProxy Load Balancer
Loaded: loaded (/lib/systemd/system/haproxy.service; enabled; vendor preset: enabled)
Active: active (running)
Basic Configuration
HAProxy configuration lives in /etc/haproxy/haproxy.cfg. A minimal setup has a frontend (listening point) and a backend (server pool):
global
log /dev/log local0
maxconn 4096
user haproxy
group haproxy
defaults
log global
mode http
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
frontend web_frontend
bind *:80
default_backend web_servers
backend web_servers
balance roundrobin
server web1 10.0.1.1:80 check
server web2 10.0.1.2:80 check
server web3 10.0.1.3:80 check
Expected behavior
curl -I http://localhost
# HTTP/1.1 200 OK
# Each request is distributed to web1, web2, or web3 in turn
ACL Rules for Traffic Routing
ACLs let you route traffic based on domain, URL path, headers, or client IP:
frontend web_frontend
bind *:80
bind *:443 ssl crt /etc/haproxy/certs/
# ACLs for domain-based routing
acl is_api hdr(host) -i api.example.com
acl is_app hdr(host) -i app.example.com
acl is_static hdr(host) -i static.example.com
# ACL for URL path routing
acl is_health path_beg /health
acl is_admin path_beg /admin
# ACL for WebSocket
acl is_websocket hdr(Upgrade) -i websocket
# Routing decisions
use_backend api_servers if is_api
use_backend app_servers if is_app
use_backend static_servers if is_static
default_backend web_servers
backend api_servers
balance leastconn
option httpchk GET /health
server api1 10.0.2.1:3000 check
server api2 10.0.2.2:3000 check
backend static_servers
balance roundrobin
server static1 10.0.3.1:80 check
server static2 10.0.3.2:80 check
Testing ACL routing
curl -H "Host: api.example.com" http://localhost/api/users
# Routes to api_servers backend
curl -H "Host: app.example.com" http://localhost/dashboard
# Routes to app_servers backend
SSL Termination
Terminate SSL at the load balancer so backend servers handle unencrypted traffic:
# Create certificate directory
sudo mkdir -p /etc/haproxy/certs
# Combine certificate and key into PEM format
sudo 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/example.com.pem
frontend https_frontend
bind *:443 ssl crt /etc/haproxy/certs/example.com.pem
http-request redirect scheme https unless { ssl_fc }
# Security headers
http-response add-header Strict-Transport-Security "max-age=31536000; includeSubDomains"
http-response add-header X-Content-Type-Options nosniff
http-response add-header X-Frame-Options DENY
default_backend web_servers
frontend http_frontend
bind *:80
http-request redirect scheme https code 301
Expected output
curl -I https://example.com
# HTTP/1.1 200 OK
# strict-transport-security: max-age=31536000; includeSubDomains
Health Checks
HAProxy monitors backend servers with active health checks:
backend web_servers
balance roundrobin
# Active HTTP health check
option httpchk GET /health HTTP/1.1\r\nHost:\ example.com
http-check expect status 200
# Server with custom check interval
server web1 10.0.1.1:80 check inter 2000 rise 3 fall 2
server web2 10.0.1.2:80 check inter 2000 rise 3 fall 2
# Backup server (only used if all primary servers are down)
server web-backup 10.0.1.4:80 check backup
Checking server status
echo "show stat" | sudo socat stdio /var/run/haproxy/admin.sock
# Expected columns: pxname, svname, status, weight, act, bck, chkfail, downtime
# web_servers web1 UP 1 1 0 0 0
# web_servers web2 UP 1 1 0 0 0
Session Persistence
Ensure a client always reaches the same backend server:
backend app_servers
balance roundrobin
# Cookie-based persistence
cookie SERVERID insert indirect nocache
server app1 10.0.4.1:8080 cookie app1 check
server app2 10.0.4.2:8080 cookie app2 check
server app3 10.0.4.3:8080 cookie app3 check
For source IP persistence:
backend app_servers
balance source
hash-type consistent
server app1 10.0.4.1:8080 check
server app2 10.0.4.2:8080 check
server app3 10.0.4.3:8080 check
Monitoring with Stats Dashboard
Enable the built-in statistics page:
frontend stats_frontend
bind *:8404
stats enable
stats uri /stats
stats refresh 10s
stats admin if LOCALHOST
stats auth admin:securepassword
Expected behavior
curl -u admin:securepassword http://localhost:8404/stats
# Returns HTML statistics page with server status, traffic, and uptime
Common Errors
1. Backend Down
Server is not responding to health checks. Verify the backend service is running and the port is correct. Check sudo journalctl -u haproxy --no-pager | tail.
2. SSL Handshake Failure
The PEM file is malformed or permissions are wrong. Ensure the certificate and key are concatenated in order and chmod 600 is set.
3. High Connection Timeout
Backend servers are slow. Increase timeout server in the defaults section. Check backend server load and database queries.
4. ACL Not Matching
ACL conditions evaluate in order. Use haproxy -f /etc/haproxy/haproxy.cfg -c to validate config syntax and test ACL patterns.
5. Port Already in Use
Another service is listening on the same port. Check with sudo ss -tlnp | grep :80 and stop the conflicting service or change HAProxy's bind port.
6. Stats Dashboard Unauthenticated
Anyone can see the stats page. Always set stats auth with a strong password and restrict the bind address to internal IPs.
Practice Questions
1. What is the difference between roundrobin and leastconn balancing? Roundrobin distributes requests evenly across servers in order. Leastconn sends requests to the server with the fewest active connections, which is better for long-lived connections.
2. How do you check if a backend server is healthy in HAProxy?
Use echo "show stat" | sudo socat stdio /var/run/haproxy/admin.sock or check the stats dashboard. Servers with status UP are healthy.
3. What is session persistence and why is it needed? Session persistence ensures a client's requests always go to the same backend server. This is needed for stateful applications that store session data locally rather than in a shared store.
4. Challenge: Blue-green deployment with HAProxy
Configure HAProxy with two backend pools (blue and green) and use an ACL based on a cookie to route 10% of traffic to green:
backend blue
server app1 10.0.1.1:8080 check
server app2 10.0.1.2:8080 check
backend green
server app3 10.0.2.1:8080 check
server app4 10.0.2.2:8080 check
Add a frontend ACL that routes requests with cookie deploy=green to the green pool and all others to blue.
Mini Project: High-Availability Reverse Proxy
Deploy HAProxy as a central load balancer for three services:
- Install HAProxy on a server with both public and private network interfaces
- Configure three backend pools:
api(Node.js on ports 3000-3001)web(static NGINX servers on ports 80-81)admin(restricted to internal IPs only)
- Set up ACLs to route
api.example.com,www.example.com, andadmin.example.com - Enable SSL termination with a Let's Encrypt certificate
- Configure the stats dashboard on port 8404 with authentication
- Test failover by stopping one backend server
# Validate config
sudo haproxy -f /etc/haproxy/haproxy.cfg -c
# Reload HAProxy
sudo systemctl reload haproxy
# Test routing
curl -H "Host: api.example.com" https://localhost/api/health
curl -H "Host: www.example.com" https://localhost/
This architecture mirrors how DodaTech balances traffic across Doda Browser update mirrors and Durga Antivirus Pro signature distribution servers.
FAQ
Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro