Skip to content

haptic-annotations library

The haptic-annotations library is HAPTIC's native annotation vocabulary, under the haproxy-haptic.org/* prefix. Its capabilities are a best-of-breed superset of the three vendor annotation libraries (haproxytech, haproxy-ingress, nginx-ingress) combined: for every capability it adopts whichever vendor's semantics is strongest and exposes it under one clean name.

Where the vendor libraries exist to ease migration from an upstream ingress controller, this is the vocabulary to reach for when writing HAPTIC configuration from scratch. It's enabled by default.

Highlights it pulls together: haproxytech's pod-aware pod-maxconn and request capture; haproxy-ingress's agent checks, OAuth2-proxy flow, path-type control, and four config-section injection points; and nginx-ingress's canary routing, request mirroring, and bandwidth throttling — alongside the timeouts, load balancing, TLS, CORS, redirects, HSTS, session affinity, access control, and authentication all three share.

Overview

This library is enabled by default. See haproxy-haptic.org/* annotations render to HAProxy config live:

In the Resources panel, change the shop Ingress's haproxy-haptic.org/load-balance from leastconn to roundrobin, then watch the backend section's balance line update in the haproxy.cfg tab.

Coming from another ingress controller?

Keep your existing annotations working by enabling the matching vendor library instead — see Migrating to HAPTIC. You can also run both: vendor annotations and haproxy-haptic.org/* annotations coexist on the same Ingress.

Configuration

controller:
  templateLibraries:
    hapticAnnotations:
      enabled: true  # Enabled by default

Snippet names use the 800-band priority, so where the same Ingress carries both a haproxy-haptic.org/* annotation and a vendor annotation for the same capability, the vendor value (100–799 band) is applied first and the native value layers after it.

Annotation reference

Every annotation below is supported (semantics carried faithfully) or, where HAProxy diverges from the source controller, different (works, with the caveat in the note). The library declares no inert annotations.

Path and host matching

Route which requests reach a backend and alias extra hostnames onto an existing host.

Annotation Status Behaviour
haproxy-haptic.org/path-type ✅ Supported Overrides how the path matches when the Ingress pathType is ImplementationSpecific: regex, exact, prefix (trailing slash normalized), or begin.
haproxy-haptic.org/server-alias ✅ Supported Adds extra exact hostnames (comma- or space-separated) that route to the same backends as the Ingress's primary host.
haproxy-haptic.org/server-alias-regex ✅ Supported Adds regular-expression hostnames that route to the same backends as the Ingress's primary host.

Backend tuning

Per-backend timeouts, load balancing, connection limits, health/agent checks, and a raw-directive escape hatch.

Annotation Status Behaviour
haproxy-haptic.org/agent-check-addr ✅ Supported Sets the agent-check address via agent-addr; requires agent-check-port.
haproxy-haptic.org/agent-check-interval ✅ Supported Sets the agent-check interval via agent-inter; requires agent-check-port.
haproxy-haptic.org/agent-check-port ✅ Supported Enables the agent check on the given port (1-65535) via agent-check and agent-port; required by the other agent-check-* keys.
haproxy-haptic.org/agent-check-send ✅ Supported Sets the string sent to the agent check via agent-send; requires agent-check-port.
haproxy-haptic.org/check ✅ Supported Toggles server health checks; off emits no-check so servers aren't health-checked.
haproxy-haptic.org/config-backend ✅ Supported Injects raw operator-authored directives verbatim into the backend section.
haproxy-haptic.org/fullconn ⚠️ Behaviour differs Emits fullconn on the backend. Unlike a hard connection cap, HAProxy's fullconn is a soft threshold that scales the per-server minconn/maxconn ranges.
haproxy-haptic.org/health-check-fall ✅ Supported Sets the failed-check count before a server is marked down via fall.
haproxy-haptic.org/health-check-interval ✅ Supported Sets the health-check interval via inter; ignored when check is off.
haproxy-haptic.org/health-check-port ✅ Supported Sets the health-check port (1-65535) via port.
haproxy-haptic.org/health-check-rise ✅ Supported Sets the successful-check count before a server is marked up via rise.
haproxy-haptic.org/health-check-uri ✅ Supported Enables HTTP health checks via option httpchk; a bare path becomes GET <path>, and a value containing a space is used verbatim.
haproxy-haptic.org/initial-weight ✅ Supported Sets the initial server weight (0-256) via weight.
haproxy-haptic.org/load-balance ✅ Supported Sets the backend balance algorithm: roundrobin, static-rr, leastconn, first, source, random, or a parameterized uri, url_param(<name>), hdr(<name>), or rdp-cookie(<name>); an invalid value fails the render.
haproxy-haptic.org/maxconn-server ✅ Supported Sets the per-server maximum concurrent connections via maxconn.
haproxy-haptic.org/maxqueue-server ✅ Supported Sets the per-server maximum queued connections via maxqueue.
haproxy-haptic.org/pod-maxconn ✅ Supported Sets a cluster-wide connection budget, divided across the ready HAProxy pods and rounded up to a power of two, then applied as each server's maxconn.
haproxy-haptic.org/proxy-protocol ✅ Supported Sends the PROXY protocol header to servers: proxy/proxy-v1 emit send-proxy, and proxy-v2, proxy-v2-ssl, proxy-v2-ssl-cn emit the matching send-proxy-v2 variant; any other value fails the render.
haproxy-haptic.org/scale-server-slots ✅ Supported Overrides the number of reserved server slots the backend pre-allocates for runtime scaling.
haproxy-haptic.org/timeout-check ✅ Supported Sets the check timeout via timeout check.
haproxy-haptic.org/timeout-connect ✅ Supported Sets the connect timeout via timeout connect.
haproxy-haptic.org/timeout-http-request ✅ Supported Sets the request timeout via timeout http-request.
haproxy-haptic.org/timeout-keep-alive ✅ Supported Sets the keep-alive timeout via timeout http-keep-alive.
haproxy-haptic.org/timeout-queue ✅ Supported Sets the queue timeout via timeout queue.
haproxy-haptic.org/timeout-server ✅ Supported Sets the server timeout via timeout server.
haproxy-haptic.org/timeout-tunnel ✅ Supported Sets the tunnel timeout via timeout tunnel.
haproxy-haptic.org/upstream-hash-by ⚠️ Behaviour differs Maps nginx's hash key to the closest HAProxy consistent-hash balance equivalent (balance uri, balance source, balance hdr(...), balance url_param(...), or balance hash req.cook(...)) with hash-type consistent; nginx has no exact analogue.

Backend TLS (to the upstream)

Speak TLS to the backend Service — protocol, verification, client certs, SNI, ciphers.

Annotation Status Behaviour
haproxy-haptic.org/backend-ca-secret ✅ Supported Loads the Secret's ca.crt as the backend ca-file and requires TLS verification; a missing Secret or key is skipped with a warning comment.
haproxy-haptic.org/backend-ciphers ✅ Supported Sets the cipher list for TLS 1.2 and earlier via ciphers on a TLS-enabled backend.
haproxy-haptic.org/backend-ciphersuites ✅ Supported Sets the cipher suites for TLS 1.3 via ciphersuites on a TLS-enabled backend.
haproxy-haptic.org/backend-crt-secret ✅ Supported Presents the Secret's tls.crt and tls.key as a client certificate to the upstream via crt; a missing Secret is skipped with a warning.
haproxy-haptic.org/backend-protocol ✅ Supported Selects the upstream protocol from h1, h2, h1-ssl, h2-ssl, http, https, grpc, or grpcs; the h2, grpc, h2-ssl, and grpcs values add proto h2, and h1-ssl, https, h2-ssl, and grpcs speak TLS to the upstream.
haproxy-haptic.org/backend-sni ✅ Supported Sets the SNI sent to the upstream: host or sni forwards the request Host via sni req.hdr(host), and any other value is sent literally via sni str(<value>).
haproxy-haptic.org/backend-ssl-protocols ⚠️ Behaviour differs Maps a space-separated TLS version list to ssl-min-ver (lowest) and ssl-max-ver (highest). HAProxy expresses only a contiguous span, so a gap in the list (for example, skipping TLSv1.2) can't be represented.
haproxy-haptic.org/backend-verify ✅ Supported A truthy value (on, true, yes, 1) requires upstream certificate verification, and fails closed rather than silently downgrading to verify none when no CA is available.
haproxy-haptic.org/backend-verify-host ✅ Supported Sets the expected upstream certificate hostname via verifyhost, independent of the SNI value.

Rate and bandwidth limiting

Per-source request-rate caps (reload-surviving stick-tables) and per-connection download throttling.

Annotation Status Behaviour
haproxy-haptic.org/limit-rate ✅ Supported Throttles per-connection download bandwidth (bytes per second) via a bwlim-out filter and set-bandwidth-limit, independent of the request-rate caps.
haproxy-haptic.org/limit-rate-after ✅ Supported Sets the number of bytes transferred before limit-rate throttling begins, via the bwlim-out minimum size.
haproxy-haptic.org/rate-limit-connections ✅ Supported Caps concurrent connections per source IP; ignored when rate-limit-rps or rate-limit-rpm is set.
haproxy-haptic.org/rate-limit-period ⚠️ Behaviour differs Overrides the stick-table window. When unset, it derives from the active cap (1 second for requests per second, 60 seconds for requests per minute, a 30-second TTL for connection caps) instead of a flat 1-second default, so per-minute limits stay per-minute.
haproxy-haptic.org/rate-limit-rpm ✅ Supported Caps requests per minute per source IP (a 60-second http_req_rate window); ignored when rate-limit-rps is also set.
haproxy-haptic.org/rate-limit-rps ✅ Supported Caps requests per second per source IP via an http_req_rate stick-table; requests over the cap are rejected with the deny status (default 429), with no burst allowance.
haproxy-haptic.org/rate-limit-size ✅ Supported Sets the stick-table size (default 100k).
haproxy-haptic.org/rate-limit-status-code ✅ Supported Sets the HTTP status returned to rejected requests (default 429).
haproxy-haptic.org/rate-limit-whitelist ✅ Supported Exempts comma-separated CIDRs from the rate limit; invalid CIDRs fail the render.

Rewriting, retries, and session affinity

Path/target rewriting, body-size limits, upstream retries, Host/header overrides, and cookie-based stickiness.

Annotation Status Behaviour
haproxy-haptic.org/affinity ✅ Supported The value cookie enables cookie-based session affinity via the backend cookie directive.
haproxy-haptic.org/connection-proxy-header ✅ Supported Overrides the Connection header sent to the upstream.
haproxy-haptic.org/path-rewrite ✅ Supported Rewrites the request path via http-request replace-path: a <from> <to> pair rewrites the match, and a bare value replaces the whole path.
haproxy-haptic.org/proxy-body-size ✅ Supported Limits the request body size (with k, m, or g suffixes), returning 413 when exceeded; 0 means unlimited.
haproxy-haptic.org/proxy-next-upstream ⚠️ Behaviour differs Maps nginx retry conditions to HAProxy retry-on values (error, timeout, invalid_header, and http_<code>); non_idempotent is ignored and off disables retries, so the retry surface differs from nginx.
haproxy-haptic.org/proxy-next-upstream-tries ✅ Supported Sets the number of upstream retries via retries; 0 keeps the default.
haproxy-haptic.org/rewrite-target ✅ Supported Rewrites the request path via http-request replace-path; capture references like $1 become HAProxy backreferences like \1.
haproxy-haptic.org/session-cookie-domain ✅ Supported Sets the session cookie's Domain via the domain cookie keyword.
haproxy-haptic.org/session-cookie-dynamic ✅ Supported Enables dynamically generated cookie values via the dynamic cookie keyword (default on).
haproxy-haptic.org/session-cookie-keywords ✅ Supported Appends extra keywords to the cookie directive verbatim (for example, httponly).
haproxy-haptic.org/session-cookie-max-age ✅ Supported Sets the browser cookie lifetime in seconds via attr Max-Age; this is the cookie's Max-Age, not HAProxy's server-affinity lifetime.
haproxy-haptic.org/session-cookie-name ✅ Supported Sets the session cookie name (default INGRESSCOOKIE).
haproxy-haptic.org/session-cookie-path ✅ Supported Sets the session cookie's Path via attr Path.
haproxy-haptic.org/session-cookie-preserve ✅ Supported The value true adds the preserve keyword to the cookie directive.
haproxy-haptic.org/session-cookie-samesite ✅ Supported Sets the cookie SameSite attribute (None, Lax, or Strict) via attr SameSite.
haproxy-haptic.org/session-cookie-secure ✅ Supported The value true sets the cookie Secure attribute via attr Secure.
haproxy-haptic.org/session-cookie-strategy ✅ Supported Selects the cookie mode: insert (default), rewrite, or prefix; insert and prefix add indirect nocache.
haproxy-haptic.org/set-host ✅ Supported Overrides the Host header sent to the upstream.
haproxy-haptic.org/x-forwarded-prefix ✅ Supported Sets the X-Forwarded-Prefix header sent to the upstream.

Headers, CORS, and access control

Request/response header manipulation, capture, CORS, source-IP allow/deny, and upstream cookie/redirect rewriting.

Annotation Status Behaviour
haproxy-haptic.org/allowlist-source-range ✅ Supported Allows only the listed CIDRs and denies all other source IPs for the host.
haproxy-haptic.org/cors-allow-credentials ✅ Supported Sets Access-Control-Allow-Credentials: true when enabled.
haproxy-haptic.org/cors-allow-headers ✅ Supported Sets the Access-Control-Allow-Headers response header.
haproxy-haptic.org/cors-allow-methods ✅ Supported Sets the Access-Control-Allow-Methods response header.
haproxy-haptic.org/cors-allow-origin ✅ Supported Sets the allowed origins (comma-separated, with a single-level *. wildcard); the matching request Origin is echoed back (default *).
haproxy-haptic.org/cors-enable ✅ Supported Enables CORS response headers and answers OPTIONS requests with 204.
haproxy-haptic.org/cors-expose-headers ✅ Supported Sets the Access-Control-Expose-Headers response header.
haproxy-haptic.org/cors-max-age ✅ Supported Sets the Access-Control-Max-Age response header (default 86400).
haproxy-haptic.org/denylist-source-range ✅ Supported Denies the listed CIDRs and allows all other source IPs for the host.
haproxy-haptic.org/forwardfor ✅ Supported Controls the X-Forwarded-For header: add, update, ifmissing, or ignore.
haproxy-haptic.org/proxy-cookie-domain ✅ Supported Rewrites the Domain in upstream Set-Cookie headers, given a <from> <to> pair.
haproxy-haptic.org/proxy-cookie-path ✅ Supported Rewrites the Path in upstream Set-Cookie headers, given a <from> <to> pair.
haproxy-haptic.org/proxy-redirect-from ⚠️ Behaviour differs Rewrites the Location and Refresh response headers matching this pattern; nginx's default mode isn't supported, and the rewrite applies at the frontend rather than per-backend.
haproxy-haptic.org/proxy-redirect-to ⚠️ Behaviour differs Supplies the replacement text for proxy-redirect-from; required whenever that annotation names a real pattern, or the render fails.
haproxy-haptic.org/request-capture ✅ Supported Captures the named request headers (newline-separated) in the logs via capture request header, across the whole frontend.
haproxy-haptic.org/request-capture-len ✅ Supported Sets the capture length for request-capture (default 128).
haproxy-haptic.org/request-set-header ✅ Supported Sets request headers sent to the upstream via http-request set-header, one <name> <value> per line.
haproxy-haptic.org/response-set-header ✅ Supported Sets response headers via http-response set-header, one <name> <value> per line.
haproxy-haptic.org/src-ip-header ✅ Supported Derives the client source IP from the named request header via http-request set-src.

Canary and traffic mirroring

Header/cookie/weight-based canary routing and request mirroring via the SPOA hub.

Annotation Status Behaviour
haproxy-haptic.org/canary ✅ Supported Marks the Ingress as a canary for a host owned by another Ingress, overlaying a use_backend split instead of owning the route.
haproxy-haptic.org/canary-by-cookie ✅ Supported Routes to the canary backend when the named cookie is present.
haproxy-haptic.org/canary-by-header ✅ Supported Routes to the canary backend when the named header is present.
haproxy-haptic.org/canary-by-header-pattern ✅ Supported Routes to the canary backend when the named header matches this regular expression; takes precedence over canary-by-header-value.
haproxy-haptic.org/canary-by-header-value ✅ Supported Routes to the canary backend only when the named header equals this value.
haproxy-haptic.org/canary-weight ✅ Supported Sends a percentage of traffic (an integer 0-100) to the canary backend via a weighted random split.
haproxy-haptic.org/mirror-target ✅ Supported Mirrors requests fire-and-forget to a scheme://host[:port] target through the SPOA hub's mirror plugin, buffering the request body via option http-buffer-request; requires the mirror plugin and a host on the rule.

Redirects, HSTS, passthrough, and config injection

HTTP→HTTPS and host redirects (reload-free maps), HSTS, SSL passthrough, a default backend, and raw section injection.

Annotation Status Behaviour
haproxy-haptic.org/app-root ✅ Supported Redirects requests for the host root (/) to the given path.
haproxy-haptic.org/config-defaults ✅ Supported Injects raw operator-authored directives verbatim into the defaults section.
haproxy-haptic.org/config-frontend ✅ Supported Injects raw operator-authored directives into every frontend, before routing.
haproxy-haptic.org/config-global ✅ Supported Injects raw operator-authored directives verbatim into the global section.
haproxy-haptic.org/default-backend ⚠️ Behaviour differs Routes unmatched requests for the host to a named Service (its first port) as a catch-all backend; silently skipped when the Service or port can't be resolved, unlike haproxy-ingress's redirect-based default backend.
haproxy-haptic.org/default-backend-redirect ✅ Supported Redirects requests that match the host but no path to the given URL.
haproxy-haptic.org/default-backend-redirect-code ✅ Supported Sets the status code for default-backend-redirect (default 302).
haproxy-haptic.org/from-to-www-redirect ✅ Supported Issues a 301 redirect between the apex domain and its www subdomain.
haproxy-haptic.org/hsts ✅ Supported Enables HSTS by adding the Strict-Transport-Security response header for the host.
haproxy-haptic.org/hsts-include-subdomains ✅ Supported Appends includeSubDomains to the Strict-Transport-Security header when set to true.
haproxy-haptic.org/hsts-max-age ✅ Supported Sets the HSTS max-age in seconds (default 63072000).
haproxy-haptic.org/hsts-preload ✅ Supported Appends preload to the Strict-Transport-Security header when set to true.
haproxy-haptic.org/permanent-redirect ✅ Supported Redirects the host to the given URL with a permanent status code (default 301).
haproxy-haptic.org/permanent-redirect-code ✅ Supported Sets the status code for permanent-redirect (default 301).
haproxy-haptic.org/ssl-passthrough ✅ Supported Passes TLS through to the backend without terminating it, routed by SNI on a dedicated TCP frontend.
haproxy-haptic.org/ssl-redirect ✅ Supported Redirects plain HTTP requests for the host to HTTPS; hosts that also set ssl-redirect-port are handled there instead to avoid a double redirect.
haproxy-haptic.org/ssl-redirect-code ✅ Supported Sets the HTTP-to-HTTPS redirect status code (301, 302, 303, 307, or 308; default 302).
haproxy-haptic.org/ssl-redirect-port ✅ Supported Redirects plain HTTP requests to HTTPS on an explicit port, preserving the URI.
haproxy-haptic.org/temporal-redirect ✅ Supported Redirects the host to the given URL with a temporary status code (default 302).
haproxy-haptic.org/temporal-redirect-code ✅ Supported Sets the status code for temporal-redirect (default 302).

Authentication, mTLS, and WAF

Basic auth, client-certificate verification, external/forward auth, OAuth2-proxy, and the Coraza WAF via the SPOA hub.

Annotation Status Behaviour
haproxy-haptic.org/auth-headers-fail ✅ Supported Adds response headers on failed external authentication via http-after-response set-header.
haproxy-haptic.org/auth-headers-request ✅ Supported Lists the request headers forwarded to the external authentication service.
haproxy-haptic.org/auth-headers-succeed ✅ Supported Adds request headers to the upstream on successful external authentication.
haproxy-haptic.org/auth-method ✅ Supported Overrides the HTTP method used for the external authentication subrequest.
haproxy-haptic.org/auth-realm ✅ Supported Sets the basic-auth realm (default Restricted).
haproxy-haptic.org/auth-secret ✅ Supported Names the Secret holding basic-auth credentials; an absent Secret skips the challenge.
haproxy-haptic.org/auth-secret-type ✅ Supported Selects the credentials Secret format: auth-file (htpasswd in the auth key) or auth-map (one key per user); default auth-file.
haproxy-haptic.org/auth-signin ✅ Supported Sets the sign-in redirect URL for failed external authentication.
haproxy-haptic.org/auth-tls-cert-header ✅ Supported Forwards the client certificate details (X-SSL-Client-CN, X-SSL-Client-DN, X-SSL-Client-Cert) to the upstream when a client certificate was presented.
haproxy-haptic.org/auth-tls-error-page ✅ Supported Redirects to the given URL when client-certificate (mTLS) verification fails.
haproxy-haptic.org/auth-tls-secret ✅ Supported Enables client-certificate (mTLS) verification for the host using the CA in the named Secret; a host is required.
haproxy-haptic.org/auth-tls-verify-client ⚠️ Behaviour differs Sets client-certificate verification: on requires it, optional and optional_no_ca both map to verify optional (HAProxy has no distinct optional_no_ca mode), and off disables it.
haproxy-haptic.org/auth-type ✅ Supported Enables basic authentication; the only accepted value is basic.
haproxy-haptic.org/auth-url ✅ Supported Sets the external authentication service URL; requires the SPOA hub's external-auth plugin.
haproxy-haptic.org/modsecurity-snippet ✅ Supported Adds per-application Coraza WAF rules for the Ingress; requires the Coraza plugin.
haproxy-haptic.org/oauth ✅ Supported Enables authentication through oauth2-proxy (the only supported provider), building on external auth; skipped when auth-url is set.
haproxy-haptic.org/oauth-headers ✅ Supported Lists headers forwarded from the oauth2-proxy response on success (default X-Auth-Request-Email).
haproxy-haptic.org/oauth-uri-prefix ✅ Supported Sets the oauth2-proxy callback path prefix (default /oauth2).
haproxy-haptic.org/satisfy ✅ Supported The value any grants access when either the source-IP allowlist or basic authentication passes, instead of requiring both.
haproxy-haptic.org/waf ✅ Supported The value modsecurity enables the Coraza WAF for the Ingress; requires the Coraza plugin.
haproxy-haptic.org/waf-mode ✅ Supported Sets the WAF mode: deny (default) or detect; requires waf to be set.
Found a problem on this page? Report it or edit the page with the pencil icon above the title.