Master HAProxy ACLs: Dynamic Routing, Traffic Splitting, and Real‑Time Updates
This comprehensive guide explains HAProxy ACL fundamentals, showcases powerful routing patterns such as multi‑domain, path‑based, header‑based, and canary releases, provides step‑by‑step configuration examples, scripts for runtime adjustments, best‑practice recommendations, troubleshooting tips, and monitoring strategies for production‑grade load balancing.
Overview
HAProxy ACLs allow fine‑grained traffic routing based on host, path, headers, cookies, IP, etc. They are essential for micro‑service, multi‑tenant and API‑gateway scenarios.
Key Features
Declarative rules : define a condition once and reuse it.
Rich matching methods : exact, prefix, suffix, regex, IP range, and more.
Value extraction : URL, headers, cookies, query parameters, SSL information.
Logical composition : combine ACLs with AND, OR, NOT.
Runtime updates : modify ACLs and map files via the Runtime API without reloading.
Typical Use Cases
Multi‑domain routing
Path‑based routing
Canary / A‑B testing (percentage or header‑based)
Blue‑green deployments
IP whitelist / blacklist
Rate limiting per source IP
Maintenance mode
Environment Requirements
HAProxy 3.0.5 or newer
Linux (Rocky 9.4 or Ubuntu 24.04 LTS) socat for Runtime API communication
ACL Syntax
acl <name> <fetch> [flags] [pattern]Common fetch methods: path, path_beg, hdr(name), cook(name), src, method. Common flags: -i (case‑insensitive), -f (read values from a file), -m with str, beg, end, sub, reg, found.
Configuration Examples
Multi‑Domain Routing
frontend http_front
bind *:80
bind *:443 ssl crt /etc/haproxy/certs/ alpn h2,http/1.1
acl host_api hdr(host) -i api.company.com
acl host_web hdr(host) -i www.company.com
use_backend api_servers if host_api
use_backend web_servers if host_web
default_backend web_servers
backend api_servers
balance roundrobin
server api1 192.168.1.11:8080 check
server api2 192.168.1.12:8080 checkPath‑Based Routing
acl path_api_users path_beg /api/v1/users
acl path_api_orders path_beg /api/v1/orders
use_backend user_service if path_api_users
use_backend order_service if path_api_ordersHeader‑Based Canary Release
acl gray_header hdr(X-Gray-Release) -i true
use_backend canary_servers if gray_header
default_backend stable_serversTraffic Splitting by Percentage
# 10 % canary traffic
acl is_canary rand(100) lt 10
use_backend canary_servers if is_canary
use_backend stable_servers if !is_canaryDynamic Map Files
Map files store key‑value pairs that can be updated at runtime.
# /etc/haproxy/maps/user_canary.map
user_001 canary
user_002 canary
user_003 canaryReference in configuration:
http-request set-var(req.canary) var(req.user_id),map(/etc/haproxy/maps/user_canary.map,stable)
acl is_canary var(req.canary) -m str canary
use_backend canary_servers if is_canaryRuntime Update Scripts
Adjust canary ratio without reload:
#!/bin/bash
SOCKET="/run/haproxy/admin.sock"
set_canary_ratio() {
local ratio=$1
echo "set map /etc/haproxy/maps/canary_ratio.map default $ratio" | socat stdio $SOCKET
}
# Example: ./script.sh set 20 # 20 % canary trafficBlue‑Green Deployment
Active environment stored in a map file ( active_env.map). The frontend reads the map and routes accordingly.
frontend http_front
bind *:80
http-request set-var(req.active_env) str(default),map(/etc/haproxy/maps/active_env.map,blue)
use_backend blue_servers if { var(req.active_env) -m str blue }
use_backend green_servers if { var(req.active_env) -m str green }
default_backend blue_serversSwitch script (simplified):
#!/bin/bash
SOCKET="/run/haproxy/admin.sock"
ENV_MAP="/etc/haproxy/maps/active_env.map"
switch_env() {
local target=$1
echo "set map $ENV_MAP default $target" | socat stdio $SOCKET
}
# Usage: ./blue_green_switch.sh switch blue|greenBest Practices
Naming convention : host_ for domain ACLs, path_ for URL ACLs, is_ for boolean checks, has_ for existence checks.
Order optimization : place the most frequently matched and cheapest checks first; move expensive regex or body parsing to the end.
Use map files for large or frequently changing lists (IP blacklists, tenant routing, canary assignments). They can be updated via the Runtime API.
Avoid redundant extraction : store a value in a variable once and reuse it in multiple ACLs.
Common pitfalls : missing -i makes host matching case‑sensitive; path_beg /api also matches /api123 – add a trailing slash for precise matching; escape dots in regular expressions; use canonical header names.
Troubleshooting & Monitoring
ACL Debug Commands (Bash helper)
#!/bin/bash
SOCKET="/run/haproxy/admin.sock"
show_acls() { echo "show acl" | socat stdio $SOCKET; }
test_acl() { local id=$1 val=$2; echo "get acl #$id $val" | socat stdio $SOCKET; }
# Usage examples:
# ./debug_acl.sh list
# ./debug_acl.sh test 12 "hdr(host) -i example.com"Request Tracing
Add a debug header ( X-Debug: true) and return routing information in response headers. This does not require a configuration reload.
acl debug_mode hdr(X-Debug) -i true
http-response set-header X-Matched-Host %[hdr(host)] if debug_mode
http-response set-header X-Matched-Path %[path] if debug_mode
http-response set-header X-Backend-Name %[be_name] if debug_mode
http-response set-header X-Server-Name %[srv_name] if debug_modePrometheus Metrics
Export backend request rates and canary traffic proportion. Example alert when canary traffic exceeds 20 %:
alert: CanaryTrafficRatioHigh
expr: sum(rate(haproxy_backend_http_requests_total{backend="canary_servers"}[5m]))
/ sum(rate(haproxy_backend_http_requests_total[5m])) > 0.2
for: 5m
labels:
severity: warningBackup Script
#!/bin/bash
BACKUP_DIR="/data/backups/haproxy_acl"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p "$BACKUP_DIR/$DATE"
cp /etc/haproxy/haproxy.cfg "$BACKUP_DIR/$DATE/"
cp -r /etc/haproxy/maps "$BACKUP_DIR/$DATE/"
SOCKET="/run/haproxy/admin.sock"
if [ -S "$SOCKET" ]; then
echo "show acl" | socat stdio $SOCKET > "$BACKUP_DIR/$DATE/runtime_acls.txt"
for map in /etc/haproxy/maps/*.map; do
name=$(basename $map)
echo "show map $map" | socat stdio $SOCKET > "$BACKUP_DIR/$DATE/runtime_${name}.txt"
done
fi
cd "$BACKUP_DIR"
tar -czf "${DATE}.tar.gz" "$DATE"
rm -rf "$DATE"
find "$BACKUP_DIR" -name "*.tar.gz" -mtime +30 -deleteReal‑World Cases
Multi‑Tenant SaaS Routing
Extract tenant ID from sub‑domain, look up tenant_routing.map to select a backend pool, and optionally apply a tenant‑specific canary map.
# Extract tenant ID
http-request set-var(req.tenant_id) hdr(host),regsub(\.saas\.company\.com$,)
# Map tenant → backend
http-request set-var(req.tenant_backend) var(req.tenant_id),map(/etc/haproxy/maps/tenant_routing.map,shared_pool)
# Tenant‑level canary
http-request set-var(req.tenant_canary) var(req.tenant_id),map(/etc/haproxy/maps/tenant_canary.map,stable)
acl tenant_is_canary var(req.tenant_canary) -m str canary
use_backend canary_servers if tenant_is_canary
use_backend %[var(req.tenant_backend)]Blue‑Green Deployment Automation
Map file active_env.map stores the current environment. A Bash script validates backend health, updates the map atomically via the Runtime API, and optionally sends a webhook.
# Switch environment (blue or green)
switch_env() {
local target=$1
# Verify at least two healthy servers in the target backend
healthy=$(echo "show stat" | socat stdio $SOCKET | grep "${target}_servers" | grep UP | wc -l)
if [ "$healthy" -lt 2 ]; then
echo "Not enough healthy servers in $target, abort"
exit 1
fi
echo "set map /etc/haproxy/maps/active_env.map default $target" | socat stdio $SOCKET
# Optional webhook notification
curl -s -X POST http://alert-api/webhook -d "{\"message\":\"Switched to $target\"}"
}
# Usage: ./deploy_switch.sh blueSummary
ACLs are the core of HAProxy traffic control; mastering them enables flexible routing.
Combine fetch methods and flags to express precise matching conditions.
Map files provide a runtime‑updatable data source for tenant routing, canary assignments, IP lists, and more.
Optimize ACL order and avoid heavy regex to keep latency low.
Instrument ACL usage with Prometheus metrics and enable debug headers for fast troubleshooting.
MaGe Linux Operations
Founded in 2009, MaGe Education is a top Chinese high‑end IT training brand. Its graduates earn 12K+ RMB salaries, and the school has trained tens of thousands of students. It offers high‑pay courses in Linux cloud operations, Python full‑stack, automation, data analysis, AI, and Go high‑concurrency architecture. Thanks to quality courses and a solid reputation, it has talent partnerships with numerous internet firms.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
