Unreleased documentation. Choose your installed release in the version menu. Features described here may be absent from that release.
Template libraries¶
A template library is a set of text templates that turns Kubernetes resource fields into HAProxy configuration. The bundled libraries handle Ingress, Gateway API, annotations, and TLS, and include validation tests for their output. Enable or disable them through Helm values.
Available libraries¶
| Library | Default | Purpose |
|---|---|---|
| Base | Enabled | Core HAProxy configuration, extension point definitions; disabling drops the haproxyConfig the other libraries plug into |
| kubernetes-backends | Enabled | Service port and EndpointSlice resolution for the routing libraries |
| SSL | Enabled | TLS certificate management, HTTPS frontend |
| Ingress | Enabled | Kubernetes Ingress resource support |
| Gateway API | Enabled | Gateway API (HTTP, gRPC, TLS and TCP routes) support |
| ingress-annotations-compat | Enabled | Shared helpers for native and vendor Ingress annotation libraries |
| governance | Enabled | Defaults and constraints on watched resource fields; add rules under controller.config.templatingSettings.extraContext.governance.rules |
| haptic-annotations | Enabled | haproxy-haptic.org/* — HAPTIC's native vocabulary; the only annotation library enabled by default |
| haproxytech | Disabled | haproxy.org/* annotations (haproxytech/kubernetes-ingress compat) — opt-in migration aid |
| haproxy-ingress | Disabled | haproxy-ingress.github.io/* annotations (jcmoraisjr/haproxy-ingress compat) — opt-in migration aid |
| nginx-ingress | Disabled | nginx.ingress.kubernetes.io/* annotations (kubernetes/ingress-nginx compat) — opt-in migration aid |
| vector | Loaded with vector.enabled (default on) |
Configures access-log processing and traffic metrics |
| spoa-hub | Loaded when the hub or a plugin is enabled | Connects HAProxy to plugins for authentication, request inspection, and other policies |
Enabling and disabling libraries¶
Configure libraries in your complete Helm values file. The values reference lists every switch:
controller:
templateLibraries:
base:
enabled: true # Default — disabling drops the haproxyConfig the other libraries plug into
ssl:
enabled: true # TLS/HTTPS support
ingress:
enabled: true # Kubernetes Ingress
gateway:
enabled: true # Gateway API
hapticAnnotations:
enabled: true # haproxy-haptic.org native annotations (default)
haproxytech:
enabled: false # haproxy.org compat — opt-in migration aid
haproxyIngress:
enabled: false # haproxy-ingress.github.io compat — opt-in migration aid
nginxIngress:
enabled: false # nginx-ingress compat — opt-in migration aid
config:
templatingSettings:
extraContext:
routing:
regexMatchOrder: default # "default" or "last" — see Path Matching Order below
How your settings combine with libraries¶
Each enabled library becomes an HAProxyTemplateLibrary resource. The chart's
HAProxyTemplateConfig references these libraries in merge order and contains
your controller.config overrides. See merge order for how overrides apply.
Inspect the merged configuration:
Try changing a hostname in an example that combines the routing libraries:
Path matching order¶
Path-based routing inside the rendered frontend-routing-logic snippet evaluates four map types: exact, regex, prefix-exact, and prefix. The evaluation order is selected by controller.config.templatingSettings.extraContext.routing.regexMatchOrder:
| Value | Order | Use case |
|---|---|---|
default (default) |
Exact > Regex > Prefix-exact > Prefix | A matching regex takes precedence over a prefix. |
last |
Exact > Prefix-exact > Prefix > Regex | A matching prefix takes precedence over a regex. |
Library merge order¶
Libraries are merged in a specific order, with later libraries overriding earlier ones:
1. base/ (lowest priority)
2. ssl/
3. ingress/
4. gateway/
5. ingress-annotations-compat/ (level 2.5 - Ingress-only shared scaffold)
6. governance/
7. haptic-annotations/ (native haproxy-haptic.org/* superset)
8. haproxytech/
9. haproxy-ingress/
10. nginx-ingress/
11. spoa-hub/ (auto-loaded when SPOA hub sidecar is enabled)
12. vector/ (loaded with vector.enabled; contributes only the sidecar's config file)
13. controller.config.* (highest priority - your values.yaml overrides for templateSnippets / maps / files / sslCertificates / haproxyConfig / validationTests / watchedResources)
Your custom configuration in controller.config always takes precedence.
Extension points¶
An extension point includes snippets whose names match a pattern. Use it to add directives or routing entries without replacing the surrounding template.
How extension points work¶
The base library uses render_glob "prefix-*" to automatically include all template snippets matching a glob pattern:
This includes all snippets whose names start with backends- (for example backends-500-ingress, backends-500-gateway, any user-provided backends-*). Snippets render in alphabetical order, so numeric prefixes control execution order — see the snippet priority numbering table below.
Available extension points¶
Choose an extension point by where your configuration belongs:
| Add | Snippet prefix |
|---|---|
| Global HAProxy settings | global-settings-* |
| Shared HTTP frontend directives | frontend-extra-* |
| Ingress backend directives | backend-directives-* |
| Your own backends | backends-* |
The extension point reference lists every hook, its position, and the variables available there.
For a complete snippet and deployment procedure, follow Write your first template.
Library Configuration via extraContext¶
extraContext supplies settings to every snippet. It contains values computed by
the chart, such as ports and Service names, plus your settings under
controller.config.templatingSettings.extraContext.
Use it to override library defaults. For example, set the nginx-ingress library's
HTTP-to-HTTPS redirect status code (default 308):
controller:
config:
templatingSettings:
extraContext:
nginxHttpRedirectCode: "301" # override the library default of 308
A value you set here always wins over the library's default. Custom snippets read any key the same way:
Snippet priority¶
Snippets within a render_glob pattern execute in alphabetical order. Priority is encoded in the snippet name via a numeric prefix:
For example, features-050-my-init runs before features-500-*, while
features-700-my-finalize runs after it. Use fixed-width numbers so their
alphabetical order matches the intended order.
Reserved numeric ranges used by the built-in libraries:
| Range | Purpose |
|---|---|
| 000-099 | Infrastructure / initialization |
| 100-199 | Feature registration |
| 200-499 | Security, Cross-Origin Resource Sharing (CORS), header manipulation, redirects |
| 500-599 | Core features (ingress, gateway) |
| 600-699 | haproxy-ingress (haproxy-ingress.github.io/*) compatibility |
| 700-799 | nginx-ingress (nginx.ingress.kubernetes.io/*) compatibility |
| 800-899 | haptic-annotations (haproxy-haptic.org/*) native vocabulary |
| 900-999 | Finalization / cleanup |
These ranges determine snippet order. They don't resolve conflicting annotations on one Ingress: HAPTIC rejects contradictory values from different annotation families. Use one annotation family per feature; see annotations.
See each library's reference for the hooks and variables it provides. Start with your first template for a complete customization workflow.
Custom libraries¶
To route from your own resources, add a watch and write snippets for the relevant
extension points. This example reads ConfigMaps and generates backends and host
routing entries through backends-* and map-host-*.
This example supplies its own minimal routing configuration. Its host.map maps
hostnames directly to backends; the bundled base library uses a different map
contract. For an example that extends the bundled chart, use the
custom-CRD library.
Library dependencies determine which snippets can call one another. When writing a library, use the extension point reference and the merge order above to choose where your snippets belong.
See also¶
- Annotations — which vendor annotation library covers which annotation prefix
- Templating Guide — writing your own snippets and templates
- Chart Values Reference → Template Libraries — every
controller.templateLibraries.*value