HAProxy Load Balancer Configuration and Deployment Guide

HAProxy Overview

HAProxy is an open-source high-performance reverse proxy and load balancer that supports active-passive failover, virtual hosting, and application-layer proxying for TCP and HTTP protocols. Its configuration is straightforward, maintenance is simple, and it includes robust health-checking capabilities. When a backend server fails, HAProxy automatically removes it from the pool; once recovered, the server is seamlessly reintegrated.

HAProxy excels in high-traffic scenarios requiring session persistence or layer 7 application proxying. Running on standard hardware, it can handle tens of thousands of concurrent connections without extensive optimization. Its proxy mode keeps backend servers hidden from external networks, eliminating the need for public IPs on backend nodes.

HAProxy operates at both layer 4 and layer 7, similar to how LVS works at layer 4 and Nginx at layer 7. Configuration involves defining backend servers in a configuration file, then distributing traffic using various algorithms.

Key Advantages:

  • Virtual host support across layers 4 and 7
  • Session persistence and cookie-based routing
  • URL-based backend health checking
  • Superior concurrent connection handling compared to Nginx
  • MySQL read load balancing with multiple algorithm support

Architecture Topology

Layer 4 TCP Proxy Configuration

HAProxy's layer 4 TCP proxy is straightforward and requires no scripts on the real servers, making it easier to configure than LVS or Nginx. Note that NAT mode routes all traffic through HAProxy, so performance under extremely high load may be lower than LVS. For small to medium deployments, HAProxy is recommended over LVS or Nginx.

Layer 7 Load Balancing

HAProxy's strength lies in its layer 7 URL-based request filtering capabilities. It's commonly deployed behind LVS or hardware load balancers like F5.

Host Planning

Host Interface IP Purpose
MASTER eth0 192.168.1.81 External management, WAN forwarding
MASTER eth1 192.168.2.81 Internal management, LAN forwarding
MASTER eth2 192.168.3.81 Heartbeat connection (optional)
MASTER vip 192.168.1.181 Application A service
BACKUP eth0 192.168.1.82 External management
BACKUP eth1 192.168.2.82 Internal management
BACKUP eth2 192.168.3.82 Heartbeat connection (optional)
BACKUP vip 192.168.1.182 Application B service

Load Balancing Algorithms

HAProxy provides eight balancing algorithms:

  1. roundrobin - Dynamic weighted round-robin with weight support
  2. static-rr - Static round-robin without weight support
  3. leastconn - Least connections first (recommended)
  4. source - Source IP hashing
  5. uri - URI-based hashing
  6. url_param - URL parameter-based hashing
  7. hdr(name) - HTTP header-based request distribution
  8. rdp-cookie(name) - Cookie-based TCP request hashing

Installation

Dependencies:

yum install gcc gcc-c++ -y

Enable IP Forwarding:

vim /etc/sysctl.conf
net.ipv4.ip_forward = 1
net.ipv4.ip_nonlocal_bind = 1
sysctl -p

Compile from Source:

tar xf haproxy-2.4.tar.gz && cd haproxy-2.4
make TARGET=linux-glibc PREFIX=/opt/haproxy
make install PREFIX=/opt/haproxy

Note: The TARGET parameter should match your kernel version. Refer to the README file in the source directory for specific target options.

Directory Structure and Configuration

Create Directories:

cd /opt/haproxy/
mkdir -p bin conf logs var/run var/chroot

Configure Rsyslog:

vim /etc/rsyslog.conf
$ModLoad imudp
$UDPServerRun 514
local0.* /var/log/haproxy.log

Restart rsyslog:

/etc/init.d/rsyslog restart

Configuration File Structure

Global Section

global
    log 127.0.0.1 local0
    log 127.0.0.1 local1 notice
    maxconn 4096
    user haproxy
    group haproxy
    daemon
    pidfile /opt/haproxy/conf/haproxy.pid
    spread-checks 3
    nbproc 4
    ulimit-n 819200
    chroot /opt/haproxy/var/chroot
    stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin
    stats timeout 2m

