From 1fa9c044d0a569bc7b4c6c97c7e17d433f3fc0e1 Mon Sep 17 00:00:00 2001 From: Simon Cornet Date: Fri, 17 Apr 2026 13:49:26 +0200 Subject: [PATCH] feat: add teleport like configs --- defaults/main.yaml | 7 ++- examples/full-example.yaml | 91 ------------------------------- readme.md | 109 ++++++++++++++++++++++++++++++++++--- templates/haproxy.cfg.j2 | 64 ++++++++++++++++++---- 4 files changed, 158 insertions(+), 113 deletions(-) delete mode 100644 examples/full-example.yaml diff --git a/defaults/main.yaml b/defaults/main.yaml index d76e58d..3e2d9f4 100644 --- a/defaults/main.yaml +++ b/defaults/main.yaml @@ -2,7 +2,8 @@ # global settings haproxy_global: - log: "/dev/log local2" + log: + - "/dev/log local2" chroot: "/var/lib/haproxy" pidfile: "/var/run/haproxy.pid" maxconn: 35000 @@ -15,11 +16,13 @@ haproxy_global: haproxy_defaults: log: "global" mode: "tcp" - option: "tcplog" + options: + - "tcplog" timeout_check: "5s" timeout_connect: "10s" timeout_client: "600s" timeout_server: "600s" + timeout_tunnel: "" # optional # stats listener (optional) haproxy_stats: diff --git a/examples/full-example.yaml b/examples/full-example.yaml deleted file mode 100644 index 62125b1..0000000 --- a/examples/full-example.yaml +++ /dev/null @@ -1,91 +0,0 @@ ---- -# Example playbook using role-haproxy -# This recreates the configuration from the README example - -- name: "Deploy HAProxy Load Balancer" - hosts: "haproxy_servers" - become: true - - vars: - - # enable stats interface - haproxy_stats: - enabled: true - bind: "10.120.32.10:9000" - mode: "http" - uri: "/" - show_node: true - refresh: "10s" - auth: "admitcreation:gZ4hWWeMWy7Bd8" - - # frontends - haproxy_frontends: - - # http frontend - - name: "http-in" - bind: "10.120.32.15:80" - default_backend: "waf_itcreation_tools_http" - - # https frontend - - name: "https-in" - bind: "10.120.32.15:443" - default_backend: "waf_itcreation_tools_https" - - # backends - haproxy_backends: - - # http backend with simple load balancing - - name: "waf_itcreation_tools_http" - balance: "source" - hash_type: "consistent" - options: - - "option httpchk GET /health" - servers: - - # waf0.itcreation.tools - - name: "waf0.itcreation.tools" - address: "10.120.32.20:80" - check: true - send_proxy: true - - # waf1.itcreation.tools - - name: "waf1.itcreation.tools" - address: "10.120.32.21:80" - check: true - send_proxy: true - - # https backend with SSL session persistence - - name: "waf_itcreation_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.itcreation.tools - - name: "waf0.itcreation.tools" - address: "10.120.32.20:443" - send_proxy: true - check: true - extra_params: "check-ssl verify none" - - # waf0.itcreation.tools - - name: "waf1.itcreation.tools" - address: "10.120.32.21:443" - send_proxy: true - check: true - extra_params: "check-ssl verify none" - - roles: - - "role-haproxy" diff --git a/readme.md b/readme.md index 0fddf52..4faf4a0 100644 --- a/readme.md +++ b/readme.md @@ -8,14 +8,14 @@ Install and configure HAProxy load balancer with flexible frontends, backends, a | Variable | Required | Default | Description | |----------|----------|---------|-------------| -| `haproxy_global.log` | No | `/dev/log local2` | Log target | +| `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.chroot` | No | `/var/lib/haproxy` | Chroot directory | -| `haproxy_global.pidfile` | No | `/var/run/haproxy.pid` | PID file location | -| `haproxy_global.maxconn` | No | `35000` | Maximum connections | | `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.stats_socket` | No | See defaults | Stats socket configuration | +| `haproxy_global.pidfile` | No | `/var/run/haproxy.pid` | PID file location (optional) | +| `haproxy_global.maxconn` | No | `35000` | Maximum connections (optional) | ### Default Settings @@ -23,11 +23,12 @@ Install and configure HAProxy load balancer with flexible frontends, backends, a |----------|----------|---------|-------------| | `haproxy_defaults.log` | No | `global` | Log setting | | `haproxy_defaults.mode` | No | `tcp` | Default mode (tcp/http) | -| `haproxy_defaults.option` | No | `tcplog` | Default option | -| `haproxy_defaults.timeout_check` | No | `5s` | Health check timeout | +| `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 @@ -67,18 +68,110 @@ Install and configure HAProxy load balancer with flexible frontends, backends, a | `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 | -## Full Example +## Examples + +### Teleport Example + +Configuration for Teleport with SSL session persistence and advanced health checks: + +```yaml +--- +- 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" +``` + +### WAF Example with SSL Persistence ```yaml --- -# Example playbook using role-haproxy - name: "Deploy HAProxy Load Balancer" hosts: "haproxy_servers" become: true diff --git a/templates/haproxy.cfg.j2 b/templates/haproxy.cfg.j2 index aae1f57..2b1dce1 100644 --- a/templates/haproxy.cfg.j2 +++ b/templates/haproxy.cfg.j2 @@ -1,29 +1,57 @@ # global global +{%- if haproxy_global.log is string %} log {{ haproxy_global.log }} - +{%- else %} +{%- for log_entry in haproxy_global.log %} + log {{ log_entry }} +{%- endfor %} +{%- endif %} +{%- if haproxy_global.stats_socket is defined %} + stats socket {{ haproxy_global.stats_socket }} +{%- endif %} +{%- if haproxy_global.chroot is defined %} chroot {{ haproxy_global.chroot }} - pidfile {{ haproxy_global.pidfile }} - - maxconn {{ haproxy_global.maxconn }} - group {{ haproxy_global.group }} +{%- endif %} +{%- if haproxy_global.user is defined %} user {{ haproxy_global.user }} +{%- endif %} +{%- if haproxy_global.group is defined %} + group {{ haproxy_global.group }} +{%- endif %} {%- if haproxy_global.daemon %} daemon {%- endif %} - - stats socket {{ haproxy_global.stats_socket }} +{%- if haproxy_global.pidfile is defined %} + pidfile {{ haproxy_global.pidfile }} +{%- endif %} +{%- if haproxy_global.maxconn is defined %} + maxconn {{ haproxy_global.maxconn }} +{%- endif %} # default settings defaults log {{ haproxy_defaults.log }} mode {{ haproxy_defaults.mode }} +{%- if haproxy_defaults.options is string %} + option {{ haproxy_defaults.options }} +{%- elif haproxy_defaults.options is defined %} +{%- for option in haproxy_defaults.options %} + option {{ option }} +{%- endfor %} +{%- elif haproxy_defaults.option is defined %} option {{ haproxy_defaults.option }} - timeout check {{ haproxy_defaults.timeout_check }} - timeout connect {{ haproxy_defaults.timeout_connect }} - timeout client {{ haproxy_defaults.timeout_client }} - timeout server {{ haproxy_defaults.timeout_server }} +{%- endif %} +{%- if haproxy_defaults.timeout_check is defined %} + timeout check {{ haproxy_defaults.timeout_check }} +{%- endif %} + timeout connect {{ haproxy_defaults.timeout_connect }} + timeout client {{ haproxy_defaults.timeout_client }} + timeout server {{ haproxy_defaults.timeout_server }} +{%- if haproxy_defaults.timeout_tunnel is defined and haproxy_defaults.timeout_tunnel != "" %} + timeout tunnel {{ haproxy_defaults.timeout_tunnel }} +{%- endif %} {%- if haproxy_stats.enabled %} @@ -104,9 +132,21 @@ backend {{ backend.name }} {{ option }} {%- endfor %} {%- endif %} +{%- if backend.http_check is defined %} + +{%- for http_chk in backend.http_check %} + http-check {{ http_chk }} +{%- endfor %} +{%- endif %} +{%- if backend.tcp_check is defined %} + +{%- for tcp_chk in backend.tcp_check %} + tcp-check {{ tcp_chk }} +{%- endfor %} +{%- endif %} {%- for server in backend.servers %} - server {{ server.name }} {{ server.address }}{% if server.send_proxy | default(false) %} send-proxy{% endif %}{% if server.check | default(false) %} check{% endif %}{% if server.extra_params is defined %} {{ server.extra_params }}{% endif %} + server {{ server.name }} {{ server.address }}{% if server.check | default(false) %} check{% endif %}{% if server.check_port is defined and server.check_port != "" %} port {{ server.check_port }}{% endif %}{% if server.send_proxy | default(false) %} send-proxy{% endif %}{% if server.extra_params is defined %} {{ server.extra_params }}{% endif %} {%- endfor %} {%- endfor %}