--- title: "Traefik Kubernetes Ingress NGINX Routing Configuration" description: "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.