Parameters explained:

  • daemon: Run in background
  • nbproc: Number of worker processes (match CPU cores)
  • pidfile: Process ID file location
  • ulimit-n: File descriptor limit
  • chroot: Security jail directory
  • stats socket: Enable runtime management via socket

Defaults Section

defaults
    log global
    mode http
    option httplog
    option dontlognull
    option forwardfor
    option httpclose
    retries 3
    maxconn 4096
    timeout connect 5000
    timeout client 30000
    timeout server 30000
    balance roundrobin

Key options:

  • mode: http (layer 7), tcp (layer 4), or health
  • forwardfor: Inject client IP into X-Forwarded-For header
  • htttpclose: Close connections after each request
  • retries: Failed connection attempts before marking server down

Listen Section for Statistics

listen monitoring
    bind 0.0.0.0:1080
    mode http
    option httplog
    option forwardfor
    maxconn 10
    stats enable
    stats refresh 30s
    stats uri /admin?stats
    stats realm Production\ HAProxy
    stats auth admin:strongpass123
    stats hide-version
    stats admin if TRUE

    server web01 192.168.1.101:80 check port 80 inter 2000 fall 3
    server web02 192.168.1.102:80 check port 80 inter 2000 fall 3

Access the statistics page at: http://IP:1080/admin?stats

Frontend Configuration

frontend web_cluster
    bind *:80
    acl is_static path_beg /images /css /js
    acl is_api path_beg /api
    
    use_backend static_pool if is_static
    use_backend api_pool if is_api
    default_backend dynamic_pool

Backend Configuration

backend dynamic_pool
    mode http
    balance roundrobin
    option httpchk GET /health.html HTTP/1.0
    option httpclose
    option forwardfor
    
    server app01 10.0.1.11:8080 weight 5 check inter 2000 rise 2 fall 3
    server app02 10.0.1.12:8080 weight 3 check inter 2000 rise 2 fall 3
    server app03 10.0.1.13:8080 backup

backend static_pool
    mode http
    balance leastconn
    option httpchk GET /health.html
    
    server static01 10.0.2.11:80 check inter 2000 fall 3
    server static02 10.0.2.12:80 check inter 2000 fall 3

backend api_pool
    mode http
    balance source
    
    server api01 10.0.3.11:8000 check inter 1500 fall 2
    server api02 10.0.3.12:8000 check inter 1500 fall 2

Backend server parameters:

  • check: Enable health monitoring
  • inter: Check interval in milliseconds
  • fall: Failed checks before marking down
  • rise: Successful checks before marking up
  • weight: Traffic weight relative to other servers
  • backup: Activate only when all primary servers fail

Health Checking Options

# Basic HTTP check
option httpchk /index.html

# Check with specific method
option httpchk GET /api/health HTTP/1.1\r\nHost:\ example.com

# TCP check (default port)
option httpchk

Recommendation: Coordinate with developers on which URI to use for health checks, as this provides accountability when issues arise.

SSL/TLS Configuration

global
    maxsslconn 2048
    tune.ssl.default-dh-param 2048

frontend https_in
    bind *:443 ssl crt /etc/ssl/certs/web.pem
    mode http
    default_backend web_pool

Generate a self-signed certificate:

make certbot CERTDIR=/etc/pki/tls/certs

TCP Proxy Configuration

listen mysql_proxy
    bind 0.0.0.0:3306
    mode tcp
    option tcplog
    maxconn 4086
    
    server db01 10.0.10.11:3306 weight 1 check port 3306
    server db02 10.0.10.12:3306 weight 1 check port 3306 backup

ACL Rules

Syntax:

acl <name> <criterion> [flags] [operator] <value>

Domain-Based Routing

acl website_a hdr(host) -i www.example.com
acl website_b hdr(host) -i api.example.com

use_backend service_a if website_a
use_backend service_b if website_b
default_backend service_a

