Upgrade Path

Traefik 3.5.0 → 3.7.13

34 versions, 38 migration-guide sections in 22 versions, 0 required stops

Version by version, oldest first

3.5.1: no action items (1 version)

3.5.2 2025-09-09

Migration

Deprecation of ProxyProtocol option

Starting with v3.5.2, the proxyProtocol option for TCP LoadBalancer is deprecated. This option can now be configured at the TCPServersTransport level, please check out the documentation for more details.

Kubernetes CRD Provider

To use the new proxyprotocol option in the Kubernetes CRD provider, you need to update your CRDs.

Apply Updated CRDs:

kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v3.5/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml

From doc.traefik.io/traefik/migrate/v3/#deprecation-of-proxyprotocol-option

Full release notes for 3.5.2

3.5.3: no action items (1 version)

3.5.4 2025-10-28

Migration

Certificate Metric Renamed with OpenTelemetry

Starting with v3.5.4, and when using OpenTelemetry, the traefik_tls_certs_not_after_milliseconds metric is renamed to traefik_tls_certs_not_after_seconds. This change aligns the metric name with its real unit precision, which is in seconds.

From doc.traefik.io/traefik/migrate/v3/#certificate-metric-renamed-with-opentelemetry

Full release notes for 3.5.4

3.5.6: no action items (1 version)

3.6.0 2025-11-07

Quoted from doc.traefik.io/traefik/migrate/v3/#v360

Migration

Kubernetes Gateway API Provider

Starting with v3.6.0, the Kubernetes Gateway API provider only supports version v1.4.0 of the specification, which requires the Gateway API CRDs to be updated.

Apply Updated CRDs:

kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.4.0/standard-install.yaml

For the experimental channel:

kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.4.0/experimental-install.yaml

Migration

Kubernetes CRD Provider

To use the new leasttime load-balancer algorithm with the Kubernetes CRD provider, you need to update your CRDs.

Apply Updated CRDs:

kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v3.6/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml

Full release notes for 3.6.0

3.6.1: no action items (1 version)

3.6.2 2025-11-18

Migration

Ingress NGINX Provider

The KubernetesIngressNGINX Provider is no longer experimental in v3.6.2 and can be enabled without the experimental.kubernetesIngressNGINX option.

Deprecated Configuration:

Experimental kubernetesIngressNGINX option (deprecated)

File (YAML)

experimental:
  kubernetesIngressNGINX: true

File (TOML)

[experimental]
    kubernetesIngressNGINX=true

CLI

--experimental.kubernetesIngressNGINX=true

Migration Steps:

  1. Remove the kubernetesIngressNGINX option from the experimental section
  2. Configure the provider using the kubernetesIngressNGINX Provider documentation

From doc.traefik.io/traefik/migrate/v3/#v362

Full release notes for 3.6.2

3.6.4 2025-12-05

Migration

Encoded Characters in Request Path

Starting with v3.6.4, for security reasons, Traefik now rejects requests with a path containing a specific set of encoded characters by default.

When such a request is received, Traefik responds with a 400 Bad Request status code.

Here is the list of the encoded characters that are rejected by default, along with the corresponding configuration option to allow them:

Encoded CharacterCharacterConfig option to allow the encoded character
%2f or %2F/ (slash)entryPoints.<name> .http.encodedCharacters .allowEncodedSlash
%5c or %5C\ (backslash)entryPoints.<name> .http.encodedCharacters .allowEncodedBackSlash
%00NULL (null character)entryPoints.<name> .http.encodedCharacters .allowEncodedNullCharacter
%3b or %3B; (semicolon)entryPoints.<name> .http.encodedCharacters .allowEncodedSemicolon
%25% (percent)entryPoints.<name> .http.encodedCharacters .allowEncodedPercent
%3f or %3F? (question mark)entryPoints.<name> .http.encodedCharacters .allowEncodedQuestionMark
%23# (hash)entryPoints.<name> .http.encodedCharacters .allowEncodedHash

Please check out the entrypoint encodedCharacters option documentation for more details.

From doc.traefik.io/traefik/migrate/v3/#encoded-characters-in-request-path

