Scrydon

TLS Offloading

Configurez Traefik derrière un équilibreur de charge qui termine le TLS (App Gateway / ALB / GCP LB), gardez l'ingress privé et dépannez les erreurs 502 Bad Gateway.

Ces paramètres s'appliquent à votre release Traefik, pas au chart Scrydon. Le chart Scrydon ne provisionne jamais de contrôleur d'ingress ; il génère uniquement les objets Ingress que votre contrôleur route.

Derrière un équilibreur de charge qui termine le TLS

Si un équilibreur de charge en amont termine le TLS et transmet du HTTP brut à Traefik — Azure Application Gateway, AWS ALB, GCP HTTP(S) LB, F5 — Traefik doit être configuré pour faire confiance à la plage d'IP source de cet équilibreur. Sans cela, trois symptômes apparaissent :

  • Boucles de redirection HTTP → HTTPS. Traefik voit du HTTP brut et redirige vers HTTPS ; l'équilibreur termine à nouveau le TLS et transmet du HTTP. Le navigateur tourne en boucle.
  • Mauvaise IP cliente. Les limites de débit par IP et les journaux d'audit enregistrent l'IP de l'équilibreur plutôt que celle du vrai client.
  • La connexion semble fonctionner, puis le cookie de session disparaît au prochain clic. Better-Auth lit x-forwarded-proto pour calculer son schéma public. Quand Traefik le réécrit en http, le cookie sécurisé est rejeté ou le POST cross-origin est refusé — pas de boucle de redirection, pas de 5xx, juste un « je suis déconnecté » silencieux.

Deux conditions doivent être réunies :

  1. Traefik doit voir l'IP source réelle de l'équilibreur au niveau TCP. La valeur par défaut externalTrafficPolicy: Cluster fait que kube-proxy effectue un SNAT vers l'IP du nœud avant que Traefik le reçoive. Définir Local pour préserver l'IP source en amont.
  2. Les entrypoints doivent lister le CIDR source de l'équilibreur comme fiable, afin que Traefik honore les en-têtes X-Forwarded-* qu'il envoie.
# traefik-values.yaml — votre release Traefik, pas le chart Scrydon.
service:
  spec:
    externalTrafficPolicy: Local

ports:
  web:
    forwardedHeaders:
      trustedIPs:
        - 10.0.1.0/24   # le sous-réseau depuis lequel l'équilibreur transmet (App Gateway, pare-feu, …)
  websecure:
    forwardedHeaders:
      trustedIPs:
        - 10.0.1.0/24
helm upgrade --install traefik traefik/traefik \
  --namespace traefik --create-namespace \
  -f traefik-values.yaml

trustedIPs est une liste — utilisez un fichier de valeurs, pas le style --set. Un --set inline fonctionne pour une valeur unique, mais devient fragile avec --reuse-values lors des mises à jour suivantes.

Cela complète le middleware force-https du chart Scrydon (ingress.middleware.forceHttps, activé par défaut). Ce middleware s'exécute après la logique des entrypoints de Traefik — il ne stoppe pas la boucle de redirection ni ne restaure l'IP cliente par lui-même.

Raccourci de diagnostic

Si vous suspectez ce problème sans connaître le bon CIDR, faites temporairement confiance à tout :

helm upgrade traefik traefik/traefik -n traefik --reuse-values \
  --set "ports.web.forwardedHeaders.insecure=true" \
  --set "ports.websecure.forwardedHeaders.insecure=true"

Si le symptôme disparaît, lisez l'IP source depuis les journaux d'accès (kubectl logs -n traefik -l app.kubernetes.io/name=traefik | rg ClientAddr), convertissez-la en CIDR de sous-réseau, définissez trustedIPs et désactivez à nouveau insecure. Laisser insecure: true en production permet à n'importe quelle charge de travail de falsifier les en-têtes X-Forwarded-*.

ingress.tls.enabled — schéma public, pas protocole backend

C'est un piège classique :

ingress.tls.enabled est l'interrupteur « Scrydon est-il accessible via HTTPS par le navigateur ? » — ce n'est pas un bouton « Traefik termine-t-il le TLS ».

Le chart l'utilise pour dériver le schéma de chaque URL que les applications publient (APP_URL, URL de callback Better-Auth, liste d'autorisation CORS) et pour piloter le comportement des cookies sécurisés. false → les applications émettent des URL http:// ; truehttps://.

Derrière un App Gateway qui sert le site en HTTPS, définissez ingress.tls.enabled: true même si l'équilibreur transmet du HTTP brut au cluster.

ingress:
  enabled: true
  tls:
    enabled: true                       # le navigateur utilise https → mettre true quel que soit le saut backend
    clusterIssuer: letsencrypt-prod
routing:
  mode: subpath
  host: app.example.com                 # doit être égal au nom d'hôte du listener App Gateway

