TLS Offloading
Configurez Traefik derrière un équilibreur de charge qui termine le TLS (App Gateway / ALB / GCP LB), gardez la périphérie privée et dépannez les erreurs 502 Bad Gateway.
Ces paramètres s'appliquent à votre release Traefik. Le chart Scrydon génère les objets Gateway et HTTPRoute ; le Traefik qui les programme est soit le vôtre, soit celui que le chart installe lorsque vous définissez traefik.enabled: true.
Vous utilisez le Traefik du chart (traefik.enabled: true) ? Placez les valeurs Traefik ci-dessous sous la clé traefik: de votre fichier de valeurs Scrydon au lieu d'un traefik-values.yaml séparé, et appliquez-les avec votre helm upgrade scrydon … habituel. Ce Traefik tourne dans le namespace traefik et son Service s'appelle scrydon-traefik. Il définit déjà service.spec.externalTrafficPolicy: Local.
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-protopour calculer son schéma public. Quand Traefik le réécrit enhttp, 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 :
- Traefik doit voir l'IP source réelle de l'équilibreur au niveau TCP. La valeur par défaut
externalTrafficPolicy: Clusterfait que kube-proxy effectue un SNAT vers l'IP du nœud avant que Traefik le reçoive. DéfinissezLocalpour préserver l'IP source en amont. - 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 — your Traefik release, not the Scrydon chart.
service:
spec:
externalTrafficPolicy: Local
ports:
web:
forwardedHeaders:
trustedIPs:
- 10.0.1.0/24 # the subnet the LB forwards FROM (App Gateway, firewall, …)
websecure:
forwardedHeaders:
trustedIPs:
- 10.0.1.0/24helm upgrade --install traefik traefik/traefik \
--namespace traefik --create-namespace \
-f traefik-values.yamltrustedIPs 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 la redirection HTTP→HTTPS propre au chart, qui est désormais un filtre RequestRedirect du cœur de la Gateway API posé sur le listener HTTP, généré dès que gateway.tls.enabled est actif. (ingress.middleware.forceHttps.* a disparu — il n'y a plus de bouton.) Cette redirection s'exécute après la logique des entrypoints de Traefik : elle ne stoppe donc pas la boucle de redirection ni ne restaure l'IP cliente par elle-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-*.
gateway.tls.enabled — schéma public, pas protocole backend
C'est un piège classique :
gateway.tls.enabledest 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:// ; true → https://. Il décide aussi si la Gateway reçoit un listener HTTPS et la route de redirection.
Derrière un App Gateway qui sert le site en HTTPS, définissez gateway.tls.enabled: true même si l'équilibreur transmet du HTTP brut au cluster.
gateway:
enabled: true
className: traefik # a GatewayClass name, not an IngressClass
tls:
enabled: true # browser uses https → set true regardless of backend hop
clusterIssuer: letsencrypt-prod
routing:
mode: subpath
host: app.example.com # must equal the App Gateway listener hostnameSi 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.
Avec tls.enabled: false et sans HTTPS en amont, le déploiement fonctionne en HTTP simple. Les applications continuent de fonctionner, mais le navigateur traite la page comme un contexte non sécurisé et Scrydon affiche une bannière que l'on peut fermer. HTTPS est recommandé.
Ce que le protocole backend détermine — si Traefik lui-même a besoin d'un vrai certificat :
| App Gateway → Traefik | Traefik 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). |
Pour les options Let's Encrypt, ACME interne et certificat d'entreprise statique applicables au certificat présenté par Traefik, consultez Certificats TLS.
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 la périphérie privée
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) — l'objet Gateway ne porte aucune adresse propre.
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 should be a VNet/VPC private address (e.g. 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 tout le trafic entrant.
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. Is the Scrydon backend healthy?
kubectl -n scrydon-platform get pods # all Running, 2/2 with Dapr sidecar?
# 2. Are the Gateway and its routes actually programmed?
kubectl get gateway -n scrydon-platform # PROGRAMMED=True
kubectl get httproute -A # one per enabled app
kubectl describe gateway gateway-frontdoor -n scrydon-platform
# 3. Does Traefik route the request? Send the real Host header to Traefik directly.
curl -i -H "Host: app.example.com" http://<traefik-ip>/platform
# 200/3xx → Traefik fine; look upstream at the LB.
# 404 → Host header doesn't match `routing.host`, or no HTTPRoute attached.
# 502/503 → Traefik has no healthy backend → back to step 1.Causes habituelles :
- Un listener de Gateway est
Accepted=Falseavecreason=PortUnavailable.gateway.listenerPorts.*doit correspondre à un port réellement écouté par votre contrôleur. Les entryPoints de Traefik écoutent sur:8000/:8443dans le conteneur alors que son Service publie 80/443 — d'où les valeurs par défaut8000/8443du chart ; un listener sur le port 80 est refusé d'emblée. Une implémentation managée qui écoute sur le port public attend au contraire80/443. - 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.hostcomme Host, acceptez200–399. Si la sonde reçoit encore301 → https, Traefik réécritX-Forwarded-Proto— définissezexternalTrafficPolicy: Localet vérifiez que le CIDRtrustedIPscorrespond au sous-réseau de l'équilibreur (pas à celui du client).