Full release notes for 3.6.4

3.6.5 – 3.6.6: no action items (2 versions)

3.6.7 2026-01-14

Migration

Encoded Characters Configuration Default Values

Since v3.6.7, the options for encoded characters now have a true default value. This means that Traefik will not reject requests with a path containing a specific set of encoded characters by default. It is now up to the users to configure the security hardening of encoded characters.

Here is the list of the encoded characters that can be configured to false to disallow them:

Encoded CharacterCharacterConfig optionsDefault value
%2f or %2F/ (slash)entryPoints.<name> .http.encodedCharacters .allowEncodedSlashtrue
%5c or %5C\ (backslash)entryPoints.<name> .http.encodedCharacters .allowEncodedBackSlashtrue
%00NULL (null character)entryPoints.<name> .http.encodedCharacters .allowEncodedNullCharactertrue
%3b or %3B; (semicolon)entryPoints.<name> .http.encodedCharacters .allowEncodedSemicolontrue
%25% (percent)entryPoints.<name> .http.encodedCharacters .allowEncodedPercenttrue
%3f or %3F? (question mark)entryPoints.<name> .http.encodedCharacters .allowEncodedQuestionMarktrue
%23# (hash)entryPoints.<name> .http.encodedCharacters .allowEncodedHashtrue

Note: This check is not done against query parameters, but only against the request path as defined in RFC3986 section-3.

Please check out the entrypoint encodedCharacters option documentation for more details.

From doc.traefik.io/traefik/migrate/v3/#encoded-characters-configuration-default-values

Full release notes for 3.6.7

3.6.8 2026-02-11

Migration

Health Check Request Path

Since v3.6.8, the configured path for the health check request is now verified to be a relative URL, and the health check will fail if it is not.

From doc.traefik.io/traefik/migrate/v3/#health-check-request-path

Full release notes for 3.6.8

3.6.9 2026-02-23

Migration

maxResponseBodySize configuration on ForwardAuth middleware

In v3.6.9, a new maxResponseBodySize option has been added to the ForwardAuth middleware configuration. The default value for this option is -1, which means there is no limit to the response body size. However, it is strongly recommended to set this option to a suitable value to avoid performance and security issues, such as DoS attacks and memory exhaustion.

Please check out the ForwardAuth middleware documentation for more details.

From doc.traefik.io/traefik/migrate/v3/#maxresponsebodysize-configuration-on-forwardauth-middleware

Migration

Kubernetes CRD Provider

To use the new maxResponseBodySize option in the ForwardAuth middleware with the Kubernetes CRD provider, you need to update your CRDs.

Apply Updated CRDs:

kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v3.6/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml

From doc.traefik.io/traefik/migrate/v3/#v369

Full release notes for 3.6.9

3.6.10 – 3.6.13: no action items (4 versions)

3.6.14 2026-04-22

Migration

Kubernetes CRD: Chain middleware and allowCrossNamespace

In v3.6.14, the Chain middleware now honors the Kubernetes CRD provider's allowCrossNamespace option. Previously, a Chain could reference middlewares in other namespaces regardless of the allowCrossNamespace configuration.

If allowCrossNamespace is set to false (the default) and a Chain middleware references a middleware in a different namespace from its own, the whole Chain is now rejected and an error is logged.

From doc.traefik.io/traefik/migrate/v3/#kubernetes-crd-chain-middleware-and-allowcrossnamespace

Migration

ForwardAuth middleware: trustForwardHeader

Starting with v3.6.14, the trustForwardHeader option has been deprecated and will be removed in the next major version. Configure the trusted IPs at the EntryPoint level by using the forwardedHeaders.trustedIPs option, and set trustForwardHeader to true on this middleware.

When trustForwardHeader is not explicitly set, Traefik logs a warning as its behavior is inconsistent: some X-Forwarded-* headers (e.g. X-Forwarded-For, X-Forwarded-Proto) are removed while others (e.g. X-Forwarded-Prefix) are forwarded untouched.

To silence the warning and avoid security concerns, explicitly set trustForwardHeader to true or false in your ForwardAuth middleware configuration.