Si le navigateur utilise https:// mais que tls.enabled: false, le chart publie http://. Les navigateurs rejettent les cookies sécurisés et Better-Auth rebondit les callbacks de connexion comme des incompatibilités d'origine. L'interface se charge, mais on ne peut jamais terminer la connexion.

Ce que le protocole backend détermine — si Traefik lui-même a besoin d'un vrai certificat :

App Gateway → TraefikTraefik a-t-il besoin d'un certificat ?
HTTP / port 80 (TLS offload — le cas le plus courant)Non. App Gateway détient le seul certificat.
HTTPS / port 443 (re-chiffrement / bout en bout)Oui. Traefik doit terminer le TLS backend — a besoin d'un certificat utilisable dans tls-frontdoor (mode sous-chemin) ou dans des secrets par application (mode sous-domaine).

Cert-manager + défi HTTP-01 derrière un App Gateway : le chemin /.well-known/acme-challenge/… n'est généralement pas accessible publiquement, donc l'émission échoue. Pour le cas de déchargement HTTP/80, c'est sans conséquence (Scrydon a seulement besoin du schéma, pas d'un vrai certificat). Pour le re-chiffrement HTTPS/443, optez pour DNS-01, pré-créez le secret TLS avec votre propre certificat, ou comptez sur App Gateway qui ne pinne pas une racine backend.

Garder l'ingress privé

Le chart Scrydon ne provisionne jamais d'IP publique. Tous les Services sont ClusterIP. L'IP externe provient du contrôleur Traefik (type LoadBalancer par défaut).

Pour donner à Traefik une adresse privée VNet/VPC, annotez son Service :

# traefik-values.yaml
service:
  annotations:
    # AKS
    service.beta.kubernetes.io/azure-load-balancer-internal: "true"
    # AWS EKS
    # service.beta.kubernetes.io/aws-load-balancer-internal: "true"
    # GKE
    # networking.gke.io/load-balancer-type: "Internal"
  spec:
    externalTrafficPolicy: Local

ports:
  web:
    forwardedHeaders:
      trustedIPs: [10.0.1.0/24]
  websecure:
    forwardedHeaders:
      trustedIPs: [10.0.1.0/24]
helm upgrade --install traefik traefik/traefik \
  --namespace traefik --create-namespace \
  -f traefik-values.yaml

kubectl -n traefik get svc traefik
# EXTERNAL-IP devrait être une adresse privée VNet/VPC (ex. 10.0.x.x).

Reconfigurez ensuite le pool backend de l'équilibreur en amont pour pointer vers cette IP Traefik privée.

externalTrafficPolicy: Local oblige l'équilibreur cloud à sonder chaque nœud et à ne transmettre qu'aux nœuds qui exécutent un pod Traefik. Faites tourner ≥ 2 répliques Traefik réparties sur les nœuds (le chart le fait par défaut) — le drain d'un seul nœud peut sinon couper l'ingress.

Dépannage des erreurs 502 Bad Gateway

Une 502 de l'équilibreur en amont signifie que son pool backend est en mauvaise santé — la requête n'a jamais reçu de bonne réponse de Traefik. Les changements trustedIPs modifient la façon dont Traefik interprète les requêtes ; ils ne rendent pas le backend accessible.

Isolez le saut défaillant depuis le pod vers l'extérieur :

# 1. Le backend Scrydon est-il en bonne santé ?
kubectl -n scrydon-platform get pods          # tous Running, 2/2 avec le sidecar Dapr ?

# 2. Traefik route-t-il la requête ? Envoyez le vrai en-tête Host directement à Traefik.
curl -i -H "Host: app.example.com" http://<traefik-ip>/platform
#    200/3xx → Traefik fonctionne ; cherchez en amont au niveau de l'équilibreur.
#    404     → l'en-tête Host ne correspond pas à `routing.host`.
#    502/503 → Traefik n'a pas de backend sain → retourner à l'étape 1.

Causes habituelles :

  • Le pool backend pointe vers une IP Traefik périmée — ex. vous avez basculé Traefik de public vers interne et l'équilibreur cible encore l'ancienne IP publique.
  • Le paramètre HTTP backend utilise HTTPS ou le mauvais port. Traefik reçoit du HTTP sur :80 (web) ; le paramètre backend de l'équilibreur doit être HTTP / port 80.
  • La sonde de santé reçoit une redirection ou une incompatibilité de Host. Pointez vers un chemin servi par Scrydon, envoyez routing.host comme Host, acceptez 200–399. Si la sonde reçoit encore 301 → https, Traefik réécrit X-Forwarded-Proto — définissez externalTrafficPolicy: Local et vérifiez que le CIDR trustedIPs correspond au sous-réseau de l'équilibreur (pas à celui du client).
Sur cette page

Sur cette page