---
title: Infra — Risques & vigilance : Traefik
domain: infra
bucket: risques
tags: [traefik, docker, reverse-proxy, bun, websocket, basic-auth, ios]
applies_to: [implementation, review, debug, architecture]
severity: high
validated_on: 2026-06-25
source_projects: [_Assistant_Cuisine]
---

# Infra — Risques & vigilance : Traefik

> Extrait de la base de connaissance Lead_tech. Voir `knowledge/infra/risques/README.md` pour l'index complet.

---

<a id="risque-traefik-v3-docker29-api"></a>
## Pièges Traefik v3 + Docker Engine 29

### Risques

- **Incompatibilité d'API Docker** : Docker 29 a élevé la minimum API version. Traefik < 3.6 utilise un client Docker SDK figé en `1.24` ; le daemon refuse la connexion et aucune route ne fonctionne.
- **`PathPrefix(/api)` trop large** : un routeur `Host(...) && PathPrefix(/api)` vole les routes `/api/*` de toutes les autres apps du même domaine (Homepage `/api/services`, Next.js `/api/...`, n'importe quel SPA) → 401/404 silencieux.
- **Bun `new Response(body, {status: 3xx})` perd le header `Location`** : un proxy HTTP en Bun qui forward un upstream 302/303 retransmet le status mais le client reçoit un 200 vide (ou un status sans `Location`). Le navigateur ne suit pas la redirection.

### Symptômes

- Container Traefik qui tourne mais aucune route active, logs en boucle :

```
ERR Failed to retrieve information of the docker client and server host
error="Error response from daemon: client version 1.24 is too old.
Minimum supported API version is 1.40, please upgrade your client to a newer version"
```

- Une app exposée sur le même domaine que le dashboard Traefik se met à retourner 401/404 sur ses propres `/api/*`.
- Un proxy Bun qui forward une redirection : le client reçoit un 200 vide ou un `Location` nul.

### Bonnes pratiques / mitigations

**Incompatibilité API Docker**

- Utiliser **Traefik 3.6.1+** (client Docker avec négociation auto de version). Les tags `:v3.5` / `:v3.2` ne marchent pas, même avec `DOCKER_API_VERSION=1.44` en env (le client n'honore pas cette variable dans Traefik).
- Pinner explicitement la version (ex. `traefik:v3.6.15`), jamais le tag mouvant `:v3.6`.
- Vérifier la compatibilité Traefik ↔ Docker Engine **avant** un upgrade Docker.

**`PathPrefix(/api)` trop large**

```yaml
# ❌ trop large — capture tous les /api/* du domaine
- "traefik.http.routers.dashboard-api.rule=Host(`example.com`) && PathPrefix(`/api`)"

# ✅ ne capture que les endpoints natifs Traefik
- "traefik.http.routers.dashboard-api.rule=Host(`example.com`) && PathRegexp(`^/api/(overview|version|rawdata|support-dump|entrypoints|http|tcp|udp)(/|$$)`)"
```

Les endpoints natifs Traefik sont fixés : `overview`, `version`, `rawdata`, `support-dump`, `entrypoints`, `http/*`, `tcp/*`, `udp/*`. Sur un domaine partagé entre plusieurs apps : **jamais** de `PathPrefix(/api)` générique, toujours une regex explicite.

**Bun `new Response` perd le `Location`**

```ts
// ❌ perd le Location dans Bun (~1.1.x)
return new Response(upstream.body, {
  status: upstream.status,   // 303
  headers: upstream.headers, // contient Location, ignoré au final
});

// ✅ Hono c.redirect() ou équivalent
if (upstream.status >= 300 && upstream.status < 400) {
  const loc = upstream.headers.get("location");
  if (loc) return c.redirect(loc, upstream.status as 301 | 302 | 303 | 307 | 308);
}
```

**Règle** : tout proxy HTTP qui forward des redirects upstream doit traiter explicitement la branche 3xx avant la branche "body normal".

- Contexte technique : Traefik v3 / Docker 29 / Bun + Hono — _Assistant_Cuisine 04-05-2026

---

<a id="risque-basic-auth-websocket-webkit-ios"></a>
## Basic auth + WebSocket : re-prompts répétés (surtout WebKit/iOS)

### Risques

- Une app derrière une basic auth (Traefik, nginx) qui utilise des WebSockets (code-server, Jupyter, ttyd, et beaucoup d'apps "live") déclenche **plusieurs prompts d'authentification** à l'ouverture, même quand les credentials viennent d'être saisis.

### Symptômes

- 3 prompts d'authentification successifs à chaque ouverture de l'app, observés notamment sur tablette iOS / iPadOS.
- Persiste sur Chrome iOS et Firefox iOS (tous contraints d'utiliser WebKit sur iOS). Sporadique sur macOS, rare sur desktop Linux/Windows.

### Cause

Safari (et tous les navigateurs iOS, contraints à WebKit) ne **propage pas systématiquement les credentials basic auth aux requêtes WebSocket** d'une page déjà authentifiée. Chaque WS qui échoue redéclenche un prompt.

### Bonnes pratiques / mitigations

Remplacer la basic auth par une auth à **cookie de session** :

- Soit l'auth native de l'app si elle existe (code-server `HASHED_PASSWORD`, JupyterHub login form, etc.).
- Soit un système central type Authelia / Authentik / traefik-forward-auth qui pose un cookie partagé entre apps.

Le cookie passe automatiquement avec les requêtes WebSocket (même origine) → plus de re-prompt.

**Règle** : pour toute app qui utilise des WebSockets ET qui doit être protégée, ne **pas** utiliser la basic auth. Toujours cookie-based. La basic auth reste OK pour des UI sans WS (dashboards en pull, API REST simples).

- Contexte technique : Traefik / basic auth / WebKit iOS — _Assistant_Cuisine 04-05-2026