Please check out the ForwardAuth middleware documentation for more details.

From doc.traefik.io/traefik/migrate/v3/#forwardauth-middleware-trustforwardheader

Full release notes for 3.6.14

3.6.15 2026-04-29

Migration

In v3.6.15, a new errorRequestHeaders option has been added to the Errors middleware.

By default, the behavior is unchanged: all original request headers are forwarded to the error page service. If the error page service is in a separate trust domain, consider using errorRequestHeaders to restrict which headers are forwarded.

Please check out the Error Pages middleware documentation for more details.

From doc.traefik.io/traefik/migrate/v3/#v3615

Full release notes for 3.6.15

3.6.16 2026-05-05

Migration

Docker provider: minimum Docker Engine version

Starting with v3.6.16, the Docker provider requires Docker API version v1.40 or above (Docker Engine v19.03). Users running older (end of life) versions of Docker Engine should update their Docker Engine or use the DOCKER_API_VERSION environment variable to override the API version used by Traefik.

From doc.traefik.io/traefik/migrate/v3/#docker-provider-minimum-docker-engine-version

Full release notes for 3.6.16

3.6.17 – 3.6.25: released after 3.7.0; not on this route

3.7.0 2026-05-05

Quoted from doc.traefik.io/traefik/migrate/v3/#v370

Migration

Ingress NGINX Provider

Starting with v3.7.0, the Ingress NGINX provider now supports the nginx.ingress.kubernetes.io/custom-headers annotation to add custom headers to the response forwarded to the client.

Therefore, in the corresponding RBACs (see KubernetesIngressNGINX provider RBACs) the configmaps right has been added.

Required RBAC Updates:

  ...
  - apiGroups:
      - ""
    resources:
      - configmaps
    verbs:
      - list
      - watch  
  ...

Migration

Kubernetes Gateway API Provider

Starting with v3.7.0, the Kubernetes Gateway API provider supports version v1.5.1 of the specification, which requires the Gateway API CRDs to be updated.

TLSRoute has graduated to the Standard channel and no longer requires the experimentalChannel option. The experimentalChannel option is now only needed for TCPRoute.

Apply Updated CRDs:

kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.5.1/standard-install.yaml

For the experimental channel:

kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.5.1/experimental-install.yaml

Migration

Kubernetes CRD Provider

To use the new options of the retry middleware or the new ingressClassName field with the Kubernetes CRD provider, you need to update your CRDs.

Apply Updated CRDs:

kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v3.7/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml

Migration

Wildcard Host and HostSNI

Since v3.7.0, the Host and HostSNI matchers support wildcard subdomain matching (e.g., *.example.com). This allows matching any direct subdomain of a domain with a single-level wildcard prefix. For example, *.example.com matches foo.example.com but not foo.bar.example.com or example.com itself.

This feature is only available with the v3 rule syntax (the default).

TLSOptions with Wildcard Domains

Since v3.7.0, TLSOptions can now be associated with routers using wildcard Host and HostSNI matchers (e.g., Host(*.example.com)). This enables configuring different TLS options for wildcard domains.

Previously, TLSOptions selection was limited to exact Host matches, and using HostRegexp or wildcards would fall back to the default TLS options with a warning message like: No domain found in rule HostRegexp(...) the TLS option foo cannot be applied.

Note: TLSOptions for HostRegexp matchers remains unsupported. Use wildcard Host matchers as an alternative.

From doc.traefik.io/traefik/migrate/v3/#wildcard-host-and-hostsni

Full release notes for 3.7.0

3.7.1 2026-05-11

Migration

Kubernetes providers: crossProviderNamespaces

In v3.7.1, a new crossProviderNamespaces option is available on the Kubernetes CRD, Ingress, and Gateway providers.

Traefik offers the possibility to reference resources from one provider to another (cross-provider references).

However, in the context of Kubernetes providers, those references (e.g. myservice@kubernetescrd) allow a user to cross namespace boundaries, as well as exposing @internal services, that only the operator should be able to expose.

This new crossProviderNamespaces option restricts in which namespaces Kubernetes resources are allowed to use cross-provider references.

