46 KiB

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

Traefik & Ingresses with NGINX Annotations

Enable seamless migration from NGINX Ingress Controller to Traefik 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.
Traefik provides a migration path by supporting NGINX annotations, allowing you to transition your workloads without rewriting all your Ingress configurations.

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 Traefik's dynamic configuration, creating the corresponding routers, services, middlewares, and other components needed to handle your traffic.

Configuration Example

??? example "Configuring Kubernetes Ingress NGINX Controller"

  ```yaml tab="RBAC"
  ---
  apiVersion: rbac.authorization.k8s.io/v1
  kind: ClusterRole
  metadata:
    name: traefik-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: traefik-ingress-controller
      roleRef:
        apiGroup: rbac.authorization.k8s.io
        kind: ClusterRole
        name: traefik-ingress-controller
      subjects:
        - kind: ServiceAccount
          name: traefik-ingress-controller
          namespace: default
  ```

  ```yaml tab="Traefik"
  ---
  apiVersion: v1
  kind: ServiceAccount
  metadata:
    name: traefik-ingress-controller

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

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

  ---
  apiVersion: v1
  kind: Service
  metadata:
    name: traefik
  spec:
    type: LoadBalancer
    selector:
      app: traefik
    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: traefik/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.

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.
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

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-path
nginx.ingress.kubernetes.io/session-cookie-domain
nginx.ingress.kubernetes.io/session-cookie-samesite

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

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-max-age

Routing

Annotation Limitations / Notes
nginx.ingress.kubernetes.io/use-regex

Limitations

Caveats and Key Behavioral Differences

  • Authentication: Forward auth behaves differently and session caching is not supported. NGINX supports sub-request based auth, while Traefik 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; Traefik handles headers differently between pre-flight and regular requests.
  • TLS/Backend Protocols: AUTO_HTTP, FCGI and some TLS options are not supported in Traefik.
  • Path Handling: Traefik 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 [Traefik Labs support team](https://info.traefik.io/request-commercial-support?cta=doc).

All contributions and suggestions are welcome — let's build this together!
Annotation Notes
nginx.ingress.kubernetes.io/app-root
nginx.ingress.kubernetes.io/affinity-canary-behavior
nginx.ingress.kubernetes.io/auth-tls-secret
nginx.ingress.kubernetes.io/auth-tls-verify-depth
nginx.ingress.kubernetes.io/auth-tls-verify-client
nginx.ingress.kubernetes.io/auth-tls-error-page
nginx.ingress.kubernetes.io/auth-tls-pass-certificate-to-upstream
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/client-body-buffer-size
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/permanent-redirect
nginx.ingress.kubernetes.io/permanent-redirect-code
nginx.ingress.kubernetes.io/temporal-redirect
nginx.ingress.kubernetes.io/preserve-trailing-slash Traefik preserves trailing slash by default.
nginx.ingress.kubernetes.io/proxy-cookie-domain
nginx.ingress.kubernetes.io/proxy-cookie-path
nginx.ingress.kubernetes.io/proxy-connect-timeout
nginx.ingress.kubernetes.io/proxy-send-timeout
nginx.ingress.kubernetes.io/proxy-read-timeout
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-request-buffering
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/rewrite-target
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-expires
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/upstream-vhost
nginx.ingress.kubernetes.io/denylist-source-range
nginx.ingress.kubernetes.io/whitelist-source-range
nginx.ingress.kubernetes.io/proxy-buffering
nginx.ingress.kubernetes.io/proxy-buffers-number
nginx.ingress.kubernetes.io/proxy-buffer-size
nginx.ingress.kubernetes.io/proxy-max-temp-file-size
nginx.ingress.kubernetes.io/stream-snippet

Global Configuration

Traefik 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.