haproxy/readme.md
Simon Cornet bf46e6340e
All checks were successful
ci/woodpecker/push/linting Pipeline was successful
style(readme): align markdown tables
2026-05-15 13:04:17 +02:00

14 KiB

Ansible Role: HAProxy

Install and configure HAProxy load balancer with flexible frontends, backends, and stats.

Variables

Global Settings

Variable Required Default Description
haproxy_global.log No List with /dev/log local2 Log target (string or list)
haproxy_global.stats_socket No See defaults Stats socket configuration
haproxy_global.stats_timeout No Empty Stats timeout (optional, e.g., "30s")
haproxy_global.chroot No /var/lib/haproxy Chroot directory
haproxy_global.user No haproxy User to run as
haproxy_global.group No haproxy Group to run as
haproxy_global.daemon No true Run as daemon
haproxy_global.pidfile No /var/run/haproxy.pid PID file location (optional)
haproxy_global.maxconn No 35000 Maximum connections (optional)

Default Settings

Variable Required Default Description
haproxy_defaults.log No global Log setting
haproxy_defaults.mode No tcp Default mode (tcp/http)
haproxy_defaults.options No List with tcplog Options list (or use option for single)
haproxy_defaults.timeout_check No 5s Health check timeout (optional)
haproxy_defaults.timeout_connect No 10s Connection timeout
haproxy_defaults.timeout_client No 600s Client timeout
haproxy_defaults.timeout_server No 600s Server timeout
haproxy_defaults.timeout_tunnel No Empty Tunnel timeout (optional)

Stats Listener

Variable Required Default Description
haproxy_stats.enabled No false Enable stats interface
haproxy_stats.bind No 192.168.32.10:9000 Bind address for stats
haproxy_stats.mode No http Stats mode
haproxy_stats.uri No / Stats URI path
haproxy_stats.show_node No true Show node name
haproxy_stats.refresh No 10s Refresh interval
haproxy_stats.auth No admin:password Basic auth credentials

Frontends

Variable Required Default Description
haproxy_frontends No [] List of frontends
haproxy_frontends[].name Yes - Frontend name
haproxy_frontends[].bind Yes - Bind address and port
haproxy_frontends[].default_backend Yes - Default backend name
haproxy_frontends[].mode No - Override default mode
haproxy_frontends[].options No [] Additional options

Backends

Variable Required Default Description
haproxy_backends No [] List of backends
haproxy_backends[].name Yes - Backend name
haproxy_backends[].balance No - Load balancing algorithm
haproxy_backends[].hash_type No - Hash type for balancing
haproxy_backends[].mode No - Override default mode
haproxy_backends[].stick_table No - Stick table configuration
haproxy_backends[].acls No [] List of ACL rules
haproxy_backends[].tcp_request No [] TCP request rules
haproxy_backends[].tcp_response No [] TCP response rules
haproxy_backends[].stick No [] Stick rules
haproxy_backends[].options No [] Additional options
haproxy_backends[].http_check No [] HTTP health check directives
haproxy_backends[].tcp_check No [] TCP health check directives
haproxy_backends[].servers Yes - List of backend servers
haproxy_backends[].servers[].name Yes - Server name
haproxy_backends[].servers[].address Yes - Server address:port
haproxy_backends[].servers[].check No false Enable health checks
haproxy_backends[].servers[].check_port No - Health check port (if different)
haproxy_backends[].servers[].send_proxy No false Enable send-proxy
haproxy_backends[].servers[].extra_params No - Additional server parameters

Examples

Teleport Example

Configuration for Teleport with SSL session persistence and advanced health checks:

---
- name: "Deploy HAProxy for Teleport"
  hosts: "haproxy_servers"
  become: true

  vars:

    # global settings with multiple log targets
    haproxy_global:
      log:
        - "/dev/log local0"
        - "/dev/log local1 notice"
      stats_socket: "/var/lib/haproxy/stats level admin"
      chroot: "/var/lib/haproxy"
      user: "haproxy"
      group: "haproxy"
      daemon: true

    # defaults with multiple options
    haproxy_defaults:
      log: "global"
      mode: "tcp"
      options:
        - "httplog"
        - "dontlognull"
      timeout_connect: "5000"
      timeout_client: "10m"
      timeout_server: "10m"
      timeout_tunnel: "10m"

    # frontends
    haproxy_frontends:
      - name: "hafrontend"
        bind: "*:443"
        mode: "tcp"
        default_backend: "teleport"

    # backends with http-check and tcp-check
    haproxy_backends:
      - name: "teleport"
        mode: "tcp"
        balance: "roundrobin"
        stick_table: "type binary len 2048 size 300k expire 30m"
        acls:
          - "clienthello req.ssl_hello_type 1"
          - "serverhello res.ssl_hello_type 2"
        tcp_request:
          - "inspect-delay 10s"
          - "content accept if clienthello"
        tcp_response:
          - "content accept if serverhello"
        stick:
          - "on req.payload_lv(43,1) if clienthello"
          - "store-response res.payload_lv(43,1) if serverhello"
        options:
          - "option httpchk GET /healthz"
          - "option tcp-check"
        http_check:
          - "expect status 200"
        tcp_check:
          - "connect"
        servers:

          # teleport node 1
          - name: "teleport-prod-01"
            address: "192.168.10.120:443"
            check: true
            check_port: "3000"
            send_proxy: true
            extra_params: "check-ssl verify none"

          # teleport node 2
          - name: "teleport-prod-02"
            address: "192.168.10.121:443"
            check: true
            check_port: "3000"
            send_proxy: true
            extra_params: "check-ssl verify none"

  roles:
    - "role-haproxy"