The behavior is as follows:

ValueBehavior
not setAll Kubernetes resources can declare cross-provider references.
[]Every Kubernetes resource declaring a cross-provider reference is rejected.
["ns-a"]Only Kubernetes resources in the listed namespaces can declare cross-provider references.

Please check out the Kubernetes CRD, Kubernetes Ingress, and Kubernetes Gateway provider documentation for more details.

From doc.traefik.io/traefik/migrate/v3/#v371

Full release notes for 3.7.1

3.7.3 2026-06-04

Quoted from doc.traefik.io/traefik/migrate/v3/#v373

Migration

Kubernetes Gateway API Provider

Starting with v3.7.3, the QPS and Burst values of the Kubernetes client used by the Kubernetes Gateway API provider have been increased to 50 and 100 respectively (10x the default values of the Kubernetes client).

The Kubernetes Gateway API provider writes status updates intensively to comply with the Kubernetes Gateway API specification. This change helps avoid performance issues related to Kubernetes API rate limiting, which can increase the setup time when a new routing configuration is built.

These values are configurable through the kubernetesGateway.qps and kubernetesGateway.burst provider options.

Migration

BasicAuth Middleware

From version v3.7.3 onwards, the BasicAuth middleware requires a non-empty users configuration in order to be built successfully. Previously, the middleware would be built successfully but always return a 401 status code for any request. Now, an error occurs and any routers using it will be unmounted. For the same request, a 404 status code is served instead of a 401 status code.

Migration

StripPrefix and StripPrefixRegex Middleware

From version v3.7.3 onwards, the StripPrefix middleware and the StripPrefixRegex middleware reject requests (400 Bad Request) when stripping the configured prefix produces a path that differs from its normalised form (i.e. a path containing . or .. segments that would be collapsed by normalisation).

This prevents the stripped path from being interpreted as a different resource by the upstream service.

Examples with a configured prefix of /api:

Request pathPath after stripNormalised pathResult
/api/foo/foo/foo200 (sent)
/api///200 (sent)
/api./foo/./foo/foo400
/api../foo/../foo/foo400

Full release notes for 3.7.3

3.7.4 – 3.7.5: no action items (2 versions)

3.7.6 2026-06-30

Migration

Kubernetes Gateway API Provider: generated service and middleware names

Starting with v3.7.6, the Kubernetes Gateway API provider derives the name of the services and middlewares it generates from the route rule they belong to, instead of from the backend reference alone. This is required to prevent distinct route rules referencing the same backend from colliding on a single generated configuration.

Generated service names were previously built from the backend reference only:

<backend namespace>-<backend name>-<port>

They are now prefixed with the route rule they are generated for:

<route kind>-<route namespace>-<route name>-gw-<gateway namespace>-<gateway name>-ep-<entry point>-<rule index>-<rule hash>-svc-<backend namespace>-<backend name>-<backend index>

For example, a whoami backend in the default namespace previously exposed as default-whoami-http-80@kubernetesgateway is now exposed as httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-af329269dd38031b03e3-svc-default-whoami-0@kubernetesgateway.

Observability

These names are user-visible: they appear in the dashboard and API, in the access logs ServiceName field, and in the service label of the metrics. Dashboards, alerting rules, and log queries that match on Gateway API service names must be updated accordingly.

From doc.traefik.io/traefik/migrate/v3/#kubernetes-gateway-api-provider-generated-service-and-middleware-names

Migration

UnderscoreHeadersStrategy

Deprecated since v3.7.12

Please use the aliasHeadersStrategy option instead, which handles every aliasing character instead of the underscore only.

From version v3.6.20 onwards, a new underscoreHeadersStrategy entry point option defines how request headers with underscores in their names are handled before routing:

  • keep (default): request headers with underscores are forwarded as is.
  • delete: any request header whose name contains an underscore character is silently removed from the request.
  • reject: any request carrying a header whose name contains an underscore character is rejected with a 400 Bad Request response.

The default value is keep, so the existing behavior is preserved.

