Available for day contractsFrom 21st September I have availability for day and half day contracts. Please contact for more information.

Contact →
mikepreston.org

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.

HAProxy Traffic FlowMatchDefaultClient RequestFrontendACL RulesBackend Pool 1Backend Pool 2Server 1Server 2Server 3Server 4ResponseHAProxy Traffic FlowMatchDefaultClient RequestFrontendACL RulesBackend Pool 1Backend Pool 2Server 1Server 2Server 3Server 4Response

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
haproxy.cfgglobaldefaultsfrontendbackendlistenbinddefault_backendacl + use_backendbalanceserver definitionshealth checkshaproxy.cfgglobaldefaultsfrontendbackendlistenbinddefault_backendacl + use_backendbalanceserver definitionshealth 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
StaticStaticStaticDynamicDynamicConsistentConsistentLoad BalancingAlgorithmTypeRound RobinStatic Round RobinSource HashLeast ConnectionsRandomURI HashURL Parameter HashStaticStaticStaticDynamicDynamicConsistentConsistentLoad BalancingAlgorithmTypeRound RobinStatic Round RobinSource HashLeast ConnectionsRandomURI HashURL 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
Initial StateFailed Checks >= fallSuccessful Checks >= riseAdmin DrainAdmin ReadyAdmin MaintenanceAdmin ReadyUPDOWNDRAINMAINTInitial StateFailed Checks >= fallSuccessful Checks >= riseAdmin DrainAdmin ReadyAdmin MaintenanceAdmin ReadyUPDOWNDRAINMAINT

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
SSL BridgingHTTPSHTTPSClientHAProxyBackendSSL PassthroughHTTPSHTTPSClientHAProxyBackendSSL TerminationHTTPSHTTPClientHAProxyBackendSSL BridgingHTTPSHTTPSClientHAProxyBackendSSL PassthroughHTTPSHTTPSClientHAProxyBackendSSL TerminationHTTPSHTTPClientHAProxyBackend

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
High Availability SetupVirtual IP /KeepalivedHAProxy PrimaryHAProxy StandbyBackend PoolHigh Availability SetupVirtual IP /KeepalivedHAProxy PrimaryHAProxy StandbyBackend Pool

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:

  1. Nginx - Alternative reverse proxy and load balancer with different architecture
  2. Keepalived - VRRP implementation for HAProxy high availability setups
  3. Let's Encrypt / Certbot - Free SSL certificate automation for HAProxy
  4. Prometheus / Grafana - Monitoring HAProxy metrics and creating dashboards
  5. Docker / Kubernetes - Containerising HAProxy for orchestrated deployments
  6. Observability Patterns - Distributed tracing and logging strategies