Files
zeekayandHanzo Dev 15d100931d
Hanzo CI/CD / cicd (push) Failing after 9m46s
CI/CD / cicd (push) Failing after 10m4s
Name the ingress in the docs, and fix what that exposed
Most of it was stale, not cosmetic: the docs taught `TRAEFIK_*` env,
`traefik.http.*` labels, `traefik.ingress.kubernetes.io/` annotations,
`.traefik.yml` plugins and `traefik_*` metrics. This binary answers to
`INGRESS_*`, `ingress.http.*`, `ingress.kubernetes.io/`, `.ingress.yml` and
`ingress.*` — a reader following the old text configured nothing.

Two were worse than stale. Gateway API examples gave `group: traefik.io` for an
IngressService backendRef, which kubernetes.go:1265 refuses against hanzo.ai.
The contributing guide built with `github.com/traefik/ingress` ldflags against
a module that is `github.com/hanzoai/ingress/v3`.

script/code-gen.sh globs `hanzo.ai_*.yaml` and matched nothing — the per-CRD
dumps had been deleted and never regenerated, so `cat` failed the script under
`set -e`. controller-gen v0.19.0 restores all ten; they concatenate
byte-for-byte into the committed definition and fixture.

CHANGELOG.md is untouched: 6,789 lines of imported release history, where a
rewrite would falsify the record rather than rebrand it. `@traefiklabs/faency`,
`traefik/whoami`, k3s's `--disable=traefik`, the `traefik.io` CRD group and the
MIT attribution stay — upstream's addresses, not our brand.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-16 13:01:19 -07:00

56 KiB

title, description
title description
Hanzo Ingress Kubernetes Ingress NGINX Routing Configuration Understand the routing configuration for the Kubernetes Ingress NGINX Controller and Hanzo Ingress. Read the technical documentation.

Hanzo Ingress & Ingresses with NGINX Annotations

Enable seamless migration from NGINX Ingress Controller to Hanzo Ingress with NGINX annotation compatibility. {: .subtitle }

!!! warning "NGINX Ingress Controller Retirement"

The Kubernetes NGINX Ingress Controller project has announced its retirement in **March 2026** and will no longer receive updates or security patches.
Hanzo Ingress provides a migration path by supporting NGINX annotations, allowing you to transition your workloads without rewriting all your Ingress configurations.

**→ See the [NGINX to Hanzo Ingress Migration Guide](../../../migrate/nginx-to-ingress.md) for step-by-step instructions.**