This option exists because underscores are valid characters in HTTP header names, but Go canonicalizes header names only on dashes. As a result, a middleware managing a header in its dash form (e.g. X-Auth-User set by the ForwardAuth authResponseHeaders option) does not see, and therefore cannot overwrite or remove, an underscore variant of that header (e.g. X_Auth_User).

Many backends map both forms to the same variable (CGI, WSGI, PHP, NGINX, ...): for them, X-Auth-User and X_Auth_User are the same header. Against such a backend, a client can smuggle the underscore variant past a middleware that only manages the dash form, and have the backend read the spoofed value, bypassing the protection the middleware was meant to provide.

Security

When an entry point fronts a backend that interprets underscores and dashes in header names identically, keeping the default keep strategy is not recommended, as it leaves the backend open to the header spoofing described above. Set underscoreHeadersStrategy to delete or reject on such entry points.

From doc.traefik.io/traefik/migrate/v3/#v376

Full release notes for 3.7.6

3.7.7 2026-07-08

Migration

Wildcard Host matcher

From version v3.7.7 onwards, the Host matcher treats a bare * as a catch-all, consistent with the TCP HostSNI() matcher. ``Host(``)`` now matches every request regardless of its host, including requests with no host at all.

Previously, the * was treated as a single wildcard label, so Host(`*`) only matched hosts made of a single segment (e.g. localhost) and not multi-segment hosts (e.g. example.com).

Please check out the HTTP routing rules documentation for more details.

From doc.traefik.io/traefik/migrate/v3/#wildcard-host-matcher

Full release notes for 3.7.7

3.7.8 2026-07-15

Migration

Kubernetes CRD: Errors middleware errorRequestHeaders

The errorRequestHeaders option, introduced in v3.6.15 for the Errors middleware, was not exposed on the Kubernetes CRD provider. Starting with v3.7.8, it can now be configured on the Middleware CRD.

To use this new option, the Kubernetes CRDs must be updated in the cluster before upgrading Traefik. To do so, please apply the CRDs manifest for v3.7:

kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v3.7/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml

Please check out the Error Pages middleware documentation for more details.

From doc.traefik.io/traefik/migrate/v3/#v378

Full release notes for 3.7.8

3.7.9 2026-07-24

Migration

HTTP/1 CONNECT requests

Starting with v3.7.9, HTTP/1 CONNECT requests are rejected with a 501 Not Implemented response.

HTTP/1 CONNECT requests were not functional before this change, so this rejection makes it explicit.

From doc.traefik.io/traefik/migrate/v3/#v379

Full release notes for 3.7.9

3.7.10 2026-07-31

Quoted from doc.traefik.io/traefik/migrate/v3/#v3710

Migration

Kubernetes Gateway API Provider: generated router, middleware, and service names

Starting with v3.7.10, the Kubernetes Gateway API provider derives the hash suffix of the router names it generates from all the route, Gateway, and listener identifying fields, instead of from the route rule alone. This is required to prevent distinct routes whose namespace, name, Gateway, and listener happen to concatenate to the same string from colliding on a single generated router name.

Generated router names keep the same overall shape:

<route kind>-<route namespace>-<route name>-gw-<gateway namespace>-<gateway name>-ep-<entry point>-<rule index>-<hash>

but the <hash> suffix changes, since it is no longer computed from the route rule alone.

For example, an HTTPRoute named http-app-1 in the default namespace previously generated the router httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-af329269dd38031b03e3 and is now generated as httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-799bcbf0c2317c5d1c93.

Middleware names are derived from the router name, so they change accordingly, for example <router name>-requestheadermodifier-0.

Generated service names were previously built from the backend reference only:

<backend namespace>-<backend name>-<port>

They are now prefixed with the route rule they are generated for:

<router name>-svc-<backend namespace>-<backend name>-<backend index>

For example, a whoami backend in the default namespace previously exposed as default-whoami-http-80@kubernetesgateway is now exposed as httproute-default-http-app-1-gw-default-my-gateway-ep-web-0-799bcbf0c2317c5d1c93-svc-default-whoami-0@kubernetesgateway.

Observability

