---
title: "Traefik Migration Documentation"
description: "Learn the steps needed to migrate to new Traefik Proxy v3 versions. Read the technical documentation."
---

# Migration: Steps needed between the versions

This guide provides detailed migration steps for upgrading between different Traefik v3 versions. Each section covers breaking changes, deprecations, and configuration updates required for a smooth transition.

---

## v3.7.3

### 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`](../reference/install-configuration/providers/kubernetes/kubernetes-gateway.md#opt-providers-kubernetesgateway-qps)
and [`kubernetesGateway.burst`](../reference/install-configuration/providers/kubernetes/kubernetes-gateway.md#opt-providers-kubernetesgateway-burst) provider options.

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

### 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 path | Path after strip | Normalised path | Result       |
|--------------|------------------|-----------------|--------------|
| `/api/foo`   | `/foo`           | `/foo`          | `200` (sent) |
| `/api/`      | `/`              | `/`             | `200` (sent) |
| `/api./foo`  | `/./foo`         | `/foo`          | `400`        |
| `/api../foo` | `/../foo`        | `/foo`          | `400`        |

---

## v3.7.1

### 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:

| Value      | Behavior                                                                                  |
|------------|-------------------------------------------------------------------------------------------|
| not set    | All 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](../reference/install-configuration/providers/kubernetes/kubernetes-crd.md#opt-providers-kubernetesCRD-crossProviderNamespaces), [Kubernetes Ingress](../reference/install-configuration/providers/kubernetes/kubernetes-ingress.md#opt-providers-kubernetesIngress-crossProviderNamespaces),
and [Kubernetes Gateway](../reference/install-configuration/providers/kubernetes/kubernetes-gateway.md#opt-providers-kubernetesGateway-crossProviderNamespaces) provider documentation for more details.

---

## v3.7.0

### 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](../reference/dynamic-configuration/kubernetes-ingress-nginx-rbac.yml) provider RBACs) the `configmaps` right has been added.

**Required RBAC Updates:**

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

### Kubernetes Gateway API Provider

Starting with `v3.7.0`, the Kubernetes Gateway API provider supports version [v1.5.1](https://github.com/kubernetes-sigs/gateway-api/releases/tag/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:**

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

For the experimental channel:

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

### 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:**

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

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

---

## v3.6.19

### Kubernetes Gateway API Provider

Starting with `v3.6.19`, 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`](../reference/install-configuration/providers/kubernetes/kubernetes-gateway.md#opt-providers-kubernetesgateway-qps)
and [`kubernetesGateway.burst`](../reference/install-configuration/providers/kubernetes/kubernetes-gateway.md#opt-providers-kubernetesgateway-burst) provider options.

### BasicAuth Middleware

From version `v3.6.19` 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.

### StripPrefix and StripPrefixRegex Middleware

From version `v3.6.19` 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 path | Path after strip | Normalised path | Result       |
|--------------|------------------|-----------------|--------------|
| `/api/foo`   | `/foo`           | `/foo`          | `200` (sent) |
| `/api/`      | `/`              | `/`             | `200` (sent) |
| `/api./foo`  | `/./foo`         | `/foo`          | `400`        |
| `/api../foo` | `/../foo`        | `/foo`          | `400`        |

---

## v3.6.17

### Kubernetes providers: `crossProviderNamespaces`

In `v3.6.17`, 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:

| Value      | Behavior                                                                                  |
|------------|-------------------------------------------------------------------------------------------|
| not set    | All 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](../reference/install-configuration/providers/kubernetes/kubernetes-crd.md#opt-providers-kubernetesCRD-crossProviderNamespaces), [Kubernetes Ingress](../reference/install-configuration/providers/kubernetes/kubernetes-ingress.md#opt-providers-kubernetesIngress-crossProviderNamespaces),
and [Kubernetes Gateway](../reference/install-configuration/providers/kubernetes/kubernetes-gateway.md#opt-providers-kubernetesGateway-crossProviderNamespaces) provider documentation for more details.

## v3.6.16

### 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](https://docs.docker.com/reference/api/engine/#api-version-matrix)).
Users running older (end of life) versions of Docker Engine should update their
Docker Engine or use the [`DOCKER_API_VERSION`](https://docs.docker.com/reference/api/engine/#versioned-api-and-sdk)
environment variable to override the API version used by Traefik.

## v3.6.15

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](../reference/routing-configuration/http/middlewares/errorpages.md#errorRequestHeaders) middleware documentation for more details.

## v3.6.14

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

### 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](../reference/install-configuration/entrypoints.md#forwarded-headers) 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](../reference/routing-configuration/http/middlewares/forwardauth.md#opt-trustForwardHeader) middleware documentation for more details.

---

## v3.6.9

### `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](../reference/routing-configuration/http/middlewares/forwardauth.md#opt-maxResponseBodySize) middleware documentation for more details.

### 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:**

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

---

## v3.6.8

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

---

## v3.6.7

### 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 Character | Character               | Config options                                                                       | Default value |
|-------------------|-------------------------|--------------------------------------------------------------------------------------|---------------|
| `%2f` or `%2F`    | `/` (slash)             | `entryPoints.<name>`<br/>`.http.encodedCharacters`<br/>`.allowEncodedSlash`          | `true`        |
| `%5c` or `%5C`    | `\` (backslash)         | `entryPoints.<name>`<br/>`.http.encodedCharacters`<br/>`.allowEncodedBackSlash`      | `true`        |
| `%00`             | `NULL` (null character) | `entryPoints.<name>`<br/>`.http.encodedCharacters`<br/>`.allowEncodedNullCharacter`  | `true`        |
| `%3b` or `%3B`    | `;` (semicolon)         | `entryPoints.<name>`<br/>`.http.encodedCharacters`<br/>`.allowEncodedSemicolon`      | `true`        |
| `%25`             | `%` (percent)           | `entryPoints.<name>`<br/>`.http.encodedCharacters`<br/>`.allowEncodedPercent`        | `true`        |
| `%3f` or `%3F`    | `?` (question mark)     | `entryPoints.<name>`<br/>`.http.encodedCharacters`<br/>`.allowEncodedQuestionMark`   | `true`        |
| `%23`             | `#` (hash)              | `entryPoints.<name>`<br/>`.http.encodedCharacters`<br/>`.allowEncodedHash`           | `true`        |

Note: This check is not done against query parameters,
but only against the request path as defined
in [RFC3986 section-3](https://datatracker.ietf.org/doc/html/rfc3986#section-3).

Please check out the entrypoint [encodedCharacters option](../reference/install-configuration/entrypoints.md#encoded-characters) documentation
for more details.

---

## v3.6.4

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

Please check out the entrypoint [encodedCharacters option](../reference/install-configuration/entrypoints.md#opt-http-encodedCharacters) documentation for more details.

---

## v3.6.2

### 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:**

??? example "Experimental kubernetesIngressNGINX option (deprecated)"

    ```yaml tab="File (YAML)"
    experimental:
      kubernetesIngressNGINX: true
    ```

    ```toml tab="File (TOML)"
    [experimental]
        kubernetesIngressNGINX=true
    ```

    ```bash tab="CLI"
    --experimental.kubernetesIngressNGINX=true
    ```

**Migration Steps:**

1. Remove the `kubernetesIngressNGINX` option from the experimental section
2. Configure the provider using the [kubernetesIngressNGINX Provider documentation](../reference/install-configuration/providers/kubernetes/kubernetes-ingress-nginx.md)

---

## v3.6.0

### Kubernetes Gateway API Provider

Starting with `v3.6.0`, the Kubernetes Gateway API provider only supports version [v1.4.0](https://github.com/kubernetes-sigs/gateway-api/releases/tag/v1.4.0) of the specification,
which requires the Gateway API CRDs to be updated.

**Apply Updated CRDs:**

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

For the experimental channel:

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

### 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:**

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

---

## v3.5.4

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

---

## v3.5.2

### 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](../reference/routing-configuration/tcp/serverstransport.md#opt-serverstransport-proxyProtocol) 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:**

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

---

## v3.5.0

### Observability

#### TraceVerbosity on Routers and Entrypoints

Starting with `v3.5.0`, a new `traceVerbosity` option is available for both entrypoints and routers.
This option allows you to control the level of detail for tracing spans.
Routers can override the value inherited from their entrypoint.

**Impact:**

- If you rely on tracing, review your configuration to explicitly set the desired verbosity level.
- Existing configurations will default to `minimal` unless overridden, which will result in fewer spans being generated than before.

Possible values are:

- `minimal`: produces a single server span and one client span for each request processed by a router.
- `detailed`: enables the creation of additional spans for each middleware executed for each request processed by a router.

See the updated documentation for [entrypoints](../reference/install-configuration/entrypoints.md#opt-observability-traceVerbosity) and [dynamic routers](../reference/routing-configuration/http/routing/observability.md#opt-traceVerbosity).

#### K8s Resource Attributes

Since `v3.5.0`, the semconv attributes `k8s.pod.name` and `k8s.pod.uid` are injected automatically in OTel resource attributes when OTel tracing/logs/metrics are enabled.

For that purpose, the following right has to be added to the Traefik Kubernetes RBACs:

```yaml
  ...
  - apiGroups:
      - ""
    resources:
      - pods
    verbs:
      - get
  ...
```

---

## v3.4.5

### MultiPath TCP

Since `v3.4.5`, the MultiPath TCP support introduced with `v3.4.2` has been removed.
It appears that enabling MPTCP on some platforms can cause Traefik to stop with the following error logs message:

- `set tcp X.X.X.X:X->X.X.X.X:X: setsockopt: operation not supported`

However, it can be re-enabled by setting the `multipathtcp` variable in the GODEBUG environment variable, see the related [go documentation](https://go.dev/doc/godebug#go-124).

---

## v3.4.1

### Request Path Normalization

Starting with v3.4.1, request paths are now normalized according to RFC 3986 standards for better consistency and security.

**Normalization Process:**

1. **Unreserved Character Decoding:** Characters like `%2E` (.) are decoded to their literal form
2. **Case Normalization:** Percent-encoded characters are uppercased (`%2e` becomes `%2E`)

This follows [RFC 3986 percent-encoding normalization](https://datatracker.ietf.org/doc/html/rfc3986#section-6.2.2.2) and [case normalization](https://datatracker.ietf.org/doc/html/rfc3986#section-6.2.2.1) standards.

**Processing Order:**

1. Path normalization (cannot be disabled)
2. Path sanitization (if enabled)

### Reserved Character Handling in Routing

Starting with v3.4.1, reserved characters (per [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986#section-2.2)) remain encoded during router rule matching to prevent routing ambiguity.

**Why This Matters:**
Reserved characters change the meaning of request paths when decoded. Keeping them encoded during routing prevents security vulnerabilities and ensures predictable routing behavior.

### Request Path Matching Examples

The following table illustrates how path matching behavior has changed:

| Request Path      | Router Rule                  | Traefik v3.4.0 | Traefik v3.4.1 | Explanation                                           |
|-------------------|------------------------------|----------------|----------------|-------------------------------------------------------|
| `/foo%2Fbar`      | ```PathPrefix(`/foo/bar`)``` | Match          | No match       | `%2F` (/) stays encoded, preventing false matches     |
| `/foo/../bar`     | ```PathPrefix(`/foo`)```     | No match       | No match       | Path traversal is sanitized away                      |
| `/foo/../bar`     | ```PathPrefix(`/bar`)```     | Match          | Match          | Resolves to `/bar` after sanitization                 |
| `/foo/%2E%2E/bar` | ```PathPrefix(`/foo`)```     | Match          | No match       | Encoded dots normalized then sanitized                |
| `/foo/%2E%2E/bar` | ```PathPrefix(`/bar`)```     | No match       | Match          | Resolves to `/bar` after normalization + sanitization |

---

## v3.3 to v3.4

### Kubernetes CRD Provider

#### Load-Balancing Strategy Updates

Starting with v3.4, HTTP service definitions now support additional load-balancing strategies for better traffic distribution.

**Apply Updated CRDs:**

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

**New Strategy Values:**

- `wrr` (Weighted Round Robin)
- `p2c` (Power of Two Choices)

!!! warning "Deprecation"
    The `RoundRobin` strategy is deprecated but still supported (equivalent to `wrr`). It will be removed in the next major release.

Refer to the [HTTP Services Load Balancing documentation](../reference/routing-configuration/http/load-balancing/service.md#opt-strategy) for detailed information.

#### ServersTransport CA Certificate Configuration

A new `rootCAs` option has been added to the `ServersTransport` and `ServersTransportTCP` CRDs. It supports both ConfigMaps and Secrets for CA certificates and replaces the `rootCAsSecrets` option.

**Apply Updates:**

```shell
# Update CRDs
kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v3.4/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml

# Update RBACs
kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v3.4/docs/content/reference/dynamic-configuration/kubernetes-crd-rbac.yml
```

**New Configuration Format:**

```yaml
---
apiVersion: traefik.io/v1alpha1
kind: ServersTransport
metadata:
  name: foo
  namespace: bar
spec:
  rootCAs:
    - configMap: ca-config-map
    - secret: ca-secret
      
---      
apiVersion: traefik.io/v1alpha1
kind: ServersTransportTCP
metadata:
  name: foo
  namespace: bar
spec:
  rootCAs:
    - configMap: ca-config-map
    - secret: ca-secret
```

!!! warning "Deprecation"
    The `rootCAsSecrets` option (Secrets only) is still supported but deprecated. It will be removed in the next major release.

### Rule Syntax Configuration

In v3.4, rule syntax configuration options will be removed in the next major version.

**Deprecated Options:**

- `core.defaultRuleSyntax` (static configuration)
- `ruleSyntax` (router option)

These options were transitional helpers for migrating from v2 to v3 syntax. Please ensure all router rules use v3 syntax before the next major release.

---

## v3.3.6

### Request Path Sanitization

Starting with v3.3.6, incoming request paths are now automatically cleaned before processing for security and consistency.

**What's Changed:**

The following path segments are now interpreted and collapsed:

- `/../` (parent directory references)
- `/./` (current directory references)  
- Duplicate slash segments (`//`)

**Disabling Sanitization:**

```yaml
# EntryPoint HTTP configuration
entryPoints:
  web:
    address: ":80"
    http:
      sanitizePath: false  # Not recommended
```

!!! danger "Security Warning"
    Setting `sanitizePath: false` is not safe. This option should only be used with legacy clients that don't properly URL-encode data. Always ensure requests are properly URL-encoded instead of disabling this security feature.

**Example Risk:**
Base64 data containing "/" characters can lead to unsafe routing when path sanitization is disabled and the data isn't URL-encoded.

---

## v3.3.5

### Compress Middleware Default Encodings

In v3.3.5, the default compression algorithms have been reordered to favor gzip compression.

**New Default:** `gzip, br, zstd`

This change affects requests that either:

- Don't specify preferred algorithms in the `Accept-Encoding` header
- Have no order preference in their `Accept-Encoding` header

The reordering helps ensure better compatibility with older clients that may not support newer compression algorithms.

---

## v3.3.4

### OpenTelemetry Request Duration Metric

In v3.3.4, the OpenTelemetry Request Duration metric unit has been standardized to match other providers and naming conventions.

**Change Details:**

- **Metric:** `traefik_(entrypoint|router|service)_request_duration_seconds`
- **Old Unit:** Milliseconds  
- **New Unit:** Seconds

This change ensures consistency across all metrics providers and follows standard naming conventions.

---

## v3.2 to v3.3

### ACME DNS Certificate Resolver

In v3.3, DNS challenge configuration options have been reorganized for better clarity.

**Migration Required:**

| Deprecated Option | New Option |
|-------------------|------------|
| `acme.dnsChallenge.delaybeforecheck` | `acme.dnsChallenge.propagation.delayBeforeChecks` |
| `acme.dnsChallenge.disablepropagationcheck` | `acme.dnsChallenge.propagation.disableChecks` |

### Tracing Global Attributes

In v3.3, the tracing configuration has been clarified to better reflect its purpose.

**Migration Required:**

- **Old:** `tracing.globalAttributes`
- **New:** `tracing.resourceAttributes`

The old option name was misleading as it specifically adds resource attributes for the collector, not global span attributes.

---

## v3.2.2

### Swarm Provider Label Updates

In v3.2.2, Swarm-specific labels have been deprecated and will be removed in a future version.

**Migration Required:**

| Deprecated Label | New Label |
|------------------|-----------|
| `traefik.docker.network` | `traefik.swarm.network` |
| `traefik.docker.lbswarm` | `traefik.swarm.lbswarm` |

---

## v3.2.1

### `X-Forwarded-Prefix` Header Changes

In v3.2.1, the `X-Forwarded-Prefix` header is now handled like other `X-Forwarded-*` headers - Traefik removes it when sent from untrusted sources.

This change improves security by preventing header spoofing from untrusted clients. Refer to the [Forwarded headers documentation](../reference/install-configuration/entrypoints.md#forwarded-headers) for configuration details.

---

## v3.1 to v3.2

### Kubernetes CRD Provider

New optional fields have been added to several CRDs. These updates are backward compatible and only add new functionality.

**Apply the latest CRDs:**

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

**Updated Resources:**

- [TraefikService](../reference/routing-configuration/kubernetes/crd/http/traefikservice.md#opt-mirrorBody) ([PR #11032](https://github.com/traefik/traefik/pull/11032))
- [RateLimit](../reference/routing-configuration/http/middlewares/ratelimit.md#opt-sourceCriterion-ipStrategy-ipv6Subnet) & [InFlightReq](../reference/routing-configuration/http/middlewares/inflightreq.md#opt-sourceCriterion-ipStrategy-ipv6Subnet) middlewares ([PR #9747](https://github.com/traefik/traefik/pull/9747))
- [Compress](../reference/routing-configuration/http/middlewares/compress.md#opt-encodings) middleware ([PR #10943](https://github.com/traefik/traefik/pull/10943))

### Kubernetes Gateway Provider Standard Channel

Starting with v3.2, the Kubernetes Gateway Provider now supports [GRPCRoute](https://gateway-api.sigs.k8s.io/api-types/grpcroute/) resources.

Therefore, in the corresponding RBACs (see [KubernetesGateway](../reference/install-configuration/providers/kubernetes/kubernetes-gateway.md#requirements) provider RBACs),
the `grcroutes` and `grpcroutes/status` rights have to be added.

**Required RBAC Updates:**

```yaml
...
- apiGroups:
    - gateway.networking.k8s.io
  resources:
    - grpcroutes
  verbs:
    - get
    - list
    - watch
- apiGroups:
    - gateway.networking.k8s.io
  resources:
    - grpcroutes/status
  verbs:
    - update
...
```

### Kubernetes Gateway Provider Experimental Channel

Due to breaking changes in Kubernetes Gateway [v1.2.0-rc1](https://github.com/kubernetes-sigs/gateway-api/releases/tag/v1.2.0-rc1), Traefik v3.3 only supports Kubernetes Gateway v1.2.x when experimental features are enabled.

**New Feature: BackendTLSPolicy Support**

The provider now supports [BackendTLSPolicy](https://gateway-api.sigs.k8s.io/api-types/backendtlspolicy/) resources.

Therefore, in the corresponding RBACs (see [KubernetesGateway](../reference/install-configuration/providers/kubernetes/kubernetes-gateway.md#requirements) provider RBACs),
the `backendtlspolicies` and `backendtlspolicies/status` rights have to be added.

**Required RBAC Updates:**

```yaml
  ...
  - apiGroups:
      - ""
    resources:
      - configmaps
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - gateway.networking.k8s.io
    resources:
      - backendtlspolicies
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - gateway.networking.k8s.io
    resources:
      - backendtlspolicies/status
    verbs:
      - update
  ...
```

---

## v3.1.0 to v3.1.1

### IngressClass Lookup

The `disableIngressClassLookup` option has been deprecated and will be removed in the next major version.

**Migration Required:**

- **Old:** `disableIngressClassLookup`
- **New:** `disableClusterScopeResources`

The new option provides broader control over cluster scope resources discovery, including both IngressClass and Nodes resources.

---

## v3.0 to v3.1

### Kubernetes Provider RBACs

Starting with v3.1, Traefik's Kubernetes Providers use the [EndpointSlices API](https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/) (requires Kubernetes >=v1.21) for service endpoint discovery. This change also introduces NodePort load-balancing capabilities.

The following RBAC updates are required for all Kubernetes providers:

- Remove endpoints permissions and add endpointslices:

```yaml
# Remove this section from your RBAC
# - apiGroups: [""]
#   resources: ["endpoints"]
#   verbs: ["get", "list", "watch"]

# Add this section instead
- apiGroups:
    - discovery.k8s.io
  resources:
    - endpointslices
  verbs:
    - list
    - watch
```

- Add nodes permissions for NodePort support:

```yaml
- apiGroups:
    - ""
  resources:
    - nodes
  verbs:
    - get
    - list
    - watch
```

!!! note "Affected Providers"
    These changes apply to:
    
    - [KubernetesIngress](../reference/install-configuration/providers/kubernetes/kubernetes-ingress.md) provider
    - [KubernetesCRD](../reference/install-configuration/providers/kubernetes/kubernetes-crd.md#requirements) provider
    - [KubernetesGateway](../reference/install-configuration/providers/kubernetes/kubernetes-gateway.md#requirements) provider

#### Gateway API: KubernetesGateway Provider

The KubernetesGateway Provider is no longer experimental in v3.1 and can be enabled without the `experimental.kubernetesgateway` option.

**Deprecated Configuration:**

??? example "Experimental kubernetesgateway option (deprecated)"

    ```yaml tab="File (YAML)"
    experimental:
      kubernetesgateway: true
    ```

    ```toml tab="File (TOML)"
    [experimental]
        kubernetesgateway=true
    ```

    ```bash tab="CLI"
    --experimental.kubernetesgateway=true
    ```

**Migration Steps:**

1. Remove the `kubernetesgateway` option from the experimental section
2. Configure the provider using the [KubernetesGateway Provider documentation](../reference/install-configuration/providers/kubernetes/kubernetes-gateway.md)
