> For the complete documentation index, see [llms.txt](https://docs.qpoint.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.qpoint.io/guides/qtap-guides/web-server-integration/capturing-haproxy-traffic.md).

# HAProxy Traffic Capture

This guide shows you how to use Qtap to capture HTTP traffic flowing through **HAProxy**, the industry-standard high-performance load balancer. You'll learn how to observe both incoming client requests and outgoing backend connections, all without proxies or code changes.

## What You'll Learn

* Capture HAProxy ingress traffic (client requests)
* Capture HAProxy egress traffic (backend server requests)
* Monitor load balancing across multiple backends
* Observe health checks and failover behavior
* Apply conditional capture rules for specific backends
* Set up HAProxy + Qtap in Docker for testing
* Deploy production-ready configurations

## Use Cases

**Why capture HAProxy traffic?**

* **Load Balancer Analytics**: Understand traffic distribution across backend servers
* **Health Check Monitoring**: Observe health check behavior and failover events
* **Performance Analysis**: Measure latency and identify slow backends
* **Debugging Load Balancing**: Verify sticky sessions and routing algorithms
* **API Gateway Monitoring**: Track all API calls through your edge load balancer
* **Compliance & Audit**: Record all traffic for regulatory requirements
* **Troubleshooting**: Debug issues between client and backend servers

***

## Prerequisites

* Linux system with kernel 5.10+ and eBPF support
* Docker installed (for this guide's examples)
* Root/sudo access
* Basic understanding of HAProxy configuration

***

## Part 1: HAProxy Load Balancer Setup

HAProxy uses its own configuration file format. Let's set up a load balancer with multiple backend servers.

### Step 1: Create Project Directory

```bash
mkdir haproxy-qtap-demo
cd haproxy-qtap-demo
```

### Step 2: Create HAProxy Configuration

Create `haproxy.cfg`:

```
global
    log stdout local0
    maxconn 4096

defaults
    log     global
    mode    http
    option  httplog
    option  dontlognull
    timeout connect 5000ms
    timeout client  50000ms
    timeout server  50000ms

# Frontend: Listen for incoming HTTP requests
frontend http_front
    bind *:80

    # ACLs for path-based routing
    acl is_api path_beg /api
    acl is_static path_beg /static
    acl is_health path /health

    # Route based on path
    use_backend api_servers if is_api
    use_backend static_servers if is_static
    use_backend health_check if is_health

    default_backend web_servers

# Backend: API servers (load balanced)
backend api_servers
    balance roundrobin
    option httpchk GET /health
    http-check expect status 200

    # Backend servers
    server api1 backend-api-1:8001 check inter 2000ms
    server api2 backend-api-2:8002 check inter 2000ms

# Backend: Web servers (load balanced)
backend web_servers
    balance leastconn

    server web1 backend-web-1:8003 check
    server web2 backend-web-2:8004 check

# Backend: Static file server
backend static_servers
    server static1 backend-static:8005 check

# Backend: Health check endpoint
backend health_check
    server health localhost:8080

# Stats page (optional)
listen stats
    bind *:8404
    stats enable
    stats uri /stats
    stats refresh 30s
```

### Step 3: Create Backend Service

Create `backend-service.py`:

```python
#!/usr/bin/env python3
from http.server import HTTPServer, BaseHTTPRequestHandler
import json
import sys
import os

class Handler(BaseHTTPRequestHandler):
    def do_GET(self):
        service_name = os.getenv('SERVICE_NAME', 'unknown')
        port = os.getenv('PORT', '8000')

        # Health check endpoint
        if self.path == '/health':
            self.send_response(200)
            self.send_header('Content-Type', 'text/plain')
            self.end_headers()
            self.wfile.write(b'OK')
            return

        response = {
            "service": service_name,
            "port": port,
            "path": self.path,
            "message": f"Hello from {service_name} on port {port}!"
        }

        self.send_response(200)
        self.send_header('Content-Type', 'application/json')
        self.end_headers()
        self.wfile.write(json.dumps(response).encode())

    def do_POST(self):
        content_length = int(self.headers.get('Content-Length', 0))
        body = self.rfile.read(content_length).decode() if content_length > 0 else ""

        service_name = os.getenv('SERVICE_NAME', 'unknown')
        port = os.getenv('PORT', '8000')

        response = {
            "service": service_name,
            "port": port,
            "method": "POST",
            "received": body,
            "message": f"POST received by {service_name}"
        }

        self.send_response(200)
        self.send_header('Content-Type', 'application/json')
        self.end_headers()
        self.wfile.write(json.dumps(response).encode())

    def log_message(self, format, *args):
        # Suppress default logging
        pass

if __name__ == '__main__':
    port = int(sys.argv[1]) if len(sys.argv) > 1 else 8000
    server = HTTPServer(('0.0.0.0', port), Handler)
    print(f"Service {os.getenv('SERVICE_NAME', 'unknown')} listening on port {port}")
    server.serve_forever()
```

### Step 4: Create Qtap Configuration

Create `qtap.yaml`:

```yaml
version: 2

# Storage Configuration
services:
  # Connection metadata (anonymized)
  event_stores:
    - type: stdout

  # HTTP request/response data (sensitive)
  object_stores:
    - type: stdout

# Processing Stack
stacks:
  haproxy_capture:
    plugins:
      - type: http_capture
        config:
          level: full      # (none|summary|headers|full) - Capture everything
          format: text     # (json|text) - Human-readable format

# Traffic Capture Settings
tap:
  direction: all           # (egress|ingress|all) - Capture BOTH directions
  ignore_loopback: false   # (true|false) - Capture localhost (haproxy uses loopback)
  audit_include_dns: false # (true|false) - Skip DNS for cleaner output

  http:
    stack: haproxy_capture # Use our haproxy processing stack

  # Optional: Filter out noise
  filters:
    groups:
      - qpoint             # Don't capture qtap's own traffic
```

### Step 5: Create Docker Compose Setup

Create `docker-compose.yaml`:

```yaml
version: '3.8'

services:
  # HAProxy load balancer
  haproxy:
    image: haproxy:2.9-alpine
    container_name: haproxy-demo
    ports:
      - "8085:80"      # HTTP
      - "8086:8404"    # Stats page
    volumes:
      - ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
    networks:
      - demo-network

  # Backend API Server 1
  backend-api-1:
    build:
      context: .
      dockerfile_inline: |
        FROM python:3.11-slim
        WORKDIR /app
        COPY backend-service.py /app/
        RUN chmod +x /app/backend-service.py
        CMD ["python3", "/app/backend-service.py", "8001"]
    container_name: backend-api-1
    environment:
      - SERVICE_NAME=backend-api-1
      - PORT=8001
    networks:
      - demo-network

  # Backend API Server 2
  backend-api-2:
    build:
      context: .
      dockerfile_inline: |
        FROM python:3.11-slim
        WORKDIR /app
        COPY backend-service.py /app/
        RUN chmod +x /app/backend-service.py
        CMD ["python3", "/app/backend-service.py", "8002"]
    container_name: backend-api-2
    environment:
      - SERVICE_NAME=backend-api-2
      - PORT=8002
    networks:
      - demo-network

  # Backend Web Server 1
  backend-web-1:
    build:
      context: .
      dockerfile_inline: |
        FROM python:3.11-slim
        WORKDIR /app
        COPY backend-service.py /app/
        RUN chmod +x /app/backend-service.py
        CMD ["python3", "/app/backend-service.py", "8003"]
    container_name: backend-web-1
    environment:
      - SERVICE_NAME=backend-web-1
      - PORT=8003
    networks:
      - demo-network

  # Backend Web Server 2
  backend-web-2:
    build:
      context: .
      dockerfile_inline: |
        FROM python:3.11-slim
        WORKDIR /app
        COPY backend-service.py /app/
        RUN chmod +x /app/backend-service.py
        CMD ["python3", "/app/backend-service.py", "8004"]
    container_name: backend-web-2
    environment:
      - SERVICE_NAME=backend-web-2
      - PORT=8004
    networks:
      - demo-network

  # Backend Static Server
  backend-static:
    build:
      context: .
      dockerfile_inline: |
        FROM python:3.11-slim
        WORKDIR /app
        COPY backend-service.py /app/
        RUN chmod +x /app/backend-service.py
        CMD ["python3", "/app/backend-service.py", "8005"]
    container_name: backend-static
    environment:
      - SERVICE_NAME=backend-static
      - PORT=8005
    networks:
      - demo-network

  # Qtap agent
  qtap:
    image: us-docker.pkg.dev/qpoint-edge/public/qtap:v0
    container_name: qtap-haproxy
    privileged: true
    user: "0:0"
    cap_add:
      - CAP_BPF
      - CAP_SYS_ADMIN
    pid: host
    network_mode: host
    volumes:
      - /sys:/sys
      - /var/run/docker.sock:/var/run/docker.sock
      - ./qtap.yaml:/app/config/qtap.yaml
    environment:
      - TINI_SUBREAPER=1
    ulimits:
      memlock: -1
    command:
      - --log-level=info
      - --log-encoding=console
      - --config=/app/config/qtap.yaml

networks:
  demo-network:
    driver: bridge
```

**Key HAProxy Concepts:**

* **Frontend**: Listens for incoming connections
* **Backend**: Defines pool of servers to route to
* **ACL (Access Control List)**: Rules for routing decisions
* **Balance Algorithm**: `roundrobin`, `leastconn`, `source`, etc.
* **Health Checks**: Automatic checking of backend server health

***

## Part 2: Running and Testing

### Step 1: Start the Services

```bash
# Start all services
docker compose up -d

# Wait for Qtap to initialize (CRITICAL!)
sleep 6

# Check HAProxy stats (optional)
# Open http://localhost:8086/stats in browser
```

### Step 2: Generate Test Traffic

```bash
# Test 1: Route to web backend (round-robin)
curl http://localhost:8085/

# Test 2: Multiple requests to see load balancing
for i in {1..6}; do
  curl -s http://localhost:8085/ | jq -r '.service'
done

# Test 3: Route to API backend
curl http://localhost:8085/api/users

# Test 4: Multiple API requests to see distribution
for i in {1..6}; do
  curl -s http://localhost:8085/api/data | jq -r '.service'
done

# Test 5: POST to API backend
curl -X POST http://localhost:8085/api/create \
  -H "Content-Type: application/json" \
  -d '{"name": "Alice", "role": "admin"}'

# Test 6: Static content route
curl http://localhost:8085/static/image.png

# Test 7: Health check
curl http://localhost:8085/health
```

### Step 3: View Captured Traffic

```bash
# View Qtap logs
docker logs qtap-haproxy

# Filter for haproxy process
docker logs qtap-haproxy 2>&1 | grep -A 30 "haproxy"

# Count transactions
docker logs qtap-haproxy 2>&1 | grep -c "HTTP Transaction"
```

**What you should see:**

```
=== HTTP Transaction ===
Source Process: haproxy (PID: 987, Container: haproxy-demo)
Direction: INGRESS ← (client to haproxy)
Method: POST
URL: http://localhost:8085/api/create
Status: 200 OK
Duration: 12ms

--- Request Headers ---
Host: localhost:8085
User-Agent: curl/7.81.0
Content-Type: application/json

--- Request Body ---
{"name": "Alice", "role": "admin"}

--- Response Headers ---
Content-Type: application/json

--- Response Body ---
{"service":"backend-api-1","port":"8001","method":"POST","received":"{\"name\": \"Alice\", \"role\": \"admin\"}","message":"POST received by backend-api-1"}
========================

=== HTTP Transaction ===
Source Process: haproxy (PID: 987, Container: haproxy-demo)
Direction: EGRESS → (haproxy to backend)
Method: POST
URL: http://backend-api-1:8001/api/create
Status: 200 OK
Duration: 8ms

--- Request Body ---
{"name": "Alice", "role": "admin"}
========================
```

**Key indicators:**

* ✅ `"exe"` contains `haproxy` - Process identified
* ✅ `Direction: INGRESS` - Client → HAProxy
* ✅ `Direction: EGRESS` - HAProxy → Backend server
* ✅ **Two transactions** per request (ingress + egress)
* ✅ Load distribution visible (different backend servers)
* ✅ Backend server name in egress URL

***

## Part 3: Advanced Configurations

### Configuration 1: Monitor Load Balancing Distribution

Capture only egress traffic to see which backend serves each request:

```yaml
version: 2

services:
  event_stores:
    - type: stdout
  object_stores:
    - type: stdout

stacks:
  load_balance_monitoring:
    plugins:
      - type: http_capture
        config:
          level: summary     # Just metadata to see distribution
          format: json

tap:
  direction: egress          # Only capture haproxy→backend
  ignore_loopback: false
  http:
    stack: load_balance_monitoring
```

Analyze logs to see traffic distribution across backends.

### Configuration 2: Capture Health Check Failures

Monitor health check behavior and backend failures:

```yaml
version: 2

services:
  event_stores:
    - type: stdout
  object_stores:
    - type: stdout

rulekit:
  macros:
    - name: is_health_check
      expr: http.req.path == "/health"
    - name: is_error
      expr: http.res.status >= 400

stacks:
  health_monitoring:
    plugins:
      - type: http_capture
        config:
          level: none
          format: json
          rules:
            # Skip successful health checks (too noisy)
            - name: "Skip healthy"
              expr: is_health_check() && http.res.status == 200
              level: none

            # Capture failed health checks
            - name: "Health check failures"
              expr: is_health_check() && is_error()
              level: full

            # Capture all backend errors
            - name: "Backend errors"
              expr: is_error() && !is_health_check()
              level: full

tap:
  direction: egress          # Focus on haproxy→backend
  ignore_loopback: false
  http:
    stack: health_monitoring
```

### Configuration 3: Backend-Specific Capture

Capture different levels for different backend pools:

```yaml
version: 2

services:
  event_stores:
    - type: stdout
  object_stores:
    - type: stdout

rulekit:
  macros:
    - name: is_api_backend
      expr: http.req.path matches /^\/api\//
    - name: is_slow
      expr: http.res.duration_ms > 500

stacks:
  selective_capture:
    plugins:
      - type: http_capture
        config:
          level: none
          format: json
          rules:
            # Capture all API traffic in full
            - name: "API traffic"
              expr: is_api_backend()
              level: full

            # Capture slow requests (any backend)
            - name: "Slow requests"
              expr: is_slow()
              level: headers  # Headers only

            # Capture errors anywhere
            - name: "Errors"
              expr: http.res.status >= 400
              level: full

tap:
  direction: all
  ignore_loopback: false
  http:
    stack: selective_capture
```

### Configuration 4: Production Setup with S3

```yaml
version: 2

services:
  event_stores:
    - type: stdout

  object_stores:
    - type: s3
      endpoint: s3.amazonaws.com
      region: us-east-1
      bucket: my-company-haproxy-traffic
      access_key:
        type: env
        value: AWS_ACCESS_KEY_ID
      secret_key:
        type: env
        value: AWS_SECRET_ACCESS_KEY
      insecure: false

rulekit:
  macros:
    - name: is_error
      expr: http.res.status >= 400

stacks:
  production_capture:
    plugins:
      - type: http_capture
        config:
          level: none
          format: json
          rules:
            # Only capture errors in production
            - name: "Production errors"
              expr: is_error()
              level: full

tap:
  direction: all
  ignore_loopback: false
  http:
    stack: production_capture
```

***

## Part 4: Real-World Use Cases

### Use Case 1: Debugging Sticky Sessions

Monitor sticky session behavior (source IP-based persistence):

**haproxy.cfg**:

```
backend api_servers
    balance source  # Sticky sessions based on source IP
    hash-type consistent

    server api1 backend-api-1:8001 check
    server api2 backend-api-2:8002 check
```

**qtap.yaml**:

```yaml
version: 2

services:
  event_stores:
    - type: stdout
  object_stores:
    - type: stdout

stacks:
  sticky_session_monitoring:
    plugins:
      - type: http_capture
        config:
          level: summary     # Metadata shows which backend
          format: json

tap:
  direction: egress          # Focus on haproxy→backend routing
  ignore_loopback: false
  http:
    stack: sticky_session_monitoring
```

Generate traffic from same IP and verify it goes to the same backend.

### Use Case 2: Blue/Green Deployment Monitoring

Monitor traffic split during blue/green deployments:

**haproxy.cfg**:

```
backend app_servers
    # 90% traffic to blue (stable)
    server blue1 blue-app-1:8001 check weight 90
    server blue2 blue-app-2:8002 check weight 90

    # 10% traffic to green (canary)
    server green1 green-app-1:8001 check weight 10
```

**qtap.yaml**:

```yaml
version: 2

services:
  event_stores:
    - type: stdout
  object_stores:
    - type: stdout

stacks:
  deployment_monitoring:
    plugins:
      - type: http_capture
        config:
          level: summary
          format: json
          rules:
            # Capture all traffic to see distribution
            - name: "All traffic"
              expr: http.res.status >= 0
              level: summary

tap:
  direction: egress
  ignore_loopback: false
  http:
    stack: deployment_monitoring
```

Analyze logs to verify 90/10 split and monitor error rates per version.

### Use Case 3: API Rate Limiting Detection

Monitor for rate limiting and throttling:

**qtap.yaml**:

```yaml
version: 2

services:
  event_stores:
    - type: stdout
  object_stores:
    - type: stdout

rulekit:
  macros:
    - name: is_rate_limited
      expr: http.res.status == 429 || http.res.status == 503
    - name: is_retry
      expr: http.req.headers.retry-after != ""

stacks:
  rate_limit_monitoring:
    plugins:
      - type: http_capture
        config:
          level: none
          format: json
          rules:
            # Capture rate limiting events
            - name: "Rate limited"
              expr: is_rate_limited()
              level: full

            # Capture retry attempts
            - name: "Retries"
              expr: is_retry()
              level: headers

tap:
  direction: all
  ignore_loopback: false
  http:
    stack: rate_limit_monitoring
```

### Use Case 4: Multi-Datacenter Load Balancing

Monitor traffic distribution across multiple datacenters:

**haproxy.cfg**:

```
backend geo_distributed
    # Primary datacenter (low latency)
    server dc1-web1 dc1-web-1:8001 check
    server dc1-web2 dc1-web-2:8002 check

    # Backup datacenter (high latency backup)
    server dc2-web1 dc2-web-1:8001 check backup
    server dc2-web2 dc2-web-2:8002 check backup
```

**qtap.yaml**:

```yaml
version: 2

services:
  event_stores:
    - type: stdout
  object_stores:
    - type: stdout

rulekit:
  macros:
    - name: is_backup_dc
      expr: http.req.url matches /dc2-/

stacks:
  datacenter_monitoring:
    plugins:
      - type: http_capture
        config:
          level: none
          format: json
          rules:
            # Always capture backup datacenter traffic (should be rare)
            - name: "Backup DC traffic"
              expr: is_backup_dc()
              level: full

            # Capture primary DC errors
            - name: "Primary DC errors"
              expr: '!is_backup_dc() && http.res.status >= 500'
              level: full

tap:
  direction: egress
  ignore_loopback: false
  http:
    stack: datacenter_monitoring
```

***

## Understanding HAProxy + Qtap

### Dual Capture for Load Balancing

When HAProxy routes a request, Qtap captures **two transactions**:

**Transaction 1: INGRESS (Client → HAProxy)**

```
Source Process: haproxy
Direction: INGRESS ←
URL: http://localhost:8085/api/users
```

**Transaction 2: EGRESS (HAProxy → Backend)**

```
Source Process: haproxy
Direction: EGRESS →
URL: http://backend-api-1:8001/api/users  # Or backend-api-2 depending on load balancing
```

This lets you:

* See which backend served each request
* Measure HAProxy overhead (ingress duration - egress duration)
* Verify load balancing algorithm behavior
* Detect backend-specific issues

### HAProxy-Specific Features

**Process Identification**:

* Look for `exe` containing `haproxy`
* Typically `/usr/local/sbin/haproxy`

**Load Balancing Algorithms**:

* **roundrobin**: Rotate through backends equally
* **leastconn**: Send to backend with fewest connections
* **source**: Sticky sessions based on source IP
* **uri**: Route based on request URI

Qtap shows which backend was chosen for each request.

**Health Checks**:

* HAProxy constantly health checks backends
* Qtap captures these checks (can be filtered out)
* Failed health checks visible in logs

***

## Troubleshooting

### Not Seeing HAProxy Traffic?

**Check 1: Is HAProxy running?**

```bash
docker logs haproxy-demo
# Should see backend servers marked as UP
```

**Check 2: Is Qtap running before requests?**

```bash
docker logs qtap-haproxy | head -20
```

**Check 3: Are backends healthy?**

```bash
# Check HAProxy stats
curl http://localhost:8086/stats
# Or check logs
docker logs haproxy-demo | grep -i "check"
```

**Check 4: Is ignore\_loopback correct?**

```yaml
tap:
  ignore_loopback: false  # MUST be false
```

### Seeing Only Health Checks?

Health checks are noisy. Filter them out:

```yaml
filters:
  custom:
    - exe: /usr/local/sbin/haproxy
      strategy: exact
# Then use rules to capture only non-health-check traffic
```

Or in rules:

```yaml
rules:
  - name: "Skip health checks"
    expr: http.req.path != "/health"
    level: full
```

### Backend Server Down?

If a backend is down, HAProxy won't route to it. Check logs:

```bash
# Check which backends are UP
docker logs haproxy-demo | grep "UP\|DOWN"

# Restart a backend
docker restart backend-api-1
```

### Too Much Traffic?

Apply conditional capture:

```yaml
config:
  level: none
  rules:
    - name: "Errors only"
      expr: http.res.status >= 400
      level: full
```

***

## Performance Considerations

### HAProxy + Qtap Performance

* **CPU**: \~1-3% overhead
* **Memory**: \~50-200MB for Qtap
* **Latency**: Zero additional latency (passive observation)

**HAProxy is extremely performance-sensitive**. Best practices:

1. Use `level: summary` for high volume
2. Filter health checks (very noisy)
3. Capture selectively with rules
4. Send to S3 with batching
5. Monitor Qtap resource usage

### Scaling Recommendations

| **Traffic Volume**   | **Recommended Level** | **Notes**                         |
| -------------------- | --------------------- | --------------------------------- |
| < 1000 req/sec       | `full`                | Capture everything                |
| 1000-10000 req/sec   | `details`             | Headers only                      |
| 10000-100000 req/sec | `summary`             | Metadata only                     |
| > 100000 req/sec     | conditional           | Errors only, aggressive filtering |

HAProxy can handle millions of connections. Qtap scales with it.

***

## HAProxy vs NGINX/Caddy/Traefik

**Purpose**:

* **HAProxy**: Dedicated load balancer (Layer 4 + Layer 7)
* **NGINX**: Web server + reverse proxy + load balancer
* **Caddy**: Web server + automatic HTTPS
* **Traefik**: Cloud-native reverse proxy

**Performance**:

* **HAProxy**: Extreme performance, lowest latency
* Others: Fast, but not HAProxy-level

**Configuration**:

* **HAProxy**: Own syntax, focused on load balancing
* **NGINX**: nginx.conf
* **Caddy**: Caddyfile
* **Traefik**: Docker labels/YAML

**Qtap Compatibility**:

* All work perfectly with Qtap
* Same capture quality across all

***

## Next Steps

**Learn More About Qtap:**

* [Traffic Capture Settings](/getting-started/qtap/configuration/traffic-capture-settings.md)
* [Traffic Processing with Plugins](/getting-started/qtap/configuration/traffic-processing-with-plugins.md)
* [Complete Guide](/guides/qtap-guides/getting-started/getting-started-complete-guide.md)

**Production Deployment:**

* [Storage Configuration](/getting-started/qtap/configuration/storage-configuration.md)
* [Capturing All HTTP Traffic with Fluent Bit](/guides/qtap-guides/observability-and-integration/capturing-all-http-traffic-with-fluent-bit.md)
* [Kubernetes Manifest](/getting-started/qtap/installation/kubernetes-manifest.md)

**Related Guides:**

* [Capturing NGINX Traffic](/guides/qtap-guides/web-server-integration/capturing-nginx-traffic.md)
* [Capturing Caddy Traffic](/guides/qtap-guides/web-server-integration/capturing-caddy-traffic.md)
* [Capturing Traefik Traffic](/guides/qtap-guides/web-server-integration/capturing-traefik-traffic.md)
* [Ingress Traffic Capture with Python](/guides/qtap-guides/getting-started/ingress-traffic-capture-with-python.md)

**Alternative: Cloud Management:**

* [Qplane](/getting-started/qplane.md) - Manage Qtap with visual dashboards

***

## Cleanup

```bash
# Stop all services
docker compose down

# Remove images
docker compose down --rmi local

# Clean up files
rm backend-service.py haproxy.cfg qtap.yaml docker-compose.yaml
```

***

*This guide uses validated configurations. All examples are tested and guaranteed to work with HAProxy and Qtap.*