These names are user-visible: they appear in the dashboard and API, in the access logs RouterName and ServiceName fields, and in the router/service labels of the metrics. Dashboards, alerting rules, and log queries that match on Gateway API router, middleware, or service names must be updated accordingly.

Migration

Kubernetes Gateway API Provider

Starting with v3.7.10, the Kubernetes Gateway API provider supports version v1.6.1 of the specification.

TCPRoute graduated to the Standard channel in Gateway API v1.6.0, with a new v1 version. Traefik v3.7 still watches TCPRoute through its v1alpha2 version, which the Standard channel CRDs no longer serve.

If you use TCPRoute and upgrade to Gateway API v1.6.1 CRDs, you must install the experimental channel CRDs. The experimentalChannel option remains required to enable TCPRoute support in Traefik.

Standard channel CRDs with experimentalChannel enabled

Traefik cannot watch the v1alpha2 version of TCPRoute, and the Kubernetes Gateway provider never completes its startup: no Gateway API resource is served, not only TCPRoute. No error is logged, Traefik keeps running, and other providers are unaffected.

Traefik v3.7 remains backward compatible with the v1.5.x CRDs: upgrading the CRDs in the cluster is only required to rely on the v1.6.1 resources.

Upcoming in v3.8

Traefik v3.8 will require updating the Gateway API CRDs to v1.6.x, and in return the experimentalChannel option will no longer be needed for TCPRoute.

(Optional) Apply v1.6.1 CRDs:

kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.6.1/standard-install.yaml

For the experimental channel (needed for TCPRoute):

kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.6.1/experimental-install.yaml

Full release notes for 3.7.10

3.7.11 2026-08-18

Migration

Safe naming configuration option

Starting with v3.7.11, the new safeNaming provider option enables collision-safe naming for the routers, middlewares and services generated by the Kubernetes CRD provider, instead of the current naming scheme, under which names can collide across namespaces or resources.

Generated names are derived from the identity of the object they come from instead of being flattened and normalized, and the ones generated for a route are derived from the route index instead of its rule. For example, for a Kubernetes Service named whoami and an IngressRoute named test.route, both in the default namespace:

default-whoami-80                          ->    default_whoami_80
default-test-route-6b204d94623b3df4370c    ->    default_test.route_0

The option is disabled by default, which preserves the existing behavior.

Observability

These names are user-visible: they appear in the dashboard and API, in the access logs RouterName and ServiceName fields, and in the router and service labels of the metrics. Dashboards, alerting rules, and log queries that match on Kubernetes CRD router, middleware or service names must be updated accordingly when safeNaming is enabled.

Please check out the safeNaming provider documentation for more details.

From doc.traefik.io/traefik/migrate/v3/#safe-naming-configuration-option

Migration

Conflicting TLS options

The TLS options are configured on a router, but they are applied during the TLS handshake, before the routing occurs, and are therefore mapped to the host names found in the router rule rather than to the router itself. When several routers on the same entry point serve the same host name with different TLS options, Traefik cannot decide which options to apply, and falls back to the default TLS options for that host name.

The default TLS options being the fallback of the conflict resolution, they should not be less secure than the options they can replace: a router relying on a mutual TLS authentication (clientAuth), for example, no longer enforces it if a conflict on its host name falls back to default TLS options that do not require it. See GHSA-g55h-rg46-x9c5 for more details.

Starting with v3.7.11, the new core.strictTLSOptions install configuration option disables this fallback: the routers involved in the conflict are marked in error and are not built at all.

The option is disabled by default, to preserve the existing behavior, but enabling it is recommended:

File (YAML)

## Install configuration
core:
  strictTLSOptions: true

File (TOML)

## Install configuration
[core]
  strictTLSOptions = true

CLI

## Install configuration
--core.strictTLSOptions=true

Disabled routers

This option fails closed: a conflict disables all the routers serving the conflicting host name on the concerned entry point, until the conflict is resolved.

Please check out the Conflicting TLS Options documentation for more details.

From doc.traefik.io/traefik/migrate/v3/#conflicting-tls-options

Migration

Kubernetes CRD: cluster-wide default TLSOption and TLSStore