Path-Based Routing

acl img_paths path_beg /images /assets
acl api_paths path_beg /api/v1 /api/v2

use_backend image_servers if img_paths
use_backend api_servers if api_paths

Extension-Based Routing

acl static_files path_end .jpg .png .gif .css .js

use_backend cdn_servers if static_files

Client-Based Routing

acl mobile_client hdr_sub(user-agent) -i iphone android
redirect prefix http://m.example.com if mobile_client

IP-Based Filtering

acl allowed_ips src 10.0.0.0/8 172.16.0.0/12
acl blocked_hosts hdr(host) -i evil.com

http-request allow if allowed_ips
http-request deny if blocked_hosts

301 Redirects

frontend old_site
    bind *:80
    acl legacy_domain hdr(host) -i oldsite.com
    redirect prefix http://newsite.com code 301 if legacy_domain

Logging Client IP Addresses

HAProxy configuration:

option forwardfor

Nginx log format:

log_format forwarded '$http_x_forwarded_for - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "$http_user_agent"';

High Availability

Backup Server Configuration

Activate single backup when all primaries fail:

server primary01 10.0.1.11:80 check
server primary02 10.0.1.12:80 check
server failover01 10.0.1.21:80 backup

Activate all backups simultaneously:

option allbackups
server primary01 10.0.1.11:80 check
server primary02 10.0.1.12:80 check
server failover01 10.0.1.21:80 backup
server failover02 10.0.1.22:80 backup

Handling VIP Binding Issues

If HAProxy fails to bind to a virtual IP, enable non-local binding:

vim /etc/sysctl.conf
net.ipv4.ip_nonlocal_bind = 1
sysctl -p

Dynamic Management

Connect to HAProxy socket for runtime changes:

yum install socat -y
echo "help" | socat stdio /var/lib/haproxy/haproxy.sock

Useful commands:

# Disable a backend server
echo "disable server backend_name/server_name" | socat stdio /var/lib/haproxy/haproxy.sock

# Enable a backend server
echo "enable server backend_name/server_name" | socat stdio /var/lib/haproxy/haproxy.sock

# Show current stats
echo "show info" | socat stdio /var/lib/haproxy/haproxy.sock

Startup and Management

Check configuration:

/opt/haproxy/sbin/haproxy -f /opt/haproxy/conf/haproxy.cfg -c

Start HAProxy:

/opt/haproxy/sbin/haproxy -f /opt/haproxy/conf/haproxy.cfg -D

Graceful restart:

/opt/haproxy/sbin/haproxy -f /opt/haproxy/conf/haproxy.cfg -sf $(cat /opt/haproxy/conf/haproxy.pid)

Stop:

kill $(cat /opt/haproxy/conf/haproxy.pid)

Integration with Keepalived

Keepalived configuraton for MASTER:

vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1
    virtual_ipaddress {
        192.168.1.181
    }
}

Keepalived configuration for BACKUP:

vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    virtual_router_id 51
    priority 90
    advert_int 1
    virtual_ipaddress {
        192.168.1.181
    }
}

Layer 4 + Layer 7 Separation Architecture

For high-performance requirements, separate layer 4 and layer 7 load balancing:

  • LVS handles layer 4 traffic distribution
  • HAProxy handles layer 7 URL-based routing

This approach reduces resource consumption and allows horizontal scaling of HAProxy instances.

Troubleshooting

Compilation error during make install:

If you encounter missing documentation files error:

make TARGET=linux2628 PREFIX=/opt/haproxy
make install TARGET=linux2628 PREFIX=/opt/haproxy

Or edit the Makefile to skip documentation installation.

Warning about multi-process stats:

When nbproc > 1, statistics may be limited. To suppress this warning, set nbproc to 1 or modify the source code in src/cfgparse.c.

Tags: HAProxy load-balancer reverse-proxy high-availability nginx

Posted on Sat, 05 Sep 2026 16:33:34 +0000 by kelharis