Base Library¶
The base library provides the core HAProxy configuration infrastructure. It defines extension points that other libraries use to inject their functionality, making it the foundation of the template library system.
Overview¶
The base library is always enabled and cannot be disabled. It provides:
- Core HAProxy configuration structure (global, defaults, frontends, backends)
- The plugin pattern via extension points for other libraries to inject content
- Frontend routing logic with path matching and backend selection
- Utility macros for template development
- Error page templates
- Map file infrastructure for routing decisions
Configuration¶
The base library is always included and has no enable/disable option:
Extension Points¶
The base library defines extension points using the include_matching("prefix-*") pattern. Any template snippet with a matching prefix is automatically included at the designated location in the HAProxy configuration.
Available Extension Points¶
| Extension Point | Prefix Pattern | Location in Config | Purpose |
|---|---|---|---|
| Global Settings | global-settings-* |
Inside global section |
Global directives (logging, process, paths, SSL tuning) |
| Defaults Settings | defaults-settings-* |
Inside defaults section |
Defaults directives (options, balance, timeouts, errorfiles) |
| Features | features-* |
Early in config generation | Feature initialization and registration |
| Global Top | global-top-* |
After defaults section |
Top-level HAProxy elements (userlists, peers, etc.) |
| Frontend Extra | frontend-extra-* |
After frontend bind, before routing | Early frontend directives (options, captures, ACLs) |
| Frontend Matchers | frontend-matchers-advanced-* |
Within frontend routing logic | Advanced request matching (method, headers, query params) |
| Frontend Filters | frontend-filters-* |
HTTP frontend, after routing | Request/response filters (header modification, redirects) |
| Custom Frontends | frontends-* |
After HTTP frontend | Additional frontend definitions |
| Custom Backends | backends-* |
Before default_backend | Backend definitions from resource libraries |
| Backend Directives | backend-directives-* |
Within backend blocks | Per-backend directives (auth, rate limiting) |
| Host Map | map-host-* |
host.map file | Host-to-group mapping entries |
| Path Exact Map | map-path-exact-* |
path-exact.map file | Exact path match entries |
| Path Prefix Exact Map | map-pfxexact-* |
path-prefix-exact.map file | Prefix-exact path match entries |
| Path Prefix Map | map-path-prefix-* |
path-prefix.map file | Prefix path match entries |
| Path Regex Map | map-path-regex-* |
path-regex.map file | Regex path match entries |
| Weighted Backend Map | map-weighted-backend-* |
weighted-multi-backend.map file | Weighted routing entries |
| Status Patches | status-patches-* |
After features, before backends | Resource status patch registration (side effects only) |
How Extension Points Work¶
- Base library uses
include_matching("prefix-*")to include all snippets matching the pattern - Other libraries (or user config) define snippets with matching prefixes
- At render time, all matching snippets are included in order
Injecting Custom Configuration¶
You can inject custom HAProxy configuration by adding template snippets with the appropriate prefix in your values.yaml:
controller:
config:
templateSnippets:
# Override default timeouts (replaces the base library snippet)
defaults-settings-300-timeouts:
template: |
timeout connect 5000
timeout client 30000
timeout server 30000
timeout tunnel 600000
timeout http-request 10000
# Add custom global tuning directives (extends the global section)
global-settings-500-tuning:
template: |
tune.bufsize 262144
no-memory-trimming
# Add custom security rules to the HTTP frontend
frontend-filters-custom-security:
template: |
http-request deny if { path_beg /admin } !{ src 10.0.0.0/8 }
http-request deny if { path_beg /.env }
# Add a custom userlist
global-top-custom-userlist:
template: |
userlist api_users
user apiuser password $2y$05$...
# Add custom backend
backends-custom-maintenance:
template: |
backend maintenance_backend
http-request return status 503 content-type text/html string "<h1>Under Maintenance</h1>"
Snippet Priority¶
Snippets can specify a priority field to control inclusion order (lower numbers run first):
templateSnippets:
features-ssl-initialization:
priority: 50 # Runs early
template: |
{# Initialize SSL infrastructure #}
features-ssl-crtlist:
priority: 150 # Runs after certificates are registered
template: |
{# Generate certificate list #}
Features¶
Frontend Routing Logic¶
The base library implements a sophisticated routing system using HAProxy maps and transaction variables:
- Host matching: Extracts and matches the Host header
- Path matching: Evaluates paths in priority order (Exact > Regex > Prefix)
- Qualifier system: Supports
BACKEND(direct) andMULTIBACKEND(weighted) routing
# Path matching order: Exact > Regex > Prefix-exact > Prefix
http-request set-var(txn.path_match) var(txn.host_match),concat(,txn.path,),map(/etc/haproxy/maps/path-exact.map)
http-request set-var(txn.path_match) var(txn.host_match),concat(,txn.path,),map_reg(/etc/haproxy/maps/path-regex.map) if !{ var(txn.path_match) -m found }
Overriding Path Match Order
The path-regex-last library overrides this to use performance-first ordering (Exact > Prefix > Regex).
Utility Macros¶
include_matching¶
Includes all snippets matching a glob pattern:
sanitize_regex¶
Escapes regex patterns for HAProxy's double-quoted context:
Backend Server Pool¶
The util-backend-servers snippet generates server lines with:
- Pre-allocated server slots for dynamic scaling
- Health check configuration
- Support for per-server options (maxconn, SSL, etc.)
{%- var service_name = "my-service" %}
{%- var port = 8080 %}
{{ render "util-backend-servers" inherit_context }}
Error Pages¶
Pre-configured error response templates for common HTTP errors:
| File | HTTP Status |
|---|---|
| 400.http | Bad Request |
| 403.http | Forbidden |
| 408.http | Request Timeout |
| 500.http | Internal Server Error |
| 502.http | Bad Gateway |
| 503.http | Service Unavailable |
| 504.http | Gateway Timeout |
Debug Headers¶
When debug mode is enabled, the frontend adds response headers for routing introspection:
Debug headers include:
X-HAProxy-Backend: Selected backend nameX-HAProxy-Host-Match: Matched host groupX-HAProxy-Path-Match: Full path match resultX-HAProxy-Path-Match-Qualifier: BACKEND or MULTIBACKEND
Shared Memory Stats (HAProxy 3.3+)¶
When haproxy.shmStats.enabled is true and HAProxy version is 3.3 or later, the base library adds shm-stats-file and shm-stats-file-max-objects to the global section. This persists stats counters (frontend/backend/server metrics) across HAProxy reloads via shared memory, eliminating counter resets during configuration changes.
The shm-stats-file-max-objects value is a configurable fixed value (default 50000) set via haproxy.shmStats.maxObjects. Since the shm-stats file is fixed-size and cannot be resized on reload, a large fixed value prevents reload failures when new ingresses are added. HAProxy allocates object slots lazily, so memory overhead is proportional to actual objects, not the configured maximum.
When shmStats is enabled, the chart automatically adds a /dev/shm emptyDir volume with medium: Memory to the HAProxy pod. The volume's sizeLimit is auto-calculated from maxObjects (~4KB per object with 10% margin), or can be overridden via haproxy.shmStats.shmSizeLimit. This volume counts against the pod's memory limit.
Address Discovery¶
The base library watches controller LoadBalancer Services and discovers external addresses for status reporting. Addresses are aggregated from all matching services and deduplicated, then stored in gf["addresses"]. This supports multi-service setups where HAProxy is exposed via both internal and public LoadBalancers.
Controller Services are discovered via label selector (app.kubernetes.io/name=<name>,app.kubernetes.io/component=loadbalancer). If no Service has LoadBalancer addresses assigned yet, gf["addresses"] remains nil and status patches that depend on addresses are skipped.
Address discovery can be disabled via controller.statusPatches.enabled: false. When disabled, gf["addresses"] is never set, which prevents all status-patches-* snippets from writing to Ingress or Gateway status. This is useful during migration from another ingress controller to avoid premature DNS cutover when tools like external-dns watch status fields.
Status Patch Extension Point¶
The status-patches-* extension point renders at priority 200 — after feature analysis (features-* at 050-150) but before backends and frontends (500+). This ensures status patches are captured even when later config generation fails, allowing the renderFailed variant to be applied.
Status patch snippets produce no HAProxy configuration output. They call statusPatch() as a side effect to register patches for later application by the controller.
Map Files¶
The base library generates these map files for routing:
| Map File | Purpose | Matcher |
|---|---|---|
| host.map | Host header to group mapping | Exact match |
| path-exact.map | Exact path matching | map() |
| path-prefix-exact.map | Prefix paths that should match exactly | map() |
| path-prefix.map | Prefix path matching | map_beg() |
| path-regex.map | Regex path matching | map_reg() |
| weighted-multi-backend.map | Weighted backend selection | map() |
HAProxy Configuration Structure¶
The base library generates this configuration structure. The global and defaults sections are composed from individually overridable snippets:
global
# global-settings-100-logging
log stdout len 4096 local0 info
# global-settings-200-process
daemon
nbthread 2 # auto-calculated from CPU requests
# global-settings-300-paths
default-path origin /etc/haproxy
crt-base /etc/haproxy/certs
# global-settings-400-ssl
tune.ssl.default-dh-param 2048
# global-settings-250-shm-stats (when haproxy.shmStats.enabled=true and HAProxy >= 3.3)
shm-stats-file /dev/shm/haproxy-stats
shm-stats-file-max-objects 50000 # configurable via haproxy.shmStats.maxObjects
defaults
# defaults-settings-100-options
mode http
log global
option httplog
option dontlognull
option log-health-checks
option forwardfor
# defaults-settings-200-balance
balance roundrobin
# defaults-settings-300-timeouts
timeout connect 5000
timeout client 50000
timeout server 50000
# defaults-settings-400-errorfiles
errorfile 400 /etc/haproxy/general/400.http
# ... other error files
# global-top-* snippets here (userlists, etc.)
frontend status
bind *:8404
# Health check endpoints
frontend http_frontend
bind *:8080
# frontend-extra-* snippets (options, captures, ACLs)
# Routing logic
# frontend-matchers-advanced-* snippets
# frontend-filters-* snippets
use_backend %[var(txn.backend_name)] if { var(txn.backend_name) -m found }
default_backend default_backend
# frontends-* snippets (HTTPS, TCP, etc.)
# backends-* snippets (resource-specific backends)
backend default_backend
http-request return status 404
Each global-settings-* and defaults-settings-* snippet can be individually overridden or extended via controller.config.templateSnippets in your values.yaml. For example, to customize timeouts, override defaults-settings-300-timeouts with your own values. To add new global directives, create a global-settings-500-tuning snippet (or any name matching the pattern).
See Also¶
- Template Libraries Overview - How template libraries work
- SSL Library - TLS certificate management and HTTPS frontend
- Path Regex Last Library - Alternative path matching order