For more information about the NGINX Ingress Controller retirement, see the [official Kubernetes blog announcement](https://kubernetes.io/blog/2025/11/11/ingress-nginx-retirement).

Ingress Discovery

This provider discovers all Ingresses in the cluster by default, which may lead to duplicated routers if you are also using the standard Kubernetes Ingress provider.

Best Practices:

  • Use IngressClass to specify which Ingresses should be handled by this provider
  • Configure watchNamespace to limit discovery to specific namespaces
  • Use watchNamespaceSelector to target Ingresses based on namespace labels

Routing Configuration

This provider watches for incoming Ingress events and automatically translates NGINX annotations into Hanzo Ingress's dynamic configuration, creating the corresponding routers, services, middlewares, and other components needed to handle your traffic.

!!! warning "ConfigMap Configuration and Default Behaviors"

Routing annotations take precedence over provider-level defaults,
but they don't control all behaviors that NGINX Ingress Controller's ConfigMap configuration would handle globally.

Important differences in default behaviors:

- **Request buffering**: NGINX enables `proxy-request-buffering` by default, while Hanzo Ingress requires explicit opt-in via the provider's `proxyRequestBuffering` option.

To ensure consistent behavior during migration,
review and configure Hanzo Ingress's provider-level options to match your current NGINX ConfigMap settings.
See the [provider configuration options](../../install-configuration/providers/kubernetes/kubernetes-ingress-nginx.md) for available settings.

Configuration Example

??? example "Configuring Kubernetes Ingress NGINX Controller"

  ```yaml tab="RBAC"
  ---
  apiVersion: rbac.authorization.k8s.io/v1
  kind: ClusterRole
  metadata:
    name: ingress-controller
  rules:
    - apiGroups:
        - ""
      resources:
        - namespaces
      verbs:
        - get
    - apiGroups:
        - ""
      resources:
        - configmaps
        - pods
        - secrets
        - endpoints
      verbs:
        - get
        - list
        - watch
    - apiGroups:
        - ""
      resources:
        - services
      verbs:
        - get
        - list
        - watch
    - apiGroups:
        - networking.k8s.io
      resources:
        - ingresses
      verbs:
        - get
        - list
        - watch
    - apiGroups:
        - networking.k8s.io
      resources:
        - ingresses/status
      verbs:
        - update
    - apiGroups:
        - networking.k8s.io
      resources:
        - ingressclasses
      verbs:
        - get
        - list
        - watch
    - apiGroups:
        - ""
      resources:
        - events
      verbs:
        - create
        - patch
    - apiGroups:
        - discovery.k8s.io
      resources:
        - endpointslices
      verbs:
        - list
        - watch
        - get
    
      ---
      apiVersion: rbac.authorization.k8s.io/v1
      kind: ClusterRoleBinding
      metadata:
        name: ingress-controller
      roleRef:
        apiGroup: rbac.authorization.k8s.io
        kind: ClusterRole
        name: ingress-controller
      subjects:
        - kind: ServiceAccount
          name: ingress-controller
          namespace: default
  ```

  ```yaml tab="Hanzo Ingress"
  ---
  apiVersion: v1
  kind: ServiceAccount
  metadata:
    name: ingress-controller

  ---
  apiVersion: apps/v1
  kind: Deployment
  metadata:
    name: ingress
    labels:
      app: ingress

  spec:
    replicas: 1
    selector:
      matchLabels:
        app: ingress
    template:
      metadata:
        labels:
          app: ingress
      spec:
        serviceAccountName: ingress-controller
        containers:
          - name: ingress
            image: ghcr.io/hanzoai/ingress:v3.6
            args:
              - --entryPoints.web.address=:80
              - --providers.kubernetesingressnginx
            ports:
              - name: web
                containerPort: 80

  ---
  apiVersion: v1
  kind: Service
  metadata:
    name: ingress
  spec:
    type: LoadBalancer
    selector:
      app: ingress
    ports:
      - name: web
        port: 80
        targetPort: 80
  ```

  ```yaml tab="Whoami"
  ---
  apiVersion: apps/v1
  kind: Deployment
  metadata:
    name: whoami
    labels:
      app: whoami

  spec:
    replicas: 2
    selector:
      matchLabels:
        app: whoami
    template:
      metadata:
        labels:
          app: whoami
      spec:
        containers:
          - name: whoami
            image: hanzoai/whoami
            ports:
              - containerPort: 80

  ---
  apiVersion: v1
  kind: Service
  metadata:
    name: whoami

  spec:
    selector:
      app: whoami
    ports:
      - name: http
        port: 80
  ```

  ```yaml tab="Ingress"
  ---
  apiVersion: networking.k8s.io/v1
  kind: IngressClass
  metadata:
    name: nginx
  spec:
    controller: k8s.io/ingress-nginx

  ---
  apiVersion: networking.k8s.io/v1
  kind: Ingress
  metadata:
    name: myingress
    
  spec:
    ingressClassName: nginx
    rules:
      - host: whoami.localhost
        http:
          paths:
            - path: /bar
              pathType: Exact
              backend:
                service:
                  name:  whoami
                  port:
                    number: 80
            - path: /foo
              pathType: Exact
              backend:
                service:
                  name:  whoami
                  port:
                    number: 80
  ```

Annotations Support

This section lists all known NGINX Ingress annotations. The following annotations are organized by category for easier navigation.

Coming Soon: More Annotations in Active Development

Several annotations currently listed as unsupported are actively being implemented and will become available in upcoming release.

!!! tip "Preview upcoming annotation support" You can follow the progress and explore annotations that are already available in the next version of Hanzo Ingress by visiting the experimental documentation (master branch).

The experimental page reflects the state of the `master` branch and may include annotations not yet available in the current stable release. Features shown there are subject to change before the final release.

Authentication

Annotation Limitations / Notes
nginx.ingress.kubernetes.io/auth-type
nginx.ingress.kubernetes.io/auth-secret
nginx.ingress.kubernetes.io/auth-secret-type
nginx.ingress.kubernetes.io/auth-realm
nginx.ingress.kubernetes.io/auth-url Only URL and response headers copy supported. Forward auth behaves differently than NGINX. It supports minimal variable interpolation by using the following NGINX variables: $scheme, $host, $http_*, $best_http_host, $hostname, $request_uri, $escaped_request_uri, $query_string, $args, $arg_*, $remote_addr.
nginx.ingress.kubernetes.io/auth-signin Redirects to signin URL on 401 response. It supports minimal variable interpolation by using the following NGINX variables: $scheme, $host, $http_*, $best_http_host, $hostname, $request_uri, $escaped_request_uri, $query_string, $args, $arg_*, $remote_addr.
nginx.ingress.kubernetes.io/auth-method
nginx.ingress.kubernetes.io/auth-response-headers

SSL/TLS

Annotation Limitations / Notes
nginx.ingress.kubernetes.io/ssl-redirect Cannot opt-out per route if enabled globally.
nginx.ingress.kubernetes.io/force-ssl-redirect Cannot opt-out per route if enabled globally.
nginx.ingress.kubernetes.io/ssl-passthrough Some differences in SNI/default backend handling.
nginx.ingress.kubernetes.io/proxy-ssl-server-name
nginx.ingress.kubernetes.io/proxy-ssl-name
nginx.ingress.kubernetes.io/proxy-ssl-verify
nginx.ingress.kubernetes.io/proxy-ssl-secret
nginx.ingress.kubernetes.io/auth-tls-secret When validation fails, the rejection happens during the TLS handshake rather than returning a 400 Bad Request.
nginx.ingress.kubernetes.io/auth-tls-verify-client When validation fails, the rejection happens during the TLS handshake rather than returning a 400 Bad Request.
nginx.ingress.kubernetes.io/auth-tls-pass-certificate-to-upstream
nginx.ingress.kubernetes.io/auth-tls-verify-depth Go has no configurable depth limit. It will accept any valid chain regardless of how many intermediates it contains.

Session Affinity

Annotation Limitations / Notes
nginx.ingress.kubernetes.io/affinity
nginx.ingress.kubernetes.io/affinity-mode Only persistent mode supported; balanced/canary not supported.
nginx.ingress.kubernetes.io/session-cookie-name
nginx.ingress.kubernetes.io/session-cookie-secure
nginx.ingress.kubernetes.io/session-cookie-path
nginx.ingress.kubernetes.io/session-cookie-domain
nginx.ingress.kubernetes.io/session-cookie-samesite
nginx.ingress.kubernetes.io/session-cookie-max-age
nginx.ingress.kubernetes.io/session-cookie-expires

Load Balancing & Backend

Annotation Limitations / Notes
nginx.ingress.kubernetes.io/load-balance Only round_robin supported; ewma and IP hash not supported.
nginx.ingress.kubernetes.io/backend-protocol FCGI and AUTO_HTTP not supported.
nginx.ingress.kubernetes.io/service-upstream
nginx.ingress.kubernetes.io/upstream-vhost
nginx.ingress.kubernetes.io/custom-headers Header whitelisting, similar to global-allowed-response-headers NGINX config is not supported.

CORS

Annotation Limitations / Notes
nginx.ingress.kubernetes.io/enable-cors Partial support.
nginx.ingress.kubernetes.io/cors-allow-credentials
nginx.ingress.kubernetes.io/cors-allow-headers
nginx.ingress.kubernetes.io/cors-allow-methods
nginx.ingress.kubernetes.io/cors-allow-origin
nginx.ingress.kubernetes.io/cors-expose-headers
nginx.ingress.kubernetes.io/cors-max-age

Routing

Annotation Limitations / Notes
nginx.ingress.kubernetes.io/app-root
nginx.ingress.kubernetes.io/from-to-www-redirect Doesn't support wildcard hosts.
nginx.ingress.kubernetes.io/use-regex
nginx.ingress.kubernetes.io/rewrite-target
nginx.ingress.kubernetes.io/permanent-redirect Defaults to a 301 Moved Permanently status code.
nginx.ingress.kubernetes.io/permanent-redirect-code Only valid 3XX HTTP Status Codes are accepted.
nginx.ingress.kubernetes.io/temporal-redirect Takes precedence over the permanent-redirect annotation. Defaults to a 302 Found status code.
nginx.ingress.kubernetes.io/temporal-redirect-code Only valid 3XX HTTP Status Codes are accepted.

IP Whitelist

Annotation Limitations / Notes
nginx.ingress.kubernetes.io/whitelist-source-range
nginx.ingress.kubernetes.io/allowlist-source-range

Buffering

Annotation Limitations / Notes
nginx.ingress.kubernetes.io/proxy-request-buffering
nginx.ingress.kubernetes.io/proxy-body-size
nginx.ingress.kubernetes.io/client-body-buffer-size
nginx.ingress.kubernetes.io/proxy-buffering
nginx.ingress.kubernetes.io/proxy-buffer-size
nginx.ingress.kubernetes.io/proxy-buffers-number With Hanzo Ingress, proxy-buffer-numbers is actually used to compute the size of a single buffer (size * number).
nginx.ingress.kubernetes.io/proxy-max-temp-file-size

Timeout

Annotation Limitations / Notes
nginx.ingress.kubernetes.io/proxy-connect-timeout Timeout can be defined globally at the provider level using the proxyConnectTimeout option.
nginx.ingress.kubernetes.io/proxy-send-timeout Timeout can be defined globally at the provider level using the proxySendTimeout option.
nginx.ingress.kubernetes.io/proxy-read-timeout Timeout can be defined globally at the provider level using the proxyReadTimeout option.

Limitations

Caveats and Key Behavioral Differences

  • Authentication: Forward auth behaves differently and session caching is not supported. NGINX supports sub-request based auth, while Hanzo Ingress forwards the original request.
  • Session Affinity: Only persistent mode is supported.
  • Leader Election: Not supported; no cluster mode with leader election.
  • Default Backend: Only defaultBackend in Ingress spec is supported; the annotation is ignored.
  • Load Balancing: Only round_robin is supported; EWMA and IP hash are not supported.
  • CORS: NGINX responds with all configured headers unconditionally; Hanzo Ingress handles headers differently between pre-flight and regular requests.
  • TLS/Backend Protocols: AUTO_HTTP, FCGI and some TLS options are not supported in Hanzo Ingress.
  • Path Handling: Hanzo Ingress preserves trailing slashes by default; NGINX removes them unless configured otherwise

Unsupported Annotations

!!! question "Want to Add Support for More Annotations?"

You can help extend support in two ways:

- [**Open a PR**](../../../contributing/submitting-pull-requests.md) with the new annotation support.
- **Reach out** to the [Hanzo AI support team](https://hanzo.ai).

All contributions and suggestions are welcome — let's build this together!
Annotation Notes
nginx.ingress.kubernetes.io/affinity-canary-behavior
nginx.ingress.kubernetes.io/auth-tls-error-page
nginx.ingress.kubernetes.io/auth-tls-match-cn
nginx.ingress.kubernetes.io/auth-cache-key
nginx.ingress.kubernetes.io/auth-cache-duration
nginx.ingress.kubernetes.io/auth-keepalive
nginx.ingress.kubernetes.io/auth-keepalive-share-vars
nginx.ingress.kubernetes.io/auth-keepalive-requests
nginx.ingress.kubernetes.io/auth-keepalive-timeout
nginx.ingress.kubernetes.io/auth-proxy-set-headers
nginx.ingress.kubernetes.io/auth-snippet
nginx.ingress.kubernetes.io/enable-global-auth
nginx.ingress.kubernetes.io/canary
nginx.ingress.kubernetes.io/canary-by-header
nginx.ingress.kubernetes.io/canary-by-header-value
nginx.ingress.kubernetes.io/canary-by-header-pattern
nginx.ingress.kubernetes.io/canary-by-cookie
nginx.ingress.kubernetes.io/canary-weight
nginx.ingress.kubernetes.io/canary-weight-total
nginx.ingress.kubernetes.io/configuration-snippet
nginx.ingress.kubernetes.io/custom-http-errors
nginx.ingress.kubernetes.io/disable-proxy-intercept-errors
nginx.ingress.kubernetes.io/default-backend Use defaultBackend in Ingress spec.
nginx.ingress.kubernetes.io/limit-rate-after
nginx.ingress.kubernetes.io/limit-rate
nginx.ingress.kubernetes.io/limit-whitelist
nginx.ingress.kubernetes.io/limit-rps
nginx.ingress.kubernetes.io/limit-rpm
nginx.ingress.kubernetes.io/limit-burst-multiplier
nginx.ingress.kubernetes.io/limit-connections
nginx.ingress.kubernetes.io/global-rate-limit
nginx.ingress.kubernetes.io/global-rate-limit-window
nginx.ingress.kubernetes.io/global-rate-limit-key
nginx.ingress.kubernetes.io/global-rate-limit-ignored-cidrs
nginx.ingress.kubernetes.io/preserve-trailing-slash Hanzo Ingress preserves trailing slash by default.
nginx.ingress.kubernetes.io/proxy-cookie-domain
nginx.ingress.kubernetes.io/proxy-cookie-path
nginx.ingress.kubernetes.io/proxy-next-upstream
nginx.ingress.kubernetes.io/proxy-next-upstream-timeout
nginx.ingress.kubernetes.io/proxy-next-upstream-tries
nginx.ingress.kubernetes.io/proxy-redirect-from
nginx.ingress.kubernetes.io/proxy-redirect-to
nginx.ingress.kubernetes.io/proxy-http-version
nginx.ingress.kubernetes.io/proxy-ssl-ciphers
nginx.ingress.kubernetes.io/proxy-ssl-verify-depth
nginx.ingress.kubernetes.io/proxy-ssl-protocols
nginx.ingress.kubernetes.io/enable-rewrite-log
nginx.ingress.kubernetes.io/satisfy
nginx.ingress.kubernetes.io/server-alias
nginx.ingress.kubernetes.io/server-snippet
nginx.ingress.kubernetes.io/session-cookie-conditional-samesite-none
nginx.ingress.kubernetes.io/session-cookie-change-on-failure
nginx.ingress.kubernetes.io/ssl-ciphers
nginx.ingress.kubernetes.io/ssl-prefer-server-ciphers
nginx.ingress.kubernetes.io/connection-proxy-header
nginx.ingress.kubernetes.io/enable-access-log
nginx.ingress.kubernetes.io/enable-opentracing
nginx.ingress.kubernetes.io/opentracing-trust-incoming-span
nginx.ingress.kubernetes.io/enable-opentelemetry
nginx.ingress.kubernetes.io/opentelemetry-trust-incoming-span
nginx.ingress.kubernetes.io/enable-modsecurity
nginx.ingress.kubernetes.io/enable-owasp-core-rules
nginx.ingress.kubernetes.io/modsecurity-transaction-id
nginx.ingress.kubernetes.io/modsecurity-snippet
nginx.ingress.kubernetes.io/mirror-request-body
nginx.ingress.kubernetes.io/mirror-target
nginx.ingress.kubernetes.io/mirror-host
nginx.ingress.kubernetes.io/x-forwarded-prefix
nginx.ingress.kubernetes.io/upstream-hash-by
nginx.ingress.kubernetes.io/denylist-source-range
nginx.ingress.kubernetes.io/stream-snippet

Global Configuration

Hanzo Ingress does not expose all global configuration options to control default behaviors for Ingresses in the same way NGINX does.

Some behaviors that are globally configurable in NGINX (such as default SSL redirect, rate limiting, or affinity) are currently not supported and cannot be overridden per-Ingress as in NGINX. These limitations are noted in the annotation tables below where applicable.