HAProxy State: Load Balancing & Route Management for Proxies
Documents the HAProxy Salt state for WikiOasis proxy servers, covering configuration templates, routes.map routing, pillar keys, and live route updates.
Use this file to discover all available pages before exploring further.
The haproxy state installs HAProxy and socat on all proxy* servers and manages the complete proxy configuration from pillar. All load balancer behaviour — global tunables, timeouts, frontend bind addresses, backend server pools, and HTTP health checks — is declared in the haproxy: pillar map and rendered into /etc/haproxy/haproxy.cfg via a Jinja template. A companion sub-state, haproxy.route, manages the dynamic /etc/haproxy/routes.map file and can sync routing changes into the HAProxy runtime via the admin socket without requiring a full reload.
Frontends with use_routes: true emit an ACL that looks up the Host header in routes.map and forwards to the matched backend:
{%- if frontend.get('use_routes') and haproxy.get('routes') %} acl has_route req.hdr(host),lower,map(/etc/haproxy/routes.map) -m found use_backend %[req.hdr(host),lower,map(/etc/haproxy/routes.map)] if has_route{%- endif %}
persistent_hosts entries are compiled to static ACLs that always override the map, useful for hosts that must never be affected by route updates:
{%- for ph in exact_hosts %} acl fe_{{ name }}_h{{ loop.index }} hdr(host) -i {{ ph.hostname }} use_backend {{ ph.backend }} if fe_{{ name }}_h{{ loop.index }}{%- endfor %}
Wildcard entries (starting with *.) use hdr_end to match subdomains.
WikiOasis uses two complementary routing mechanisms in the same frontend:
persistent_hosts
Static ACLs compiled directly into haproxy.cfg. Changing a persistent host requires a config change and a full haproxy reload (state.apply haproxy). Used for long-lived, critical routes (e.g. test.wikioasis.org → staging, phorge.wikioasis.org → apps).
routes (map)
Dynamic entries in /etc/haproxy/routes.map. Can be updated at runtime via the admin socket without a reload. Used for service-level routes (e.g. grafana.wikioasis.org → grafana, icinga.wikioasis.org → icinga) that may change more frequently.
Use haproxy.route for day-to-day route additions and removals. Use the full state.apply haproxy only when changing globals, defaults, frontend binds, or backend server pools — changes that require a config file update and service reload.
The runtime sync (haproxy_sync_routes) only runs onchanges — when the routes.map file content actually changes. If you need to force a sync after a haproxy restart lost in-memory routes without a pillar change, use state.apply haproxy.route which also runs per-route idempotent add map commands on every apply.