In the Kubernetes CRD provider, the TLSOption and the TLSStore named default are cluster-wide, whatever the namespace they are defined in. Anyone allowed to create one in a single namespace can therefore replace the TLS policy, mutual TLS authentication included, of the routers that do not reference TLS options explicitly.

Starting with v3.7.11, the new defaultTLSResourcesNamespace provider option reserves these resources to a namespace the cluster operator controls.

The option is empty by default, to preserve the existing behavior, but setting it is recommended:

File (YAML)

## Install configuration
providers:
  kubernetesCRD:
    defaultTLSResourcesNamespace: traefik

File (TOML)

## Install configuration
[providers.kubernetesCRD]
  defaultTLSResourcesNamespace = "traefik"

CLI

## Install configuration
--providers.kubernetescrd.defaultTLSResourcesNamespace=traefik

Ignored resources

A default resource defined outside of the configured namespace is ignored, and cannot be referenced under its namespaced name either. For a TLSStore, this also applies to the certificates it defines.

Please check out the Kubernetes CRD provider documentation for more details.

From doc.traefik.io/traefik/migrate/v3/#kubernetes-crd-cluster-wide-default-tlsoption-and-tlsstore

Full release notes for 3.7.11

3.7.12 2026-08-26

Migration

AliasHeadersStrategy

From version v3.7.12 onwards, a new aliasHeadersStrategy entry point option deprecates and replaces the underscoreHeadersStrategy option introduced in v3.6.20.

Go canonicalizes header names on dashes only, so it handles X-Auth-User, X_Auth_User and X.Auth.User as three distinct headers, while the backends deriving their variable names from the header names (CGI, WSGI, PHP, NGINX, ...) uppercase the name and replace every character that is neither a letter nor a digit with an underscore: for them, the three names above are the same HTTP_X_AUTH_USER variable.

The underscoreHeadersStrategy option only handles the header names containing an underscore character, which leaves the other aliasing forms untouched. Its behavior is unchanged. Underscores are only one of the characters building such an alias: every character HTTP allows in a header name except the letters, the digits and the dash does, that is !, #, $, %, &, ', *, +, ., ^, _, `, | and ~. The aliasHeadersStrategy option handles them all:

  • keep (default): request headers with an aliasing name are forwarded as is.
  • delete: any request header whose name contains a character which is neither a letter, a digit, nor a dash is silently removed from the request.
  • reject: any request carrying a header whose name contains a character which is neither a letter, a digit, nor a dash is rejected with a 400 Bad Request response.

The default value is keep, so the existing behavior is preserved.

File (YAML)

entryPoints:
  websecure:
    address: ':443'
    http:
      aliasHeadersStrategy: delete

File (TOML)

[entryPoints.websecure]
  address = ":443"

  [entryPoints.websecure.http]
    aliasHeadersStrategy = "delete"

CLI

--entryPoints.websecure.address=:443
--entryPoints.websecure.http.aliasHeadersStrategy=delete

Setting underscoreHeadersStrategy logs a deprecation warning. Configuring both options with different values makes the install configuration invalid.

Traefik now logs a warning at startup for every entry point left without this option configured, as the middlewares managing request headers rely on it to not be spoofed with an aliasing name.

Please check out the entry point aliasHeadersStrategy option and the Headers with Aliasing Names documentation for more details.

From doc.traefik.io/traefik/migrate/v3/#aliasheadersstrategy

Migration

TCP and UDP Weighted Services: Negative Weights

Negative weights in a TCP or UDP weighted service are now rejected when the service is built. Such a configuration previously made the load-balancer selection loop endlessly while holding its lock, which consumed a CPU core and blocked every subsequent connection to that service until Traefik was restarted.

A weighted service declaring a negative weight is now reported as disabled in the API, with the error attached, and the routers referencing it are not created. Replace any negative weight with a positive one, or with 0 to take a child service out of the rotation.

From doc.traefik.io/traefik/migrate/v3/#tcp-and-udp-weighted-services-negative-weights

Migration

TCP and UDP Weighted Services: Child Service Errors

When a child of a TCP or UDP weighted service cannot be built, for instance because it does not exist, the parent weighted service is now reported as disabled in the API, with the error attached, as the HTTP weighted service already was. Such a parent service previously reported neither an error nor a status.