K3s Cluster Example

Configuration for K3s cluster with IP-based session persistence:

---
- name: "Deploy HAProxy for K3s Cluster"
  hosts: "haproxy_servers"
  become: true

  vars:

    # global settings
    haproxy_global:
      log:
        - "/dev/log local0"
        - "/dev/log local1 notice"
      chroot: "/var/lib/haproxy"
      stats_socket: "/run/haproxy-admin.sock mode 660 level admin"
      stats_timeout: "30s"
      user: "haproxy"
      group: "haproxy"
      daemon: true

    # defaults settings
    haproxy_defaults:
      log: "global"
      mode: "tcp"
      options:
        - "tcplog"
        - "dontlognull"
      timeout_connect: "5000"
      timeout_client: "50000"
      timeout_server: "50000"

    # frontends
    haproxy_frontends:
      - name: "fe-k3s-http"
        bind: "192.168.10.17:80"
        default_backend: "be-k3s-http"

      - name: "fe-k3s-https"
        bind: "192.168.10.17:443"
        default_backend: "be-k3s-https"

      - name: "fe-k3s-api"
        bind: "192.168.10.17:6443"
        default_backend: "be-k3s-nodes"

    # backends with IP-based sticky sessions
    haproxy_backends:
      - name: "be-k3s-http"
        balance: "roundrobin"
        stick_table: "type ip size 200k expire 30m"
        stick:
          - "on src"
        options:
          - "option tcp-check"
        servers:
          - name: "k3s-node01"
            address: "192.168.10.21:80"
            check: true
          - name: "k3s-node02"
            address: "192.168.10.22:80"
            check: true
          - name: "k3s-node03"
            address: "192.168.10.23:80"
            check: true

      - name: "be-k3s-https"
        balance: "roundrobin"
        stick_table: "type ip size 200k expire 30m"
        stick:
          - "on src"
        options:
          - "option tcp-check"
        servers:
          - name: "k3s-node01"
            address: "192.168.10.21:443"
            check: true
          - name: "k3s-node02"
            address: "192.168.10.22:443"
            check: true
          - name: "k3s-node03"
            address: "192.168.10.23:443"
            check: true

      - name: "be-k3s-nodes"
        balance: "roundrobin"
        options:
          - "option tcp-check"
        servers:
          - name: "k3s-node01"
            address: "192.168.10.21:6443"
            check: true
          - name: "k3s-node02"
            address: "192.168.10.22:6443"
            check: true
          - name: "k3s-node03"
            address: "192.168.10.23:6443"
            check: true

  roles:
    - "role-haproxy"

WAF Example with SSL Persistence

---
- name: "Deploy HAProxy Load Balancer"
  hosts: "haproxy_servers"
  become: true

  vars:

    # enable stats interface
    haproxy_stats:
      enabled: true
      bind: "192.168.32.10:9000"
      mode: "http"
      uri: "/"
      show_node: true
      refresh: "10s"
      auth: "admin:password"

    # frontends
    haproxy_frontends:

      # http frontend
      - name: "http-in"
        bind: "192.168.32.15:80"
        default_backend: "waf_siempie_tools_http"

      # https frontend
      - name: "https-in"
        bind: "192.168.32.15:443"
        default_backend: "waf_siempie_tools_https"

    # backends
    haproxy_backends:

      # http backend with simple load balancing
      - name: "waf_siempie_tools_http"
        balance: "source"
        hash_type: "consistent"
        options:
          - "option httpchk GET /health"
        servers:

          # waf0.siempie.tools
          - name: "waf0.siempie.tools"
            address: "192.168.32.20:80"
            check: true
            send_proxy: true

          # waf1.siempie.tools
          - name: "waf1.siempie.tools"
            address: "192.168.32.21:80"
            check: true
            send_proxy: true

      # https backend with SSL session persistence
      - name: "waf_siempie_tools_https"
        balance: "roundrobin"
        stick_table: "type binary len 2048 size 300k expire 30m"
        acls:
          - "clienthello req.ssl_hello_type 1"
          - "serverhello res.ssl_hello_type 2"
        tcp_request:
          - "inspect-delay 10s"
          - "content accept if clienthello"
        tcp_response:
          - "content accept if serverhello"
        stick:
          - "on req.payload_lv(43,1) if clienthello"
          - "store-response res.payload_lv(43,1) if serverhello"
        options:
          - "option httpchk GET /health"
        servers:

          # waf0.siempie.tools
          - name: "waf0.siempie.tools"
            address: "192.168.32.20:443"
            send_proxy: true
            check: true
            extra_params: "check-ssl verify none"

          # waf0.siempie.tools
          - name: "waf1.siempie.tools"
            address: "192.168.32.21:443"
            send_proxy: true
            check: true
            extra_params: "check-ssl verify none"

  roles:
    - "role-haproxy"