HAProxy
High-performance TCP/HTTP load balancer and reverse proxy for distributing traffic across multiple servers.
HAProxy
High-performance TCP/HTTP load balancer and reverse proxy for distributing traffic across multiple servers.
Overview
HAProxy (High Availability Proxy) is a free, open-source load balancer and proxy server for TCP and HTTP-based applications. It's renowned for its reliability, performance, and extensive feature set, making it the de facto standard for high-traffic websites and mission-critical applications. HAProxy operates using an event-driven, single-process model that can handle thousands of concurrent connections with minimal resource usage.
flowchart LR
subgraph "HAProxy Traffic Flow"
A[Client Request] --> B[Frontend]
B --> C{ACL Rules}
C -->|Match| D[Backend Pool 1]
C -->|Default| E[Backend Pool 2]
D --> F[Server 1]
D --> G[Server 2]
E --> H[Server 3]
E --> I[Server 4]
F --> J[Response]
G --> J
H --> J
I --> J
J --> B --> A
end
Configuration Basics
HAProxy configuration uses a hierarchical structure with global settings and proxies (frontends, backends, and listen sections).
Key Concepts
- Global - Process-wide settings (security, performance, logging)
- Defaults - Default values inherited by all proxy sections
- Frontend - Defines how client connections are accepted
- Backend - Defines the pool of servers that handle requests
- Listen - Combines frontend and backend in a single section
- ACL - Access Control Lists for conditional routing
- Stick Tables - In-memory tables for session persistence
flowchart TD
A[haproxy.cfg] --> B[global]
A --> C[defaults]
A --> D[frontend]
A --> E[backend]
A --> F[listen]
D --> G[bind]
D --> H[default_backend]
D --> I[acl + use_backend]
E --> J[balance]
E --> K[server definitions]
E --> L[health checks]
Configuration File Structure
# /etc/haproxy/haproxy.cfg
#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
# Logging configuration
log /dev/log local0
log /dev/log local1 notice
# Process management
daemon
maxconn 50000
user haproxy
group haproxy
# Security settings
chroot /var/lib/haproxy
# Stats socket for runtime management
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
# SSL/TLS settings
ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256
ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets
# Tuning
tune.ssl.default-dh-param 2048
#---------------------------------------------------------------------
# Default settings for all proxies
#---------------------------------------------------------------------
defaults
log global
mode http
option httplog
option dontlognull
option forwardfor
option http-server-close
# Timeouts
timeout connect 5s
timeout client 30s
timeout server 30s
timeout http-request 10s
timeout http-keep-alive 10s
timeout queue 60s
# Error files
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
#---------------------------------------------------------------------
# Frontend: Accept incoming connections
#---------------------------------------------------------------------
frontend http_front
bind *:80
bind *:443 ssl crt /etc/haproxy/certs/combined.pem
# Redirect HTTP to HTTPS
http-request redirect scheme https unless { ssl_fc }
# Default backend
default_backend web_servers
#---------------------------------------------------------------------
# Backend: Define server pools
#---------------------------------------------------------------------
backend web_servers
balance roundrobin
option httpchk GET /health
http-check expect status 200
server web1 192.168.1.10:8080 check
server web2 192.168.1.11:8080 check
server web3 192.168.1.12:8080 check backup
Frontend Configuration
# Basic HTTP frontend
frontend http_front
bind *:80
mode http
default_backend app_servers
# HTTPS frontend with SSL termination
frontend https_front
bind *:443 ssl crt /etc/haproxy/certs/site.pem
mode http
# Add headers for backend
http-request set-header X-Forwarded-Proto https
http-request set-header X-Real-IP %[src]
default_backend app_servers
# Multi-port binding
frontend multi_front
bind *:80
bind *:8080
bind 192.168.1.100:9000
default_backend app_servers
# TCP mode frontend (for databases, etc.)
frontend mysql_front
bind *:3306
mode tcp
default_backend mysql_servers
# Frontend with connection limits
frontend limited_front
bind *:80
maxconn 10000
rate-limit sessions 100
default_backend app_servers
Backend Configuration
# Basic backend with round-robin
backend app_servers
balance roundrobin
server app1 192.168.1.10:8080 check
server app2 192.168.1.11:8080 check
# Backend with weighted servers
backend weighted_servers
balance roundrobin
server app1 192.168.1.10:8080 weight 5 check
server app2 192.168.1.11:8080 weight 3 check
server app3 192.168.1.12:8080 weight 2 check
# Backend with backup servers
backend ha_servers
balance roundrobin
server primary1 192.168.1.10:8080 check
server primary2 192.168.1.11:8080 check
server backup1 192.168.1.20:8080 check backup
server backup2 192.168.1.21:8080 check backup
# Backend with connection limits per server
backend limited_servers
balance roundrobin
server app1 192.168.1.10:8080 maxconn 100 check
server app2 192.168.1.11:8080 maxconn 100 check
# TCP backend for databases
backend mysql_servers
mode tcp
balance roundrobin
server mysql1 192.168.1.30:3306 check
server mysql2 192.168.1.31:3306 check backup
Listen Sections (Combined Frontend/Backend)
# Stats page
listen stats
bind *:8404
mode http
stats enable
stats uri /stats
stats refresh 10s
stats auth admin:password
stats admin if LOCALHOST
# Simple load balancer
listen web_cluster
bind *:80
mode http
balance roundrobin
option httpchk GET /health
server web1 192.168.1.10:8080 check
server web2 192.168.1.11:8080 check
# MySQL cluster
listen mysql_cluster
bind *:3306
mode tcp
balance roundrobin
option mysql-check user haproxy
server mysql1 192.168.1.30:3306 check
server mysql2 192.168.1.31:3306 check
Load Balancing Algorithms
HAProxy offers multiple algorithms to distribute traffic based on different criteria and use cases.
Key Concepts
- Static Algorithms - Server selection based on fixed criteria (hash, weights)
- Dynamic Algorithms - Server selection based on real-time metrics
- Consistent Hashing - Minimises redistribution when servers change
- Session Persistence - Sticky sessions to maintain client-server affinity
flowchart TD
A[Load Balancing Algorithm] --> B{Type}
B -->|Static| C[Round Robin]
B -->|Static| D[Static Round Robin]
B -->|Static| E[Source Hash]
B -->|Dynamic| F[Least Connections]
B -->|Dynamic| G[Random]
B -->|Consistent| H[URI Hash]
B -->|Consistent| I[URL Parameter Hash]
Algorithm Comparison
#---------------------------------------------------------------------
# Round Robin (default)
# Distributes requests sequentially to each server
# Best for: Similar server capacity, stateless applications
#---------------------------------------------------------------------
backend roundrobin_servers
balance roundrobin
server app1 192.168.1.10:8080 check
server app2 192.168.1.11:8080 check
server app3 192.168.1.12:8080 check
#---------------------------------------------------------------------
# Weighted Round Robin
# Distributes based on server weights
# Best for: Mixed server capacities
#---------------------------------------------------------------------
backend weighted_rr_servers
balance roundrobin
server app1 192.168.1.10:8080 weight 100 check # 50% of traffic
server app2 192.168.1.11:8080 weight 50 check # 25% of traffic
server app3 192.168.1.12:8080 weight 50 check # 25% of traffic
#---------------------------------------------------------------------
# Least Connections
# Sends to server with fewest active connections
# Best for: Varying request processing times
#---------------------------------------------------------------------
backend leastconn_servers
balance leastconn
server app1 192.168.1.10:8080 check
server app2 192.168.1.11:8080 check
server app3 192.168.1.12:8080 check
#---------------------------------------------------------------------
# Source IP Hash
# Same client IP always goes to same server
# Best for: Session persistence without cookies
#---------------------------------------------------------------------
backend source_hash_servers
balance source
hash-type consistent
server app1 192.168.1.10:8080 check
server app2 192.168.1.11:8080 check
server app3 192.168.1.12:8080 check
#---------------------------------------------------------------------
# URI Hash
# Same URI always goes to same server
# Best for: Caching servers, CDN origins
#---------------------------------------------------------------------
backend uri_hash_servers
balance uri
hash-type consistent
server cache1 192.168.1.10:8080 check
server cache2 192.168.1.11:8080 check
server cache3 192.168.1.12:8080 check
#---------------------------------------------------------------------
# URL Parameter Hash
# Hash based on URL parameter value
# Best for: Session persistence with session ID in URL
#---------------------------------------------------------------------
backend param_hash_servers
balance url_param sessionid
hash-type consistent
server app1 192.168.1.10:8080 check
server app2 192.168.1.11:8080 check
#---------------------------------------------------------------------
# Header Hash
# Hash based on HTTP header value
# Best for: Routing by custom header (e.g., tenant ID)
#---------------------------------------------------------------------
backend header_hash_servers
balance hdr(X-Tenant-ID)
hash-type consistent
server app1 192.168.1.10:8080 check
server app2 192.168.1.11:8080 check
#---------------------------------------------------------------------
# Random
# Randomly selects a server
# Best for: Large clusters, avoiding hotspots
#---------------------------------------------------------------------
backend random_servers
balance random(2) # Power of two choices
server app1 192.168.1.10:8080 check
server app2 192.168.1.11:8080 check
server app3 192.168.1.12:8080 check
#---------------------------------------------------------------------
# First Available
# Uses first server with available connection slots
# Best for: Active-passive setups
#---------------------------------------------------------------------
backend first_servers
balance first
server primary 192.168.1.10:8080 maxconn 100 check
server secondary 192.168.1.11:8080 maxconn 100 check
Session Persistence (Sticky Sessions)
# Cookie-based persistence (HAProxy inserts cookie)
backend sticky_cookie_servers
balance roundrobin
cookie SERVERID insert indirect nocache
server app1 192.168.1.10:8080 cookie s1 check
server app2 192.168.1.11:8080 cookie s2 check
server app3 192.168.1.12:8080 cookie s3 check
# Cookie-based persistence (use existing app cookie)
backend sticky_app_cookie_servers
balance roundrobin
cookie JSESSIONID prefix nocache
server app1 192.168.1.10:8080 cookie s1 check
server app2 192.168.1.11:8080 cookie s2 check
# Stick table persistence (source IP)
backend stick_table_servers
balance roundrobin
stick-table type ip size 200k expire 30m
stick on src
server app1 192.168.1.10:8080 check
server app2 192.168.1.11:8080 check
# Stick table persistence (cookie value)
backend stick_cookie_table_servers
balance roundrobin
stick-table type string len 32 size 100k expire 30m
stick store-response res.cook(SESSIONID)
stick match req.cook(SESSIONID)
server app1 192.168.1.10:8080 check
server app2 192.168.1.11:8080 check
Health Checks
HAProxy monitors backend server health to ensure traffic only goes to healthy servers.
Key Concepts
- Active Checks - HAProxy actively probes servers
- Passive Checks - Detect failures from real traffic
- Health Check Types - TCP, HTTP, custom scripts
- Check Parameters - Interval, timeout, threshold settings
- Agent Checks - External agent reports server status
stateDiagram-v2
[*] --> UP: Initial State
UP --> DOWN: Failed Checks >= fall
DOWN --> UP: Successful Checks >= rise
UP --> DRAIN: Admin Drain
DRAIN --> UP: Admin Ready
DOWN --> MAINT: Admin Maintenance
MAINT --> UP: Admin Ready
Health Check Configuration
#---------------------------------------------------------------------
# TCP Health Check (Layer 4)
# Simply checks if port is open
#---------------------------------------------------------------------
backend tcp_check_servers
mode tcp
balance roundrobin
option tcp-check
server db1 192.168.1.30:3306 check
server db2 192.168.1.31:3306 check
#---------------------------------------------------------------------
# HTTP Health Check (Layer 7)
# Sends HTTP request and checks response
#---------------------------------------------------------------------
backend http_check_servers
mode http
balance roundrobin
option httpchk GET /health
http-check expect status 200
server app1 192.168.1.10:8080 check
server app2 192.168.1.11:8080 check
# HTTP check with custom headers
backend http_custom_check_servers
mode http
balance roundrobin
option httpchk
http-check send meth GET uri /health hdr Host www.example.com hdr User-Agent HAProxy
http-check expect status 200
server app1 192.168.1.10:8080 check
server app2 192.168.1.11:8080 check
# HTTP check expecting specific content
backend http_content_check_servers
mode http
balance roundrobin
option httpchk GET /health
http-check expect string "OK"
server app1 192.168.1.10:8080 check
server app2 192.168.1.11:8080 check
# HTTP check with regex
backend http_regex_check_servers
mode http
balance roundrobin
option httpchk GET /health
http-check expect rstring "status.*:.*\"healthy\""
server app1 192.168.1.10:8080 check
server app2 192.168.1.11:8080 check
#---------------------------------------------------------------------
# Health Check Parameters
#---------------------------------------------------------------------
backend tuned_check_servers
mode http
balance roundrobin
option httpchk GET /health
# Check every 2 seconds
# Mark DOWN after 3 failures
# Mark UP after 2 successes
# 5 second timeout for checks
server app1 192.168.1.10:8080 check inter 2s fall 3 rise 2
server app2 192.168.1.11:8080 check inter 2s fall 3 rise 2
# Different check interval when down (faster recovery detection)
server app3 192.168.1.12:8080 check inter 5s downinter 1s fall 3 rise 2
#---------------------------------------------------------------------
# MySQL Health Check
#---------------------------------------------------------------------
backend mysql_check_servers
mode tcp
balance roundrobin
option mysql-check user haproxy
server mysql1 192.168.1.30:3306 check
server mysql2 192.168.1.31:3306 check
#---------------------------------------------------------------------
# PostgreSQL Health Check
#---------------------------------------------------------------------
backend postgres_check_servers
mode tcp
balance roundrobin
option pgsql-check user haproxy
server pg1 192.168.1.30:5432 check
server pg2 192.168.1.31:5432 check
#---------------------------------------------------------------------
# Redis Health Check
#---------------------------------------------------------------------
backend redis_check_servers
mode tcp
balance roundrobin
option tcp-check
tcp-check send PING\r\n
tcp-check expect string +PONG
server redis1 192.168.1.40:6379 check
server redis2 192.168.1.41:6379 check
#---------------------------------------------------------------------
# LDAP Health Check
#---------------------------------------------------------------------
backend ldap_check_servers
mode tcp
balance roundrobin
option ldap-check
server ldap1 192.168.1.50:389 check
server ldap2 192.168.1.51:389 check
#---------------------------------------------------------------------
# SMTP Health Check
#---------------------------------------------------------------------
backend smtp_check_servers
mode tcp
balance roundrobin
option smtpchk EHLO haproxy.local
server smtp1 192.168.1.60:25 check
server smtp2 192.168.1.61:25 check
#---------------------------------------------------------------------
# Agent Health Check
# External agent on port 8888 reports: ready, drain, maint, down, up
#---------------------------------------------------------------------
backend agent_check_servers
mode http
balance roundrobin
server app1 192.168.1.10:8080 check agent-check agent-port 8888 agent-inter 5s
server app2 192.168.1.11:8080 check agent-check agent-port 8888 agent-inter 5s
Advanced Health Check Patterns
# Multiple check conditions
backend multi_check_servers
mode http
balance roundrobin
option httpchk
http-check connect
http-check send meth GET uri /health
http-check expect status 200
http-check connect
http-check send meth GET uri /ready
http-check expect status 200
server app1 192.168.1.10:8080 check
server app2 192.168.1.11:8080 check
# SSL health check
backend ssl_check_servers
mode tcp
balance roundrobin
option ssl-hello-chk
server app1 192.168.1.10:443 check
server app2 192.168.1.11:443 check
# Health check on different port
backend alt_port_check_servers
mode http
balance roundrobin
option httpchk GET /health
server app1 192.168.1.10:8080 check port 8081
server app2 192.168.1.11:8080 check port 8081
# Health check to different address
backend alt_addr_check_servers
mode http
balance roundrobin
option httpchk GET /health
server app1 192.168.1.10:8080 check addr 192.168.1.10 port 8081
server app2 192.168.1.11:8080 check addr 192.168.1.11 port 8081
# Observe real traffic for health (passive checks)
backend observe_servers
mode http
balance roundrobin
option httpchk GET /health
# Mark down if 3 consecutive layer7 errors from real traffic
default-server check observe layer7 error-limit 3 on-error mark-down
server app1 192.168.1.10:8080
server app2 192.168.1.11:8080
SSL/TLS Termination
HAProxy can terminate SSL/TLS connections, offloading encryption from backend servers.
Key Concepts
- SSL Termination - Decrypt at load balancer, forward plain HTTP
- SSL Passthrough - Forward encrypted traffic without decryption
- SSL Bridging - Re-encrypt traffic to backend servers
- SNI Routing - Route based on TLS Server Name Indication
- Certificate Management - PEM files with certificate and key
flowchart LR
subgraph "SSL Termination"
A[Client] -->|HTTPS| B[HAProxy]
B -->|HTTP| C[Backend]
end
subgraph "SSL Passthrough"
D[Client] -->|HTTPS| E[HAProxy]
E -->|HTTPS| F[Backend]
end
subgraph "SSL Bridging"
G[Client] -->|HTTPS| H[HAProxy]
H -->|HTTPS| I[Backend]
end
SSL Configuration
# Global SSL settings
global
# Default ciphers for SSL/TLS
ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
# Minimum TLS version
ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets
# Server-side SSL defaults
ssl-default-server-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256
ssl-default-server-options ssl-min-ver TLSv1.2 no-tls-tickets
# DH parameters
tune.ssl.default-dh-param 2048
# SSL cache
tune.ssl.cachesize 50000
tune.ssl.lifetime 300
#---------------------------------------------------------------------
# SSL Termination
# Decrypt HTTPS, forward HTTP to backends
#---------------------------------------------------------------------
frontend https_termination
bind *:443 ssl crt /etc/haproxy/certs/site.pem
mode http
# Add headers for backend awareness
http-request set-header X-Forwarded-Proto https
http-request set-header X-SSL-Client-Verify %[ssl_fc_has_crt]
http-request set-header X-SSL-Client-DN %{+Q}[ssl_c_s_dn]
default_backend app_servers
backend app_servers
mode http
balance roundrobin
server app1 192.168.1.10:8080 check
server app2 192.168.1.11:8080 check
#---------------------------------------------------------------------
# SSL Passthrough (TCP mode)
# Forward encrypted traffic without decryption
#---------------------------------------------------------------------
frontend ssl_passthrough
bind *:443
mode tcp
# Read SNI for routing
tcp-request inspect-delay 5s
tcp-request content accept if { req_ssl_hello_type 1 }
# Route by SNI
use_backend app1_ssl if { req_ssl_sni -i app1.example.com }
use_backend app2_ssl if { req_ssl_sni -i app2.example.com }
default_backend default_ssl
backend app1_ssl
mode tcp
server app1 192.168.1.10:443 check
backend app2_ssl
mode tcp
server app2 192.168.1.11:443 check
#---------------------------------------------------------------------
# SSL Bridging
# Terminate SSL, re-encrypt to backend
#---------------------------------------------------------------------
frontend ssl_bridging
bind *:443 ssl crt /etc/haproxy/certs/site.pem
mode http
default_backend secure_servers
backend secure_servers
mode http
balance roundrobin
# Connect to backends using SSL
server app1 192.168.1.10:443 ssl verify none check
server app2 192.168.1.11:443 ssl verify required ca-file /etc/haproxy/ca.pem check
#---------------------------------------------------------------------
# Multiple Certificates (SNI)
#---------------------------------------------------------------------
frontend multi_cert
# Multiple certs - HAProxy auto-selects based on SNI
bind *:443 ssl crt /etc/haproxy/certs/
# Or specify each certificate
bind *:443 ssl crt /etc/haproxy/certs/site1.pem crt /etc/haproxy/certs/site2.pem
mode http
default_backend app_servers
#---------------------------------------------------------------------
# Client Certificate Authentication
#---------------------------------------------------------------------
frontend client_cert_auth
bind *:443 ssl crt /etc/haproxy/certs/server.pem ca-file /etc/haproxy/certs/ca.pem verify required
mode http
# Pass client cert info to backend
http-request set-header X-SSL-Client-Cert %{+Q}[ssl_c_der,base64]
http-request set-header X-SSL-Client-DN %{+Q}[ssl_c_s_dn]
http-request set-header X-SSL-Client-CN %{+Q}[ssl_c_s_dn(cn)]
http-request set-header X-SSL-Client-Verify %[ssl_c_verify]
default_backend app_servers
# Optional client certificate
frontend optional_client_cert
bind *:443 ssl crt /etc/haproxy/certs/server.pem ca-file /etc/haproxy/certs/ca.pem verify optional
mode http
default_backend app_servers
#---------------------------------------------------------------------
# HTTPS Redirect
#---------------------------------------------------------------------
frontend http_redirect
bind *:80
mode http
http-request redirect scheme https unless { ssl_fc }
default_backend app_servers
# Alternative using ACL
frontend http_redirect_acl
bind *:80
bind *:443 ssl crt /etc/haproxy/certs/site.pem
mode http
acl is_https ssl_fc
http-request redirect scheme https code 301 unless is_https
default_backend app_servers
Certificate File Format
# Combined PEM file format (/etc/haproxy/certs/site.pem)
# Order: Certificate, Intermediate(s), Private Key
-----BEGIN CERTIFICATE-----
[Server Certificate]
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
[Intermediate Certificate]
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
[Private Key]
-----END PRIVATE KEY-----
# Create combined PEM from separate files
cat server.crt intermediate.crt private.key > combined.pem
# For Let's Encrypt
cat /etc/letsencrypt/live/example.com/fullchain.pem \
/etc/letsencrypt/live/example.com/privkey.pem \
> /etc/haproxy/certs/example.com.pem
# Set correct permissions
chmod 600 /etc/haproxy/certs/*.pem
chown haproxy:haproxy /etc/haproxy/certs/*.pem
HSTS and Security Headers
frontend secure_frontend
bind *:443 ssl crt /etc/haproxy/certs/site.pem
mode http
# HSTS - Force HTTPS for 1 year
http-response set-header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
# Security headers
http-response set-header X-Frame-Options "SAMEORIGIN"
http-response set-header X-Content-Type-Options "nosniff"
http-response set-header X-XSS-Protection "1; mode=block"
http-response set-header Referrer-Policy "strict-origin-when-cross-origin"
default_backend app_servers
ACLs and Routing Rules
ACLs (Access Control Lists) enable conditional routing and request manipulation based on various criteria.
Key Concepts
- ACL - Named conditions that evaluate to true or false
- Fetch Methods - Extract data from requests/responses
- Converters - Transform fetched data
- Logical Operators - AND, OR, NOT for combining conditions
- Actions - What to do when conditions match
ACL Syntax and Operators
# ACL definition syntax
# acl <name> <criterion> [flags] [operator] <value>
# Flags
# -i : case-insensitive
# -f : values from file
# -m : matching method (str, beg, end, sub, reg, found)
# -n : forbid DNS resolution
# -u : force unique ID
# Example ACLs
frontend acl_examples
bind *:80
mode http
# Path-based ACLs
acl is_api path_beg /api
acl is_static path_end .css .js .png .jpg .gif
acl is_admin path_beg /admin
acl is_health path /health
# Host-based ACLs
acl host_www hdr(host) -i www.example.com
acl host_api hdr(host) -i api.example.com
acl host_match hdr(host) -m reg ^app[0-9]+\.example\.com$
# Method-based ACLs
acl is_get method GET
acl is_post method POST
acl is_options method OPTIONS
# Header-based ACLs
acl has_auth_header hdr(Authorization) -m found
acl is_json_content hdr(Content-Type) -i application/json
acl is_mobile hdr(User-Agent) -m sub -i mobile android iphone
# Source IP ACLs
acl is_internal src 10.0.0.0/8 192.168.0.0/16 172.16.0.0/12
acl is_blocked src -f /etc/haproxy/blocked_ips.txt
# SSL/TLS ACLs
acl is_ssl ssl_fc
acl has_client_cert ssl_fc_has_crt
# Query parameter ACLs
acl has_debug url_param(debug) -m found
acl is_version_2 url_param(version) 2
# Cookie ACLs
acl has_session cook(SESSIONID) -m found
acl is_beta_user cook(beta) 1
# Connection ACLs
acl too_many_conns fe_conn gt 1000
acl high_traffic fe_req_rate gt 100
default_backend app_servers
Routing with ACLs
frontend routing_frontend
bind *:80
bind *:443 ssl crt /etc/haproxy/certs/
mode http
# Define ACLs
acl is_api path_beg /api
acl is_websocket hdr(Upgrade) -i websocket
acl is_static path_end .css .js .png .jpg .gif .ico .woff .woff2
acl is_admin path_beg /admin
acl host_app1 hdr(host) -i app1.example.com
acl host_app2 hdr(host) -i app2.example.com
# Route to backends based on ACLs
use_backend api_servers if is_api
use_backend websocket_servers if is_websocket
use_backend static_servers if is_static
use_backend admin_servers if is_admin
use_backend app1_servers if host_app1
use_backend app2_servers if host_app2
# Default backend
default_backend main_servers
#---------------------------------------------------------------------
# Complex routing with multiple conditions
#---------------------------------------------------------------------
frontend complex_routing
bind *:443 ssl crt /etc/haproxy/certs/
mode http
# ACLs
acl is_api path_beg /api
acl is_v1 path_beg /api/v1
acl is_v2 path_beg /api/v2
acl is_internal src 10.0.0.0/8
acl is_post method POST
acl is_read method GET HEAD OPTIONS
# Route API versions
use_backend api_v1 if is_v1
use_backend api_v2 if is_v2
# Read/write splitting
use_backend read_servers if is_api is_read
use_backend write_servers if is_api is_post
# Internal-only access
use_backend internal_servers if is_internal
default_backend main_servers
#---------------------------------------------------------------------
# ACL-based access control
#---------------------------------------------------------------------
frontend access_control
bind *:443 ssl crt /etc/haproxy/certs/
mode http
# Define ACLs
acl is_internal src 10.0.0.0/8
acl is_admin path_beg /admin
acl has_api_key hdr(X-API-Key) -m found
acl valid_api_key hdr(X-API-Key) -f /etc/haproxy/valid_api_keys.txt
acl is_blocked src -f /etc/haproxy/blocked_ips.txt
# Block banned IPs
http-request deny if is_blocked
# Require internal network for admin
http-request deny if is_admin !is_internal
# Require valid API key
http-request deny deny_status 401 if !has_api_key
http-request deny deny_status 403 if !valid_api_key
default_backend app_servers
Request Manipulation
frontend request_manipulation
bind *:443 ssl crt /etc/haproxy/certs/
mode http
# ACLs
acl is_api path_beg /api
acl is_legacy path_beg /old-api
# Set headers
http-request set-header X-Forwarded-Proto https
http-request set-header X-Real-IP %[src]
http-request set-header X-Request-ID %[uuid()]
# Add headers
http-request add-header X-Forwarded-Host %[req.hdr(host)]
# Delete headers
http-request del-header X-Powered-By
# Replace a header value (set-header overwrites; replace-header needs a match regex)
http-request set-header User-Agent MyProxy/1.0 if is_api
# URL rewriting
http-request set-path /api/v2%[path] if is_legacy
# Replace path component
http-request replace-path ^/old/(.*) /new/\1
# Set query string
http-request set-query %[query]&source=haproxy
# Redirect
http-request redirect location /maintenance.html if { path / } { src -f /etc/haproxy/maintenance.txt }
http-request redirect scheme https code 301 unless { ssl_fc }
http-request redirect prefix /new code 301 if { path_beg /old }
default_backend app_servers
#---------------------------------------------------------------------
# Response manipulation
#---------------------------------------------------------------------
backend app_servers
mode http
balance roundrobin
# Modify response headers
http-response set-header X-Cache-Status HIT if { res.hdr(X-Cache) -m found }
http-response del-header X-Powered-By
http-response del-header Server
http-response add-header X-Frame-Options SAMEORIGIN
# Replace cookie domain
http-response replace-header Set-Cookie (.*) \1;\ Domain=.example.com
server app1 192.168.1.10:8080 check
server app2 192.168.1.11:8080 check
Rate Limiting with ACLs
frontend rate_limited
bind *:80
mode http
# Define stick table for rate limiting
stick-table type ip size 100k expire 30s store http_req_rate(10s)
# Track requests
http-request track-sc0 src
# Define rate limit ACLs
acl is_abuse sc_http_req_rate(0) gt 100
acl is_api path_beg /api
# Deny abusive IPs
http-request deny deny_status 429 if is_abuse
# Different limits for API
http-request deny deny_status 429 if is_api { sc_http_req_rate(0) gt 50 }
default_backend app_servers
# Rate limiting with multiple tables
# A proxy section can hold only ONE inline stick-table, so additional
# tables live in their own (backend) sections and are referenced by name.
backend per_ip_rates
stick-table type ip size 100k expire 30s store http_req_rate(10s)
backend per_url_rates
stick-table type string size 100k expire 30s store http_req_rate(10s)
frontend multi_rate_limit
bind *:80
mode http
# Track source IP and path against the named tables
http-request track-sc0 src table per_ip_rates
http-request track-sc1 path table per_url_rates
# Apply limits
http-request deny deny_status 429 if { sc_http_req_rate(0) gt 100 }
http-request deny deny_status 429 if { sc_http_req_rate(1) gt 1000 }
default_backend app_servers
Logging and Monitoring
HAProxy provides comprehensive logging and monitoring capabilities for observability and troubleshooting.
Key Concepts
- Log Formats - Predefined and custom log formats
- Log Levels - emerg, alert, crit, err, warning, notice, info, debug
- Stats Page - Real-time web-based statistics
- Stats Socket - Runtime API for monitoring and management
- Prometheus Exporter - Metrics export for monitoring systems
Logging Configuration
global
# Send logs to rsyslog
log /dev/log local0
log /dev/log local1 notice
# Or send to remote syslog server
log 192.168.1.100:514 local0
# Multiple log targets
log 192.168.1.100:514 local0 info
log 192.168.1.101:514 local1 notice
defaults
log global
mode http
# HTTP log format (more detailed than tcplog)
option httplog
# Don't log null connections (health checks, etc.)
option dontlognull
# Log health check status changes
option log-health-checks
# Detailed connection info
option logasap
#---------------------------------------------------------------------
# Custom log formats
#---------------------------------------------------------------------
defaults
log global
mode http
# Default HTTP log format
# option httplog
# Custom log format
log-format "%ci:%cp [%tr] %ft %b/%s %TR/%Tw/%Tc/%Tr/%Ta %ST %B %CC %CS %tsc %ac/%fc/%bc/%sc/%rc %sq/%bq %hr %hs %{+Q}r"
# JSON log format for parsing
log-format '{"client_ip":"%ci","client_port":%cp,"timestamp":"%t","frontend":"%ft","backend":"%b","server":"%s","time_request":%TR,"time_wait":%Tw,"time_connect":%Tc,"time_response":%Tr,"time_total":%Ta,"status":%ST,"bytes_read":%B,"retries":%rc,"request":"%r","captured_headers":"%hr"}'
#---------------------------------------------------------------------
# Per-frontend/backend logging
#---------------------------------------------------------------------
frontend detailed_logging
bind *:80
mode http
# Frontend-specific log
log /dev/log local2
# Capture request headers
capture request header Host len 50
capture request header User-Agent len 100
capture request header X-Forwarded-For len 50
capture request header X-Request-ID len 36
# Capture response headers
capture response header Content-Type len 50
capture response header X-Cache len 10
# Capture cookies
capture cookie SESSIONID len 32
# Log errored requests via a separate log line (frontend-side option)
option log-separate-errors
default_backend app_servers
backend app_servers
mode http
balance roundrobin
# Backend-specific log
log /dev/log local3
server app1 192.168.1.10:8080 check
server app2 192.168.1.11:8080 check
Log Format Variables
# Common log format variables
# %ci - Client IP
# %cp - Client port
# %fi - Frontend IP
# %fp - Frontend port
# %bi - Backend IP
# %bp - Backend port
# %si - Server IP
# %sp - Server port
# %t - Date/time
# %tr - Date/time (request accept)
# %T - Total time (seconds)
# %Ta - Total time (milliseconds)
# %Tc - Time to connect (ms)
# %Tq - Time for client to send request (ms)
# %Tw - Time waiting in queue (ms)
# %Tr - Server response time (ms)
# %ft - Frontend name
# %b - Backend name
# %s - Server name
# %ST - Status code
# %B - Bytes read
# %U - Bytes uploaded
# %r - HTTP request (first line)
# %hr - Captured request headers
# %hs - Captured response headers
# %rc - Retries
# %ts - Termination state
# %ac - Active connections (frontend)
# %fc - Frontend connections
# %bc - Backend connections
# %sc - Server connections
Stats Page Configuration
# Stats in listen section
listen stats
bind *:8404
mode http
stats enable
stats uri /stats
stats refresh 10s
stats show-legends
stats show-node
# Authentication
stats auth admin:secretpassword
stats auth viewer:viewpassword
# Enable admin functions
stats admin if TRUE
# Custom realm
stats realm HAProxy\ Statistics
# Hide HAProxy version
stats hide-version
# Stats in frontend (read-only)
frontend http_front
bind *:80
mode http
# Stats on specific path
stats enable
stats uri /haproxy-stats
stats refresh 5s
default_backend app_servers
# Prometheus metrics endpoint (HAProxy 2.0+)
frontend prometheus
bind *:8405
mode http
http-request use-service prometheus-exporter if { path /metrics }
no log
Stats Socket (Runtime API)
global
# Enable stats socket
stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
stats timeout 30s
# Common socket commands
# Show info
# echo "show info" | socat stdio /run/haproxy/admin.sock
# Show stats
# echo "show stat" | socat stdio /run/haproxy/admin.sock
# Show servers
# echo "show servers state" | socat stdio /run/haproxy/admin.sock
# Disable server
# echo "disable server backend/server1" | socat stdio /run/haproxy/admin.sock
# Enable server
# echo "enable server backend/server1" | socat stdio /run/haproxy/admin.sock
# Set server weight
# echo "set server backend/server1 weight 50" | socat stdio /run/haproxy/admin.sock
# Set server state
# echo "set server backend/server1 state drain" | socat stdio /run/haproxy/admin.sock
# Show session table
# echo "show table stick_table" | socat stdio /run/haproxy/admin.sock
# Clear counters
# echo "clear counters all" | socat stdio /run/haproxy/admin.sock
# Show errors
# echo "show errors" | socat stdio /run/haproxy/admin.sock
Rsyslog Configuration for HAProxy
# /etc/rsyslog.d/49-haproxy.conf
# Create a separate log file for HAProxy
local0.* /var/log/haproxy/haproxy.log
local1.* /var/log/haproxy/haproxy-notice.log
# Separate traffic and admin logs
local2.* /var/log/haproxy/traffic.log
local3.* /var/log/haproxy/admin.log
# Don't send HAProxy logs to messages
local0.none;local1.none;local2.none;local3.none /var/log/messages
# Restart rsyslog
# systemctl restart rsyslog
Monitoring and Alerting
# Prometheus metrics (native in HAProxy 2.0+)
frontend prometheus_exporter
bind *:8405
mode http
http-request use-service prometheus-exporter if { path /metrics }
stats uri /stats
stats refresh 10s
no log
# Sample Prometheus alerts
# groups:
# - name: haproxy
# rules:
# - alert: HAProxyBackendDown
# expr: haproxy_backend_up == 0
# for: 1m
# - alert: HAProxyHighErrorRate
# expr: rate(haproxy_backend_http_responses_total{code="5xx"}[5m]) > 0.05
# for: 5m
# - alert: HAProxyHighLatency
# expr: haproxy_backend_response_time_average_seconds > 1
# for: 5m
# Health check endpoint
frontend health_check
bind *:8406
mode http
monitor-uri /health
# Return 503 if no backend servers are up
acl no_backends nbsrv(app_servers) eq 0
monitor fail if no_backends
Common Patterns for High Availability
Production-ready configurations for highly available deployments.
Key Concepts
- Active-Passive - Primary handles traffic, standby takes over on failure
- Active-Active - Multiple instances share traffic load
- Failover - Automatic transition to backup systems
- Zero-Downtime Deployment - Rolling updates without service interruption
- Blue-Green Deployment - Switch between two identical environments
flowchart TD
subgraph "High Availability Setup"
A[Virtual IP / Keepalived] --> B[HAProxy Primary]
A --> C[HAProxy Standby]
B --> D[Backend Pool]
C --> D
end
Active-Passive with Keepalived
# /etc/keepalived/keepalived.conf (Primary)
vrrp_script chk_haproxy {
script "killall -0 haproxy"
interval 2
weight 2
}
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 101
advert_int 1
authentication {
auth_type PASS
auth_pass secret
}
virtual_ipaddress {
192.168.1.100/24
}
track_script {
chk_haproxy
}
}
# /etc/keepalived/keepalived.conf (Standby)
vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass secret
}
virtual_ipaddress {
192.168.1.100/24
}
track_script {
chk_haproxy
}
}
Production Configuration
global
log /dev/log local0
log /dev/log local1 notice
daemon
maxconn 100000
user haproxy
group haproxy
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
stats timeout 30s
# SSL hardening
ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256
ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets
tune.ssl.default-dh-param 2048
# Performance tuning
tune.bufsize 32768
tune.maxrewrite 4096
defaults
log global
mode http
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.0/8
option redispatch
retries 3
timeout http-request 10s
timeout queue 60s
timeout connect 5s
timeout client 60s
timeout server 60s
timeout http-keep-alive 10s
timeout check 5s
maxconn 50000
# Compression
compression algo gzip
compression type text/html text/plain text/css application/json application/javascript
#---------------------------------------------------------------------
# Stats and monitoring
#---------------------------------------------------------------------
listen stats
bind *:8404
mode http
stats enable
stats uri /stats
stats refresh 10s
stats auth admin:changeme
stats admin if LOCALHOST
#---------------------------------------------------------------------
# HTTP frontend with HTTPS redirect
#---------------------------------------------------------------------
frontend http_front
bind *:80
mode http
# Allow Let's Encrypt challenges
acl is_letsencrypt path_beg /.well-known/acme-challenge/
use_backend letsencrypt if is_letsencrypt
# Redirect everything else to HTTPS
http-request redirect scheme https code 301 unless is_letsencrypt
#---------------------------------------------------------------------
# Main HTTPS frontend
#---------------------------------------------------------------------
frontend https_front
bind *:443 ssl crt /etc/haproxy/certs/ strict-sni
mode http
# Security headers
http-response set-header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
http-response set-header X-Frame-Options "SAMEORIGIN"
http-response set-header X-Content-Type-Options "nosniff"
http-response del-header Server
# Request headers
http-request set-header X-Forwarded-Proto https
http-request set-header X-Real-IP %[src]
http-request set-header X-Request-ID %[uuid()]
# ACLs
acl is_api path_beg /api
acl is_ws hdr(Upgrade) -i websocket
acl is_static path_end .css .js .png .jpg .gif .ico .woff .woff2
# Rate limiting
stick-table type ip size 100k expire 30s store http_req_rate(10s),conn_cur
http-request track-sc0 src
http-request deny deny_status 429 if { sc_http_req_rate(0) gt 100 }
# Routing
use_backend api_servers if is_api
use_backend websocket_servers if is_ws
use_backend static_servers if is_static
default_backend app_servers
#---------------------------------------------------------------------
# Application backend with health checks
#---------------------------------------------------------------------
backend app_servers
mode http
balance roundrobin
option httpchk GET /health
http-check expect status 200
# Sticky sessions via cookie
cookie SERVERID insert indirect nocache
default-server check inter 3s fall 3 rise 2 maxconn 1000
server app1 192.168.1.10:8080 cookie s1
server app2 192.168.1.11:8080 cookie s2
server app3 192.168.1.12:8080 cookie s3
server app4 192.168.1.13:8080 cookie s4 backup
#---------------------------------------------------------------------
# API backend with separate health check
#---------------------------------------------------------------------
backend api_servers
mode http
balance leastconn
option httpchk GET /api/health
http-check expect status 200
# Higher timeouts for API
timeout server 120s
default-server check inter 5s fall 3 rise 2 maxconn 500
server api1 192.168.1.20:3000
server api2 192.168.1.21:3000
server api3 192.168.1.22:3000
#---------------------------------------------------------------------
# WebSocket backend
#---------------------------------------------------------------------
backend websocket_servers
mode http
balance source
option httpchk GET /health
# Long timeout for WebSocket connections
timeout tunnel 3600s
default-server check inter 5s fall 3 rise 2
server ws1 192.168.1.30:8080
server ws2 192.168.1.31:8080
#---------------------------------------------------------------------
# Static content backend
#---------------------------------------------------------------------
backend static_servers
mode http
balance roundrobin
option httpchk HEAD /health
# Cache control
http-response set-header Cache-Control "public, max-age=31536000"
default-server check inter 10s fall 3 rise 2
server static1 192.168.1.40:80
server static2 192.168.1.41:80
#---------------------------------------------------------------------
# Let's Encrypt backend
#---------------------------------------------------------------------
backend letsencrypt
mode http
server letsencrypt 127.0.0.1:8888
Zero-Downtime Deployment
# Blue-Green deployment configuration
frontend https_front
bind *:443 ssl crt /etc/haproxy/certs/
mode http
# ACL for deployment switching
acl blue_deployment path_beg /blue
acl green_deployment path_beg /green
# Manual switch via ACL file
acl use_green src -f /etc/haproxy/green_enabled.txt
use_backend blue_servers unless use_green
use_backend green_servers if use_green
backend blue_servers
mode http
balance roundrobin
option httpchk GET /health
server blue1 192.168.1.10:8080 check
server blue2 192.168.1.11:8080 check
backend green_servers
mode http
balance roundrobin
option httpchk GET /health
server green1 192.168.1.20:8080 check
server green2 192.168.1.21:8080 check
# Rolling update with server drain
# Using runtime API:
# echo "set server app_servers/app1 state drain" | socat stdio /run/haproxy/admin.sock
# Wait for connections to finish...
# Deploy new version to app1
# echo "set server app_servers/app1 state ready" | socat stdio /run/haproxy/admin.sock
# Repeat for app2, app3, etc.
Canary Deployment
frontend https_front
bind *:443 ssl crt /etc/haproxy/certs/
mode http
# ACL for canary routing
acl canary_cookie cook(canary) 1
acl canary_header hdr(X-Canary) 1
# Route canary traffic
use_backend canary_servers if canary_cookie OR canary_header
# Percentage-based canary (10%)
use_backend canary_servers if { rand(100) lt 10 }
default_backend production_servers
backend production_servers
mode http
balance roundrobin
option httpchk GET /health
server prod1 192.168.1.10:8080 check
server prod2 192.168.1.11:8080 check
server prod3 192.168.1.12:8080 check
backend canary_servers
mode http
balance roundrobin
option httpchk GET /health
server canary1 192.168.1.50:8080 check
Multi-Region Configuration
# Global traffic management with geographic routing
frontend global_frontend
bind *:443 ssl crt /etc/haproxy/certs/
mode http
# Geo-based ACLs (using GeoIP module)
acl is_europe src -f /etc/haproxy/geoip/europe.txt
acl is_americas src -f /etc/haproxy/geoip/americas.txt
acl is_asia src -f /etc/haproxy/geoip/asia.txt
# Route by region
use_backend europe_servers if is_europe
use_backend americas_servers if is_americas
use_backend asia_servers if is_asia
# Default to nearest
default_backend americas_servers
backend europe_servers
mode http
balance roundrobin
option httpchk GET /health
server eu1 10.1.1.10:8080 check
server eu2 10.1.1.11:8080 check
# Cross-region backup
server us1 10.2.1.10:8080 check backup
backend americas_servers
mode http
balance roundrobin
option httpchk GET /health
server us1 10.2.1.10:8080 check
server us2 10.2.1.11:8080 check
server eu1 10.1.1.10:8080 check backup
backend asia_servers
mode http
balance roundrobin
option httpchk GET /health
server asia1 10.3.1.10:8080 check
server asia2 10.3.1.11:8080 check
server us1 10.2.1.10:8080 check backup
Quick Reference
Essential Commands
| Command | Description |
|---|---|
haproxy -c -f /etc/haproxy/haproxy.cfg |
Check configuration syntax |
haproxy -f /etc/haproxy/haproxy.cfg -db |
Start in debug mode |
systemctl reload haproxy |
Reload configuration gracefully |
systemctl restart haproxy |
Restart HAProxy service |
haproxy -vv |
Show version and build options |
echo "show info" | socat stdio /run/haproxy/admin.sock |
Show runtime info |
echo "show stat" | socat stdio /run/haproxy/admin.sock |
Show statistics |
echo "show servers state" | socat stdio /run/haproxy/admin.sock |
Show server states |
echo "disable server backend/server1" | socat stdio /run/haproxy/admin.sock |
Disable server |
echo "enable server backend/server1" | socat stdio /run/haproxy/admin.sock |
Enable server |
Load Balancing Algorithms
| Algorithm | Use Case |
|---|---|
roundrobin |
General purpose, equal capacity servers |
leastconn |
Varying request times, long-lived connections |
source |
Session persistence without cookies |
uri |
Caching servers, consistent content routing |
url_param |
Session ID in URL parameter |
hdr(name) |
Route by header value (e.g., tenant ID) |
random |
Large clusters, avoid hotspots |
first |
Active-passive, use first available server |
Key Configuration Directives
| Directive | Context | Description |
|---|---|---|
bind |
frontend, listen | Listen address and port |
mode |
defaults, frontend, backend | Protocol mode (http/tcp) |
balance |
defaults, backend | Load balancing algorithm |
server |
backend, listen | Backend server definition |
default_backend |
frontend | Default routing target |
use_backend |
frontend | Conditional routing |
acl |
frontend, backend | Access control list |
option httpchk |
backend | HTTP health check |
cookie |
backend | Session persistence cookie |
stick-table |
frontend, backend | Session tracking table |
timeout |
defaults, frontend, backend | Various timeout settings |
Common ACL Criteria
| Criterion | Description | Example |
|---|---|---|
path |
Exact path match | path /api |
path_beg |
Path starts with | path_beg /api/ |
path_end |
Path ends with | path_end .jpg .png |
hdr(name) |
Header value | hdr(Host) example.com |
method |
HTTP method | method GET POST |
src |
Source IP | src 10.0.0.0/8 |
ssl_fc |
SSL frontend connection | ssl_fc |
url_param(name) |
URL parameter | url_param(id) -m found |
cook(name) |
Cookie value | cook(SESSIONID) -m found |
Timeout Defaults
| Timeout | Default | Description |
|---|---|---|
connect |
5s | Time to establish connection to server |
client |
50s | Inactivity timeout on client side |
server |
50s | Inactivity timeout on server side |
http-request |
10s | Time for client to send complete request |
http-keep-alive |
1s | Time to wait for new request on keep-alive |
queue |
5s | Time to wait in queue for server slot |
check |
5s | Health check timeout |
tunnel |
1h | Timeout for WebSocket/tunnel connections |
Common Issues and Solutions
| Issue | Cause | Solution |
|---|---|---|
cannot bind socket |
Port already in use or permission denied | Check port usage with netstat -tlnp, run as root for ports < 1024 |
server is DOWN |
Health check failing | Check server logs, verify health endpoint, adjust check parameters |
no server is available |
All servers down or in maintenance | Check backend health, verify server connectivity |
Connection refused |
Backend not listening | Verify backend service is running on specified port |
timeout errors |
Slow backend or network issues | Increase relevant timeout values, check backend performance |
503 Service Unavailable |
No healthy backends | Check health checks, verify backend status |
400 Bad Request |
Malformed HTTP request | Check http-request rules, increase buffer size |
SSL handshake failure |
Certificate issues | Verify certificate chain, check permissions, validate cert format |
too many open files |
File descriptor limit reached | Increase ulimit -n and maxconn |
| Uneven load distribution | Sticky sessions or algorithm choice | Check persistence settings, consider leastconn algorithm |
| Slow response times | Backend bottleneck | Enable compression, check option http-server-close |
Debugging Commands
# Check configuration syntax
haproxy -c -f /etc/haproxy/haproxy.cfg
# Validate configuration and show parsed output
haproxy -c -V -f /etc/haproxy/haproxy.cfg
# Start in debug mode (foreground, verbose)
haproxy -f /etc/haproxy/haproxy.cfg -db
# View error log
tail -f /var/log/haproxy.log
# Check server states
echo "show servers state" | socat stdio /run/haproxy/admin.sock
# View current sessions
echo "show sess" | socat stdio /run/haproxy/admin.sock
# Check for errors
echo "show errors" | socat stdio /run/haproxy/admin.sock
# View stick table contents
echo "show table stick_table" | socat stdio /run/haproxy/admin.sock
# Test backend connectivity
curl -v http://backend-server:port/health
# Check SSL certificate
openssl s_client -connect localhost:443 -servername example.com
# Monitor HAProxy process
watch -n 1 'echo "show info" | socat stdio /run/haproxy/admin.sock | grep -E "^(Cum|Cur|Max)"'
# Check file descriptor usage
ls /proc/$(pidof haproxy)/fd | wc -l
# View process limits
cat /proc/$(pidof haproxy)/limits
Related Topics
The following topics would complement this HAProxy cheatsheet:
- Nginx - Alternative reverse proxy and load balancer with different architecture
- Keepalived - VRRP implementation for HAProxy high availability setups
- Let's Encrypt / Certbot - Free SSL certificate automation for HAProxy
- Prometheus / Grafana - Monitoring HAProxy metrics and creating dashboards
- Docker / Kubernetes - Containerising HAProxy for orchestrated deployments
- Observability Patterns - Distributed tracing and logging strategies