This only changes what is reported: the routers referencing the parent service were already not created.

From doc.traefik.io/traefik/migrate/v3/#tcp-and-udp-weighted-services-child-service-errors

Full release notes for 3.7.12

3.7.13 2026-09-04

Migration

h2c Upgrade Requests

Starting with v3.7.13, Traefik does not forward the Upgrade: h2c and HTTP2-Settings request headers to the backends anymore.

Traefik does not implement the deprecated h2c upgrade mechanism, it only serves unencrypted HTTP/2 with prior knowledge. Forwarding those headers let a backend accept an upgrade that Traefik itself had not negotiated with the client.

A backend that used to accept such an upgrade now serves those requests over HTTP/1.1. To reach a backend over unencrypted HTTP/2, declare its servers with the h2c scheme:

File (YAML)

## Dynamic configuration
http:
  services:
    my-service:
      loadBalancer:
        servers:
        - url: "h2c://private-ip-server-1:8080"

File (TOML)

## Dynamic configuration
[http.services]
  [http.services.my-service.loadBalancer]

    [[http.services.my-service.loadBalancer.servers]]
      url = "h2c://private-ip-server-1:8080"

The providers exposing a scheme instead of a server URL take it the same way, with the traefik.http.services.<service_name>.loadbalancer.server.scheme=h2c label, the scheme: h2c option of the Kubernetes CRD, or the traefik.ingress.kubernetes.io/service.serversscheme: h2c Kubernetes Ingress annotation.

From doc.traefik.io/traefik/migrate/v3/#h2c-upgrade-requests

Migration

Request Target Validation

Starting with v3.7.13, a request whose target is rootless, that is a target made of a scheme followed by something that does not start with a slash, is rejected with a 400 Bad Request response. Such a target is none of the four forms allowed by rfc9112#section-3.2.

A rootless target, for instance http:example.com/admin, carries no path, hence escaping the path handling and the routing rules while still designating a resource on the backend. This rejection is not configurable, as allowing such a target would reintroduce the bypass.

As the validation happens before the routing, the rejected requests are not reported in the access logs. They are only visible at the DEBUG log level.

From doc.traefik.io/traefik/migrate/v3/#request-target-validation

Migration

Consul Catalog and Nomad: colliding service configurations

The Consul Catalog and the Nomad providers build the configuration of each service instance separately, and then merge all of them together. Until v3.7.13, the instances were identified by the normalized concatenation of their node, service name and service ID, which is ambiguous: two distinct instances could produce the same identifier, and the configuration of all but the last of them was silently discarded.

Starting with v3.7.13, this identifier is unambiguous, and every instance contributes to the merge.

Newly detected conflicts

The configurations that were previously discarded are now merged. A router or a middleware defined by several instances is only kept if all of them define it identically, and a service only if the instances agree on everything but their servers, which are then pooled together. Otherwise the resource is removed altogether, an error is logged, and a router served before the upgrade can disappear. The merge order changes as well, and with it the order of the servers of a load-balancer.

From doc.traefik.io/traefik/migrate/v3/#consul-catalog-and-nomad-colliding-service-configurations

Full release notes for 3.7.13

Release notes from github.com/traefik/traefik/blob/master/CHANGELOG.md, and Migration: Steps needed between the versions, checked 17 hours ago. Only text the vendor marks as breaking, or puts in a warning/caution/important note, is shown; read the full notes for anything else. Traefik's release notes (CHANGELOG.md, GitHub releases) are lists of merged pull requests and mark nothing as breaking. What is quoted instead is Traefik's migration documentation on doc.traefik.io: “Migration: Steps needed between the versions” (v3), the same page of the v2.11 documentation (v2), and “Configuration Details for Migrating from Traefik v2 to v3” (on 3.0.0). Each section of those pages is labelled “Migration” and shown on the release its heading names (“v3.3 to v3.4” on 3.4.0). A section naming a canceled release (v2.4.10, v2.9.0) is shown on the next release of that line. Versions are covered from 2.0.0. No required stop is documented.