Déploiement et exploitation de la passerelle Claude apps
Enregistrez la passerelle auprès de votre fournisseur d'identité, créez le conteneur, déployez sur Kubernetes ou Cloud Run, et exploitez-la : vérifications de santé, rotation des secrets, mises à jour et sécurité.
[!NOTE]
Planifiez d'abord le réseau de votre passerelle. Lors de la connexion, Claude Code refuse une passerelle Claude apps dont le nom d'hôte se résout en une adresse IP publique, même si celle-ci n'est pas accessible depuis Internet.
Une passerelle Claude apps peut envoyer des paramètres vers les machines des utilisateurs, y compris des hooks qui exécutent des commandes shell. Cette vérification aide à éviter que les utilisateurs ne se connectent accidentellement à une passerelle malveillante sur l'Internet public. Gardez également votre propre passerelle hors d'Internet.
Choisissez l'adresse de la passerelle avant de choisir où elle s'exécute. Il s'agit généralement d'une adresse privée que les utilisateurs atteignent sur votre réseau interne ou via un VPN. Si votre réseau interne utilise des plages IPv4 publiques, vous pouvez indiquer une plage qui contient à la fois la passerelle et les machines de vos utilisateurs. Claude Code considère cette correspondance comme un signe que la passerelle se trouve sur votre réseau interne. Consultez Choisir une adresse pour la passerelle. Si aucune de ces options ne convient à votre réseau, contactez l'équipe chargée de votre compte Anthropic.
Cette page couvre l'aspect opérationnel de l'exécution de la passerelle Claude apps : enregistrement d'un client OAuth auprès de votre fournisseur d'identité (IdP), déploiement de la passerelle en tant que conteneur, et son exploitation au quotidien. Pour chaque option du fichier gateway.yaml que la passerelle lit au démarrage, consultez la Référence de configuration.
Un déploiement en production suit quatre étapes dans l'ordre, et les sections ci-dessous les correspondent. Les deux premières sont des choix à faire ; les deux dernières sont des documents de référence à consulter une fois qu'elle est en cours d'exécution.
- Configurer votre fournisseur d'identité : enregistrez le client OAuth et consultez les notes spécifiques à chaque IdP pour Okta, Entra et Google
- Déployer la passerelle : créez une image de conteneur épinglée et exécutez-la sur Kubernetes, Cloud Run ou votre propre plateforme. Cette section couvre également les décisions concernant les coûts, le contournement, les passerelles multiples et les environnements sans serveur
- Configurer les opérations : journaux, sondes de santé, comportement en cas de panne, rotation des secrets et mises à jour. Référence pour le moment où vous configurez la surveillance et les runbooks
- Examiner la posture de sécurité : où les données circulent, le modèle de menace et les réponses de conformité. Référence pour un examen de sécurité
Si une connexion ou un démarrage échoue en cours de route, allez directement à Dépannage, qui est indexé sur l'erreur que vous voyez.
Configuration du fournisseur d'identité
Enregistrez une application web OAuth/OpenID Connect (OIDC) confidentielle auprès d'un seul URI de redirection, https://<gateway>/oauth/callback, et assignez-la aux utilisateurs ou groupes qui doivent avoir accès à la passerelle. La passerelle s'authentifie auprès de l'IdP avec le secret client de l'enregistrement, ou avec un certificat que vous téléversez dans l'enregistrement si votre IdP utilise plutôt des identifiants par certificat.
Tout IdP conforme à OIDC fonctionne : Okta, Microsoft Entra ID, Google Workspace, Keycloak, Dex, PingFederate et autres. L'IdP doit répondre à trois exigences :
- Servir
/.well-known/openid-configuration, via HTTPS en production ; la passerelle accepte un émetteurhttp://, et un émetteur de bouclage local nécessite en outreCLAUDE_GATEWAY_ALLOW_LOOPBACK=1 - Supporter le flux de code d'autorisation. PKCE (Proof Key for Code Exchange) est activé par défaut ; désactivez-le avec
oidc.use_pkce: falsepour les IdP qui ne le supportent pas - Retourner
emailet optionnellementgroupsdans l'id_token, ou les servir à partir du point de terminaison userinfo avecoidc.userinfo_fallback: true
Pour l'infrastructure à clé publique privée, définissez oidc.ca_cert_pem.
Quelques fournisseurs gèrent les revendications d'email et de groupe différemment :
- Okta : le serveur d'autorisation de l'organisation à
https://example.okta.comretourne un id_token mince qui ometemailetgroups, donc définissezoidc.userinfo_fallback: truechaque fois que vous l'utilisez commeissuer. Un serveur d'autorisation personnalisé tel quehttps://example.okta.com/oauth2/defaultqui inclutemailet optionnellementgroupsdans l'id_token les émet directement et n'a besoin d'aucun fallback. Okta émetgroupsuniquement lorsque la portéegroupsest demandée dansoidc.scopeset que le filtre de revendication de groupes de l'application le permet ;userinfo_fallbackne peut pas remplir une revendication pour laquelle l'IdP n'a pas été interrogé. - Microsoft Entra ID :
issuer=https://login.microsoftonline.com/<tenant-id>/v2.0. Entra émet des ID d'objet de groupe plutôt que des noms, donc utilisez les GUID dansmanaged.policies.match.groups, ou utilisez les rôles d'application pour des noms lisibles par l'homme. Si votre locataire émet des rôles sousrolesau lieu degroups, définissezoidc.groups_claim: roles. - Google Workspace :
issuer=https://accounts.google.com. L'id_token de Google ne porte pas de groupes. Pour utiliserallowed_groupsbasé sur les groupes oumanaged.policiesavec Google comme IdP, configurezoidc.google_groups, qui recherche les groupes de chaque utilisateur via l'API Directory du SDK Admin en utilisant un compte de service avec délégation au niveau du domaine. Sans cela, utilisezoidc.allowed_email_domainspour le contrôle d'accès à l'adhésion etmanaged.policies.match.email_domainpour l'attribution de politique. Google ignore également la portée standardoffline_access. Pour les jetons d'actualisation, définissezoidc.scopes: [openid, profile, email]etoidc.extra_auth_params: { access_type: offline, prompt: consent }.
[!WARNING]
Les jetons d'actualisation permettent à la passerelle de renouveler la session d'un développeur silencieusement, sans renvoyer le développeur au navigateur. Ils pilotent également le déprovisionnement, car lorsque l'IdP désactive un utilisateur, l'actualisation suivante échoue et la session se termine dans
ttl_hours. La passerelle demandeoffline_accesspar défaut pour obtenir un jeton d'actualisation. Si votre IdP nécessite un consentement explicite pour l'accès hors ligne, configurez le client OAuth pour l'autoriser.Si votre IdP ne peut pas du tout émettre de jetons d'actualisation, la passerelle fonctionne toujours, mais il n'y a pas de renouvellement silencieux, donc les développeurs réexécutent la connexion au navigateur lorsque leur session expire. Pour éviter que cela ne se produise toutes les heures, augmentez
session.ttl_hoursà8ou12. Le compromis est la latence de déprovisionnement, car sans jetons d'actualisation un utilisateur désactivé conserve l'accès jusqu'à l'expiration du TTL plus long.
Déploiement
La passerelle est un seul binaire Linux sans état qui se coordonne via Postgres, donc déployez-la comme vous déployez tout autre service sans état dans votre environnement. Gardez-la à l'intérieur de votre réseau, où vos développeurs peuvent la joindre via HTTPS et où elle peut joindre votre IdP, et traitez-la comme tout service détenant des identifiants de production.
Quelques décisions façonnent le déploiement au-delà de l'endroit où il s'exécute :
- Coûts : pas de licence séparée ou de frais par siège. La passerelle fait partie du binaire
claude, donc vous payez l'inférence via votre engagement existant, plus le calcul qu'elle exécute. - Contournement : la passerelle n'impose pas que la seule route vers un modèle passe par elle. Un développeur avec sa propre credential peut toujours appeler le fournisseur directement, donc fermer ce chemin est une décision de politique réseau, par exemple bloquer la sortie vers
api.anthropic.comsauf depuis la passerelle. Bloquer cette sortie casse également la vérification de sécurité du domaine WebFetch, qui appelleapi.anthropic.comdepuis la machine de chaque développeur. DéfinissezskipWebFetchPreflight: truedans la politique gérée pour la désactiver. - Passerelles multiples : chaque est un déploiement séparé avec sa propre configuration, et le CLI stocke la confiance et les credentials par nom d'hôte de passerelle, donc les équipes peuvent utiliser différentes passerelles sans conflit. Pour servir plusieurs émetteurs OIDC, exécutez des instances séparées.
- Sans serveur : Cloud Run fonctionne si vous définissez
min-instances: 1pour éviter la découverte OIDC à froid. Lambda et Cloud Functions ne fonctionnent pas, car la passerelle est un serveur HTTP de longue durée.
Chaque topologie de production ici place un proxy L7, tel qu'une Ingress, le front-end de Cloud Run ou un ALB, devant les répliques HTTP simples. Définissez listen.trusted_proxies sur les plages sources du proxy afin que la passerelle lise les adresses IP des clients à partir de X-Forwarded-For. La passerelle honore l'en-tête uniquement lorsque le pair TCP est de confiance. Les exemples travaillés Google Cloud et AWS ont des valeurs concrètes par topologie. Sans proxies de confiance, chaque demande semble provenir de l'adresse IP du proxy, ce qui réduit les limites de débit par IP en un seul compartiment partagé et enregistre l'adresse IP du proxy dans les événements d'audit.
Ne redirigez pas les demandes vers les points de terminaison d'autorisation d'appareil et de jeton de la passerelle, par exemple avec une réécriture HTTP-vers-HTTPS ou de canonicalisation d'hôte à l'entrée. Claude Code ne suit pas les redirections sur ces demandes, donc une règle d'entrée qui les redirige casse la connexion et l'actualisation des jetons.
Donnez au proxy un délai d'inactivité plus long que l'intervalle de maintien de la connexion de la passerelle, qui dépend de l'amont :
- Sur chaque amont sauf
provider: anthropic, la passerelle écrit unpingSSE une fois qu'un flux a été silencieux pendant environ 15 secondes. - Sur
provider: anthropic, la passerelle transmet la réponse inchangée, y compris les propres pings de l'API Anthropic.
Une valeur par défaut telle que les 60 secondes de l'ALB est suffisante pour garder un flux silencieux ouvert. L'exemple travaillé AWS l'augmente à une heure de toute façon, et sa ligne de dépannage couvre les passerelles antérieures à v2.1.229, qui n'envoyaient rien pendant les périodes silencieuses sur les amonts qui reçoivent maintenant des pings.
Choisir une adresse pour la passerelle
Claude Code accepte l'adresse d'une passerelle de l'une de deux manières :
- Adresse privée : placez la passerelle derrière un équilibreur de charge interne ou un VPN, avec un nom d'hôte qui se résout uniquement en adresses privées, telles que RFC 1918 ou CGNAT
100.64.0.0/10. Les machines des utilisateurs peuvent avoir n'importe quelle adresse. Le prérequis de réseau privé liste les plages acceptées. - Bloc déclaré : si votre réseau interne utilise un espace IPv4 public que possède votre organisation, listez le bloc dans le paramètre géré
gatewayInternalNetworks. La passerelle et la machine de l'utilisateur doivent toutes deux se trouver dans ce bloc. Consultez Autoriser une passerelle sur un espace d'adressage public que vous possédez.
Si aucun bloc unique ne contient les deux, attribuez plutôt une adresse privée à la passerelle.
Image de conteneur
Créez votre propre image autour du binaire claude natif de la version standard de Claude Code :
- Téléchargez la version Linux pour l'architecture de votre image à partir d'une version épinglée ; consultez Installer une version spécifique pour l'URL de téléchargement.
- Vérifiez-la par rapport au
manifest.jsonsigné GPG de la version comme décrit dans Intégrité binaire et signature de code. - Copiez-la dans le contexte de construction.
Miroitez la version dans votre registre interne si vos constructions ne peuvent pas atteindre l'hôte de version, et épinglez la version que votre flotte exécute.
Au-delà du binaire, l'image a besoin de :
- Une image basée sur glibc : la seule dépendance dynamique de la version glibc est les bibliothèques glibc. Les images basées sur Musl ont besoin de la version
linux-x64-musloulinux-arm64-muslplus des packages supplémentaires ; consultez Configuration Alpine Linux. - Un répertoire d'état inscriptible : la passerelle s'exécute en tant qu'utilisateur quelconque, mais les images minimales n'ont pas de répertoire personnel inscriptible. Définissez
CLAUDE_CONFIG_DIRsur un chemin inscriptible tel que/tmp/.claude. - La commande du conteneur :
claude gateway --config /etc/claude/gateway.yaml, avec le fichier de configuration monté en lecture seule et les secrets fournis en tant que variables d'environnement ; la passerelle écoute surlisten.port, par défaut8080.
Kubernetes
Exécutez la passerelle en tant que Deployment, comme tout service sans état :
- Montez la configuration à partir d'une ConfigMap et les secrets à partir d'un Secret ; référencez les secrets dans le YAML via
${file:/path/to/secret}ou en tant que variables d'environnement - Terminez TLS à l'Ingress et définissez
listen.public_urlsur le nom d'hôte de l'Ingress - Pointez la sonde de disponibilité sur
GET /readyzet la sonde de vivacité surGET /healthz
Pour un exemple travaillé complet sur AWS, couvrant ECS Fargate ou EKS, Amazon RDS et AWS Secrets Manager, consultez Déployer sur AWS.
Préférez l'identité de charge de travail de la plateforme aux clés statiques ; la référence upstreams a des détails de configuration par plateforme. Pour un appairage inter-cloud, tel qu'un amont Bedrock sur GKE, définissez des credentials explicites dans le bloc auth de l'amont à la place.
Cloud Run
Configurez le service comme suit :
- Laissez
listen.portà sa valeur par défaut de8080, qui correspond auPORTpar défaut de Cloud Run, ou définissezport: ${PORT} - Définissez
public_urlsur l'origine accessible de l'extérieur. Pour la production, c'est normalement le nom d'hôte d'un équilibreur de charge interne, car/loginrejette les adresses publiques et l'URL*.run.appse résout en une, donc l'URL Cloud Run seule fonctionne uniquement pour un test de fuméecurlou navigateur. L'exception est un réseau où*.run.appse résout en privé via Private Service Connect et une zone privée Cloud DNS ; dans cette topologie l'URL Cloud Run est unpublic_urlvalide. L'exemple travaillé Google Cloud couvre les deux. - Montez la configuration en tant que volume secret
- Définissez
min-instances: 1pour éviter une découverte OIDC à froid à la première demande
Pour un exemple travaillé complet sur Google Cloud, couvrant Cloud Run ou GKE, Cloud SQL et Secret Manager, consultez Déployer sur Google Cloud.
Envoyer l'URL de la passerelle aux machines des développeurs
Une fois que la passerelle est en service, envoyez forceLoginMethod, forceLoginGatewayUrl et parentSettingsBehavior: "merge" à la machine de chaque développeur via les paramètres gérés, via MDM ou en écrivant directement le fichier managed-settings.json par système d'exploitation.
Une fois que vous déployez les clés, Claude Code cesse d'utiliser une clé API restante ou une connexion claude.ai sur la machine, donc planifiez l'envoi avec vos instructions de connexion. La politique de l'administrateur nécessite une connexion à la passerelle Cloud décrit les messages que les développeurs voient.
Consultez où chaque mécanisme stocke la politique pour les chemins de fichiers, et Paramètres gérés côté client pour l'équivalent bootstrapUrl de Claude Desktop.
Déploiements à grande échelle
La connexion est limitée en débit par adresse IP client, et les valeurs par défaut conviennent à une petite équipe. Chaque adresse obtient 30 démarrages de connexion et 10 soumissions de code toutes les 10 minutes. Un déploiement pour des milliers de développeurs peut atteindre ces limites le premier matin, pour l'une de deux raisons :
- La passerelle ne peut pas voir au-delà de votre équilibreur de charge. Sans
listen.trusted_proxies, chaque développeur semble provenir de l'adresse de l'équilibreur de charge et partage une limite. Définissez-le avant toute autre chose. La passerelle enregistre un avertissement la première fois qu'elle ignore un en-têteX-Forwarded-For. - De nombreux développeurs partagent quelques adresses de sortie NAT ou VPN. Ils partagent les limites de ces adresses même lorsque
trusted_proxiesest correct. Augmentezrate_limitspour l'adapter.
Pour dimensionner max, divisez les développeurs par les adresses de sortie qu'ils partagent. Estimez combien d'entre eux se connectent dans une période window_seconds, qui est 10 minutes par défaut. Puis doublez-le pour couvrir les tentatives et les développeurs qui se connectent à la fois à Claude Code et Claude Desktop.
Par exemple, 10 000 développeurs derrière 4 adresses de sortie se connectent uniformément sur une heure. C'est 2 500 développeurs par adresse et environ 420 d'entre eux dans chaque 10 minutes, que vous doublez et arrondissez à 1 000. L'exemple ci-dessous définit les deux limites à 1 000 :
rate_limits:
device_authorization: { max: 1000, window_seconds: 600 }
device_verify: { max: 1000, window_seconds: 600 }
device_verify est ce qui empêche quelqu'un de deviner le code de connexion d'un autre développeur, donc augmentez-le uniquement autant que votre estimation le nécessite. Même à ces limites, un code est 8 caractères d'un alphabet de 20 caractères et expire après 10 minutes, donc deviner reste impraticable ; consultez Résistance à la force brute du code utilisateur.
Lorsque votre IdP émet des jetons d'actualisation, Claude Code renouvelle les sessions silencieusement, donc vous pouvez remettre la limite après le déploiement. Sans jetons d'actualisation, les développeurs se connectent à nouveau tous les session.ttl_hours. Dimensionnez les deux limites pour ce débit régulier aussi et laissez-les augmentées.
Lorsqu'une limite est atteinte, Claude Code v2.1.274 ou ultérieur affiche The gateway is limiting sign-in attempts right now. Une passerelle sur v2.1.274 ou ultérieur affiche Too many attempts came from your network address sur la page de vérification, avec les paramètres à vérifier. Elle écrit également une ligne de journal sign-in refused qui nomme le paramètre à modifier.
Opérations
Une fois que la passerelle traite le trafic, l'exploitation au quotidien consiste à lire ses journaux, à sonder sa santé et à faire tourner ses secrets selon votre calendrier. Les sous-sections couvrent chacun, plus ce que Postgres détient et comment les mises à jour et les restaurations se comportent.
Journaux
La passerelle écrit deux flux sur stderr, tous deux JSON-friendly :
-
Événements d'audit : JSON sur une seule ligne par événement pertinent pour la sécurité. Canalisez stderr vers votre agrégateur de journaux.
Les événements émis incluent
config.load,session.mint,session.refresh,device.authorize,device.verify,device.callback,auth.denied,access.denied,access.public_client,inference,managed.serve,desktop_bootstrap.serve,desktop_bootstrap.denied,spend.blocked,admin.denied,admin.limit.upsertetadmin.limit.delete. Les champs varient selon l'événement :- Les événements de mint et refresh réussis portent
sub,email,client_ipet le résultat auth.deniedetaccess.deniedportent la raison et l'adresse IP du client, plus le chemin de la demande pourauth.denied, car aucune identité utilisateur n'existe à ces refus. Deux raisonsaccess.deniedchangent ce que l'événement porte :xff_unparseable: l'événement porte également l'entréeX-Forwarded-Forqui n'a pas pu être lueclient_ip_unknown: l'événement ne porte pas d'adresse IP client, car la connexion n'avait pas d'adresse de pair tandis qu'une listeaccess_controlétait définie
access.public_clientporte l'adresse IP du client de la première demande par processus à arriver d'une adresse publique tandis queaccess_control.allow_cidrsest vide. La passerelle sert la demande comme d'habitude ; l'événement signale que la passerelle peut être accessible depuis l'internet public. Consultez la référenceaccess_controlpour ce qui compte comme public et pour la liste d'autorisation recommandée.inferenceenregistre quel amont a servi la demande et le statut de la réponsedesktop_bootstrap.deniedenregistre une récupération de bootstrap Claude Desktop rejetée avec la raison (not_configured,policy_not_opted_inouno_policy_matched) et l'identité de l'utilisateuradmin.deniedenregistre une tentative d'authentification d'API admin rejetée avec l'adresse IP du client, la méthode, le chemin et une raison, sans le matériel de clé présenté :invalid_keyquand unex-api-keya été présentée mais ne correspondait à aucune clé configurée,bearer_rejectedquand seul un en-têteAuthorizationa été présenté et il n'a pas vérifié comme une session de passerelle dansadmin.admin_groups, ouno_credentialsquand aucun en-tête n'a été présenté
- Les événements de mint et refresh réussis portent
-
Journaux opérationnels : lignes lisibles par l'homme avec préfixe
[gateway]pour le démarrage, les avertissements et les erreurs en amont. La variable d'environnementCLAUDE_GATEWAY_LOG_LEVELcontrôle la verbosité et acceptedebug,info,warnouerror, avecinfopar défaut. Àdebug, chaque connexion et actualisation enregistre également les noms, pas les valeurs, des revendications dans l'id_token, plus les noms des revendications userinfo quanduserinfo_fallbacken a fourni, afin que vous puissiez diagnostiquer les paramètresemail_claimetgroups_claimsans enregistrer les PII. Cela n'affecte pas les événements d'audit, qui sont toujours émis.
Santé
La passerelle sert GET /healthz comme sonde de vivacité et GET /readyz comme sonde de disponibilité. /readyz vérifie que le magasin est accessible. Si vous définissez store.readiness_grace_seconds, /readyz continue de signaler prêt pendant jusqu'à ce nombre de secondes après que le magasin cesse de répondre.
Les deux points de terminaison sont exempts de access_control.allow_cidrs, donc les sondes continuent de fonctionner sur un écouteur verrouillé.
Le document de découverte OAuth à /.well-known/oauth-authorization-server retourne également 200 uniquement après le chargement de la configuration, la découverte OIDC, la construction du client en amont et la migration Postgres réussissent, donc il double comme vérification de démarrage de bout en bout.
Demandes en amont concurrentes
Par défaut, chaque réplique de passerelle envoie au maximum 256 demandes en amont en même temps. Une réponse en streaming compte par rapport à la limite jusqu'à ce que le flux se termine.
Une demande qui arrive tandis qu'une réplique est à la limite attend à l'intérieur de la passerelle pour un créneau libre. Le développeur voit une réponse qui est lente à démarrer ou semble se bloquer. Sur une amont provider: anthropic, une demande qui attend plus longtemps que timeouts.upstream_ttfb_ms abandonne cet amont, et échoue avec un 502 quand aucun amont ultérieur ne la sert.
La ligne de journal de démarrage qui contient upstream requests: affiche la limite en vigueur. Tandis qu'une réplique a plus de demandes ouvertes que la limite, elle enregistre également un avertissement qui contient client requests are open, au maximum une fois par minute.
Pour servir plus de demandes à la fois, vous avez deux options :
- Ajouter des répliques.
- Augmenter la limite sur chaque réplique. Définissez la variable d'environnement
BUN_CONFIG_MAX_HTTP_REQUESTSsur le conteneur de passerelle à un nombre entier de 1 à 65535, puis redémarrez le conteneur.
Une réplique remplit sa limite à un taux de demande d'environ la limite divisée par le nombre moyen de secondes qu'une demande reste ouverte. Par exemple, si les demandes restent ouvertes pendant 10 secondes en moyenne, une réplique à la limite par défaut de 256 la remplit à environ 26 demandes par seconde.
Si vous mettez à l'échelle automatiquement sur CPU, une réplique à la limite met en file d'attente les demandes sans déclencher une montée en charge, donc définissez la cible en dessous du niveau CPU que vos répliques affichent quand elles enregistrent l'avertissement client requests are open.
[!WARNING]
Chaque demande ouverte détient la mémoire dans le processus de passerelle tandis qu'elle diffuse en continu et tandis qu'elle attend un créneau. Si vous gardez la limite à 256, la mémoire sur une réplique surchargée croît toujours, car les demandes en attente conservent leurs corps de demande. Dimensionnez la mémoire du conteneur pour le nombre de demandes ouvertes au pic, et surveillez la mémoire quand vous changez la limite. Une réplique qui manque de mémoire est tuée et abandonne chaque flux qu'elle détient.
Maintenir API_TIMEOUT_MS au-dessus du délai de premier octet de la passerelle
Si vous abaissez API_TIMEOUT_MS pour réessayer plus tôt une requête restée sans réponse, maintenez-le au-dessus du temps que met la passerelle à envoyer les premiers octets d'une réponse en streaming. Une requête qui attend plus longtemps expire, de même que chaque nouvelle tentative qui attend aussi longtemps, jusqu'à ce que le tour se termine avec Request timed out, sauf si le délai maximal de premier octet y met fin.
provider: anthropic: définissezAPI_TIMEOUT_MSau-dessus du temps maximal que met votre amont à envoyer son premier événement.- Tous les autres amonts : définissez-le à plus de 20 secondes au-dessus du temps maximal que met votre amont à renvoyer les en-têtes de réponse. La passerelle envoie son premier
pingkeepalive environ 15 secondes après ces en-têtes, sauf si le premier événement de l'amont arrive plus tôt. Une passerelle antérieure à v2.1.229 n'envoie aucun ping, appliquez donc la règleprovider: anthropicdans ce cas.
En plus de ce temps, prévoyez toute attente d'un créneau libre et l'attente sur un amont en panne avant le basculement. Maintenez également la valeur au-dessus de la plus longue requête sans streaming.
Réessayer plus tôt une requête restée sans réponse grâce au délai maximal de premier octet
Pour que Claude Code réessaie plus tôt une requête en streaming restée sans réponse, donnez-lui un délai maximal de premier octet en définissant CLAUDE_STREAM_FIRST_BYTE_TIMEOUT_MS sur les machines de vos développeurs. Ce délai limite le temps pendant lequel la première tentative attend les en-têtes de réponse. Sans lui, cette tentative peut attendre de 5 à 6 minutes. Nécessite Claude Code v2.1.307 ou ultérieur sur la machine du développeur.
Définissez la variable sur un nombre entier positif de millisecondes, dans le bloc env d'une politique de passerelle ou dans le shell d'un développeur. Maintenez la valeur au-dessus du plus long délai de premier octet de votre passerelle, sinon Claude Code peut interrompre et renvoyer des requêtes saines dont les en-têtes mettent plus de temps à arriver. Cet exemple définit 60 secondes dans le shell d'un développeur :
export CLAUDE_STREAM_FIRST_BYTE_TIMEOUT_MS=60000
Un renvoi resté sans réponse peut attendre de 5 à 6 minutes, jusqu'à ce que le délai d'inactivité du corps y mette fin et que Claude Code le réessaie dans la limite du budget de nouvelles tentatives. Si vous avez abaissé API_TIMEOUT_MS uniquement pour réessayer plus tôt, supprimez cette valeur, sinon un seul renvoi resté sans réponse peut terminer le tour avec No response from API.
Pour confirmer que le délai s'est déclenché, demandez à un développeur de démarrer Claude Code avec la journalisation de débogage, puis recherchez [first-byte] no response headers dans le log.
Comportement en cas de panne
Si Postgres tombe en panne, la passerelle elle-même continue de servir les développeurs connectés et les nouvelles connexions échouent. Que les développeurs continuent réellement à travailler dépend de la façon dont votre orchestrateur gère la disponibilité :
- Sessions existantes : les jetons porteurs valident localement avec le secret JWT, les actualisations de session ne touchent pas le magasin, et le processus de passerelle peut toujours servir l'inférence
- Nouvelles connexions : échouent jusqu'à la récupération de Postgres, car le flux d'appareil et ses compteurs de limite de débit vivent dans Postgres
- Application des limites de dépenses : échoue ouvert par défaut pendant la panne, donc l'inférence continue de circuler ; basculez-la pour échouer fermé si vous préférez bloquer plutôt que de fonctionner sans compteur
- Disponibilité : par défaut
/readyzsignale non-prêt dès que Postgres est inaccessible, donc chaque réplique échoue sa vérification de disponibilité à la fois. Là où le trafic ne atteint que les répliques qui passent la vérification, tout le trafic, y compris l'inférence que la passerelle pourrait toujours servir, échoue jusqu'à la récupération de Postgres. La sonde de vivacité sur/healthzcontinue de passer tout au long.
Si votre IdP tombe en panne, les sessions existantes fonctionnent jusqu'à ttl_hours et les nouvelles connexions échouent. Une actualisation de session obtient une réponse de réessai et se termine une fois que l'IdP est de retour. Définissez un ttl_hours plus long si votre IdP a des fenêtres de maintenance fréquentes.
Période de grâce de disponibilité
Pour garder les développeurs connectés qui travaillent à travers une courte panne de Postgres telle qu'un basculement de base de données, définissez store.readiness_grace_seconds à plus long que le basculement ne prend, par exemple 300. Avec les limites de dépenses activées et le comportement par défaut fail-open, les demandes à travers une réplique qui reste prête sont sans compteur jusqu'à la récupération de Postgres, donc gardez la valeur aussi basse que couvre votre basculement. Si vous définissez enforcement.fail_closed_on_error: true, la passerelle refuse l'inférence des développeurs connectés avec le message 429 spend limit unavailable jusqu'à la récupération de Postgres, même tandis que les répliques passent toujours leur vérification de disponibilité.
Le paramètre nécessite Claude Code v2.1.282 ou ultérieur sur le serveur de passerelle. Une passerelle antérieure refuse de démarrer quand elle trouve la clé, donc mettez à niveau chaque réplique avant de l'ajouter. Mises à jour couvre la restauration.
Si vous pointez la sonde de disponibilité sur /healthz à la place, les répliques passent également à travers une panne, mais /healthz ne signale jamais non-prêt, donc une réplique dont la connexion Postgres ne se rétablit pas continue de passer aussi.
Rotation du secret JWT
Faites tourner le secret de signature en étapes afin que les sessions existantes restent valides :
- Générez un nouveau secret. Ajoutez-le au début du tableau
session.jwt_secret. - Déployez le déploiement. Les nouveaux jetons signent avec le nouveau secret ; les anciens jetons valident toujours.
- Après
ttl_hoursplus une marge, supprimez l'ancien secret et déployez à nouveau.
La rotation est également le seul moyen de forcer les sessions à sortir avant leur expiration : les jetons porteurs valident localement par rapport au secret JWT, donc il n'y a pas de révocation par session. Remplacer le secret directement, sans conserver l'ancien dans le tableau, invalide chaque session en attente à la fois. Pour le déprovisionnement individuel, déprovisionner l'utilisateur dans votre IdP ; sa session se termine dans ttl_hours.
Postgres
La passerelle stocke son état dans une base de données PostgreSQL :
- Base de données : PostgreSQL lui-même, auto-hébergé ou managé, en version minimale ou ultérieure. Les bases de données qui implémentent uniquement le protocole Postgres, comme les bases de données SQL distribuées, ne sont pas prises en charge.
- Adresse :
store.postgres_urlaccepte un seul hôte. Si la base de données comporte plusieurs nœuds, utilisez l'adresse placée devant eux, comme l'endpoint de votre service managé, un équilibreur de charge ou une IP virtuelle. Définissez une période de grâce de disponibilité plus longue que la durée d'un basculement.
La passerelle détient cinq tables de données plus une table _migrations, toutes créées par ses migrations au démarrage :
| Table | Contenu | Rétention |
|---|---|---|
kv |
Subventions d'appareil (TTL de 10 minutes) et compteurs de limite de débit | TTL par ligne |
spend |
Compteurs de dépenses période-à-date par principal, en cents | admin.spend_retention_months, par défaut 13 |
spend_limits |
Plafonds de dépenses configurés | Jusqu'à suppression via l'API |
admin_audit |
Piste de mutation de l'API admin | admin.audit_retention_days, par défaut 365 |
principal_emails |
Email, nom d'affichage et groupes IdP de chaque principal vus en dernier. Contient des PII. | admin.identity_retention_days depuis la dernière activité, par défaut 90 |
Une boucle de 30 secondes expire les lignes kv au-delà de leur TTL, et un balayage horaire applique les fenêtres de rétention sur les tables de dépenses, donc rien ne croît sans limite. Sans limites de dépenses configurées, seul kv est écrit. La passerelle applique ses propres migrations de schéma au démarrage et à chaque mise à jour, donc son rôle de base de données a besoin de droits pour créer et modifier les tables. Pointez-le vers une base de données ou un schéma dédié à la passerelle pour garder cette autorisation étroite.
Avec les limites de dépenses en usage, une base de données perdue signifie le suivi des dépenses et les plafonds perdus, pas seulement les re-connexions des développeurs, donc exécutez des sauvegardes régulières. Pour effacer immédiatement un développeur parti plutôt que d'attendre la rétention, exécutez DELETE FROM principal_emails WHERE principal = '<sub>' directement ; cela supprime la seule table contenant son email, son nom et ses groupes. Les lignes spend et admin_audit ne référencent que le sub OIDC pseudonyme.
Dimensionner le pool de connexions
Chaque réplique ouvre jusqu'à store.max_connections connexions Postgres, cinq par défaut. Maintenez répliques × store.max_connections inférieur ou égal aux connexions dont la base de données dispose encore pour la passerelle :
- Répliques : comptez le nombre maximal qui s'exécutent simultanément. Partez de votre maximum d'autoscaling, ou de votre nombre de répliques si vous n'utilisez pas l'autoscaling, et ajoutez les répliques supplémentaires qu'une mise à jour progressive démarre avant d'arrêter les anciennes. Sur Amazon ECS avec les paramètres par défaut, et sur Cloud Run, cela peut représenter autant à nouveau.
- Connexions disponibles : prenez le
max_connectionsde la base de données, puis soustrayez ce que la base de données réserve et ce que détiennent les autres clients. PostgreSQL réservesuperuser_reserved_connections, trois par défaut. Un service managé peut en réserver davantage, consultez donc sa documentation.
Par exemple, prenez un maximum d'autoscaling de six, des mises à jour progressives qui démarrent au plus deux répliques supplémentaires et le pool par défaut de cinq. Cela nécessite (6 + 2) × 5 = 40 connexions. Une base de données avec un max_connections de 50 et deux connexions détenues par d'autres clients en a 50 − 3 − 2 = 45 disponibles, donc le total tient.
Si votre total ne tient pas, modifiez l'un de ces éléments :
- La base de données : augmentez son
max_connections - Les répliques : exécutez-en moins, ou faites en sorte que votre orchestrateur démarre moins de répliques supplémentaires lors d'une mise à jour progressive
- Le pool : abaissez
store.max_connections, mais avec les limites de dépenses activées, gardez-le suffisamment grand pour la charge de chaque réplique. Sinon, les vérifications de dépenses peuvent expirer en attendant une connexion, et la passerelle journalisespend check failed: spend precheck timed out.
Mises à jour
Les répliques sont sans état, donc un redémarrage roulant ne perd aucun état de passerelle. La passerelle exécute les migrations de schéma au démarrage, ce qui signifie que le déploiement du nouveau binaire auto-migre la base de données. Les répliques concurrentes se sérialisent sur un verrou consultatif Postgres, donc seule une applique chaque migration.
Quand votre orchestrateur arrête une réplique avec SIGTERM, comme dans un redémarrage roulant ou une réduction d'échelle, la passerelle arrête d'accepter les nouvelles connexions et laisse les demandes et les flux déjà en vol se terminer avant de quitter. Elle attend jusqu'à 25 secondes, appelée la fenêtre de drainage, puis ferme tout ce qui est toujours ouvert. Un SIGINT, tel que Ctrl+C dans un terminal, démarre le même drainage, et un deuxième signal pendant le drainage ferme les demandes ouvertes et quitte immédiatement. Le drainage nécessite la passerelle v2.1.274 ou ultérieure.
Les générations longues peuvent diffuser en continu pendant des minutes. Sur Kubernetes et Amazon ECS, augmentez les deux ensemble pour donner à ces flux plus de temps :
- La fenêtre de drainage : définissez la variable d'environnement
CLAUDE_GATEWAY_DRAIN_TIMEOUT_MSsur le conteneur de passerelle à un nombre entier positif de millisecondes, tel que120000. La passerelle ignore une valeur sous toute autre forme, telle que120s, et conserve la valeur par défaut de 25 secondes - La période de grâce de votre orchestrateur :
terminationGracePeriodSecondssur Kubernetes, oustopTimeoutsur Amazon ECS
La période de grâce par défaut est de 30 secondes sur les deux plates-formes. Gardez-la au moins 5 secondes plus longue que la fenêtre de drainage, ou l'orchestrateur tue la passerelle avant la fin du drainage. Sur Kubernetes, ajoutez également la durée de tout crochet preStop, car la période de grâce commence à compter avant que le crochet ne s'exécute plutôt que quand la passerelle reçoit SIGTERM.
Votre plate-forme peut également limiter la durée du drainage :
- Amazon ECS sur Fargate :
stopTimeoutpermet au maximum 120 secondes - Cloud Run : arrête une instance 10 secondes après
SIGTERM, donc les flux ouverts obtiennent au maximum 10 secondes là, quelle que soit la fenêtre de drainage
Quand la fenêtre de drainage se termine avec des demandes toujours ouvertes, la passerelle enregistre un avertissement qui contient drain window over after, compte les demandes qu'elle a coupées, et nomme les deux paramètres à augmenter.
Les migrations sont en ajout seul, donc revenir à un binaire antérieur qui connaît moins de migrations est sûr ; il ignore les lignes supplémentaires. La restauration re-valide également le YAML par rapport au schéma du binaire plus ancien, donc une configuration qui a adopté une clé introduite par la version plus récente échoue au démarrage sur l'ancienne. Supprimez la nouvelle clé avant de revenir.
Parce que vous épinglez la version de la passerelle dans votre propre image, les correctifs dans les nouvelles versions de Claude Code, y compris les correctifs de sécurité, atteignent votre déploiement uniquement lorsque vous mettez à jour l'épingle et redéployez. Incluez la passerelle dans le même calendrier de correction que vous utilisez pour les autres services qui détiennent des credentials de production.
Sécurité
Cette section répond aux questions qu'un examen de sécurité pose : quelles données circulent à travers la passerelle et où elles vont, quelles attaques la conception défend, et quelles réponses appartiennent à un questionnaire de conformité.
Flux de données
| Données | Chemin | Envoyé à Anthropic par la passerelle |
|---|---|---|
| Inférence (invites, complétions) | CLI → passerelle → votre amont | Uniquement si l'API Anthropic est un amont configuré |
| Télémétrie (métriques OTLP, plus journaux et traces opt-in) | CLI → passerelle → votre collecteur | Jamais |
| Identité (email, groupes, sub) | IdP → passerelle → CLI ; le CLI l'estampille sur les exports OTLP. Si vous activez forward_user_identity, la passerelle envoie également l'email du développeur et le sujet IdP en tant qu'en-têtes à votre proxy |
Jamais |
| Paramètres gérés | Votre YAML de passerelle → CLI | Jamais |
| Journal d'audit | Stderr de passerelle → votre agrégateur | Jamais |
Résumé du modèle de menace
La passerelle se trouve à l'intérieur de votre périmètre réseau, mais les ordinateurs portables des développeurs individuels ne sont pas traités comme de confiance. La conception en tient compte de trois façons :
-
Les développeurs détiennent des JWT de courte durée au lieu de clés en amont brutes. La jambe CLI-à-passerelle utilise la subvention d'appareil RFC 8628, et l'échange de code d'autorisation de la passerelle avec l'IdP exécute PKCE dans la configuration par défaut, donc un code d'autorisation IdP intercepté est inutile.
-
La page de vérification d'appareil applique POST de même origine et une limite de débit par IP par RFC 8628 §5.1. Consultez Résistance à la force brute du code utilisateur.
-
Les demandes de la passerelle à votre IdP, vos collecteurs OTLP, et les amonts
provider: anthropicpassent par une protection contre la falsification de demande côté serveur (SSRF) qui résout DNS, bloque les adresses de lien local et de métadonnées cloud plus la bouclage par défaut, et épingle la connexion à l'IP résolue, donc les URL influencées par l'opérateur ne peuvent pas être redirigées vers les points de terminaison de métadonnées cloud. Les plages privées RFC 1918 sont délibérément autorisées, car les IdP et les collecteurs OTLP vivent couramment sur des adresses IP privées. Pour les autres fournisseurs, la passerelle refuse unebase_urlqui nomme l'une de ces adresses ou un nom d'hôte de métadonnées lorsqu'elle charge la config, et le SDK du fournisseur se connecte ensuite sans la vérification DNS.Si vous activez sortie proxy uniquement, cette vérification d'adresse se déplace vers votre proxy avant : la passerelle lui transmet les noms d'hôte et la liste d'autorisation du proxy doit refuser ces destinations.
Définissez
CLAUDE_GATEWAY_ALLOW_LOOPBACK=1dans l'environnement de la passerelle uniquement lorsque quelque chose que la passerelle doit atteindre légitimement vit sur la bouclage, comme un IdP de développement local ou un collecteur OTLP sidecar surlocalhost. La variable assouplit le bloc de bouclage pour chaque URL configurée par l'opérateur et ignore également l'avertissement au démarrage qui vérifie si le pod peut atteindre le point de terminaison de métadonnées cloud, donc préférez donner au collecteur sa propre adresse interne.
Si vous ajoutez vos propres contrôles de sortie, la passerelle doit atteindre le serveur de métadonnées chaque fois qu'elle utilise des credentials de métadonnées d'instance tels que l'identité de charge de travail.
Deux menaces sont hors de portée car c'est votre infrastructure à sécuriser :
- Un hôte de passerelle compromis : l'hôte détient à la fois la credential en amont et distribue les paramètres gérés à chaque développeur connecté, donc le contrôle de la configuration de la passerelle est comparable au contrôle de votre MDM. La boîte de dialogue d'approbation du CLI pour les paramètres capables de shell limite les changements silencieux mais ne remplace pas la sécurité de l'hôte.
- Un fournisseur OIDC malveillant : le fournisseur signe les id_tokens que la passerelle fait confiance, donc il peut affirmer n'importe quelle identité. L'examen et la sécurisation de votre IdP sont votre responsabilité.
Résistance à la force brute du code utilisateur
Le user_code qu'un développeur tape dans la page de vérification /device est 8 caractères tirés d'un alphabet de 20 caractères, ce qui donne 20⁸ ou environ 2,56×10¹⁰ combinaisons, et il expire après 10 minutes.
La passerelle applique des limites de débit par IP sur les points de terminaison de subvention d'appareil, configurables via rate_limits. Augmentez les limites si de nombreux développeurs se connectent à partir d'une seule adresse NAT d'entreprise partagée. Les déploiements à grande échelle montre comment les dimensionner. Les limites s'appliquent uniquement au flux de connexion, pas à l'inférence.
Posture de conformité
- Résidence des données : le plan de données de la passerelle elle-même n'envoie rien à Anthropic sauf si l'API Anthropic est un amont configuré ; lorsqu'elle l'est, votre accord de traitement des données existant s'applique au chemin d'inférence. La télémétrie, l'audit, l'identité et les paramètres vont uniquement aux destinations que vous configurez.
- Trafic du processus hôte : le processus hôte est le CLI Claude Code. La commande
claude gateways'exécute selon les mêmes règles tierces que les déploiements Amazon Bedrock et Google Cloud Agent Platform et n'envoie rien à Anthropic. Avant la v2.1.227, le processus hôte envoyait la télémétrie de démarrage telle que la version du produit et la plateforme, que le paramètreCLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1dans l'environnement du conteneur désactivait. Ces versions envoyaient également une demandeHEADau démarrage, sans corps ni credentials, à/api/hellosurhttps://api.anthropic.com, ou surANTHROPIC_BASE_URLlorsque l'environnement l'a défini, sauf si l'environnement a également défini une variable proxy telle queHTTPS_PROXYou un certificat client mTLS. Elles ignoraient la réponse, donc bloquer cette demande au pare-feu de sortie n'affectait pas la passerelle. - Analytique client : le CLI désactive sa propre analytique d'utilisation et le rapport d'erreurs lorsqu'il est connecté à une passerelle. Avant la première connexion, le CLI envoie toujours les événements de démarrage à Anthropic, y compris sur les machines dont les paramètres gérés forcent la connexion à la passerelle. Pour les désactiver aussi, livrez
DISABLE_TELEMETRYdans les mêmes paramètres gérés côté client qui forcent la connexion à la passerelle. - Rapport d'erreurs : le CLI désactive le rapport d'erreurs chaque fois que ses demandes de modèle vont à n'importe quel point de terminaison autre que l'API première partie d'Anthropic, comme Amazon Bedrock ou un
ANTHROPIC_BASE_URLpersonnalisé. - Machines client : les CLI des développeurs envoient toujours les vérifications de nom d'hôte WebFetch et les vérifications de version à Anthropic sauf si
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1etskipWebFetchPreflight: truesont définis. Les requêtes de marketplace de plugins disposent de leurs propres moyens de désactivation. Consultez utilisation des données. - Évaluations d'enquête : lorsqu'il est connecté à une passerelle, le CLI désactive le téléchargement d'évaluation lié à Anthropic ainsi que les flux d'analytique, donc il n'envoie pas les évaluations à Anthropic.
- Partage de transcription : choisir Oui sur une invite de partage de transcription d'enquête écrit un fichier local sous
~/.claude/feedback-bundles/au lieu de télécharger vers Anthropic. - Mises à jour client : les vérifications de mise à jour sont séparées du trafic de passerelle. Épinglez les versions via votre propre distribution et définissez
DISABLE_UPDATESsi les ordinateurs portables ne doivent pas récupérer les versions.DISABLE_AUTOUPDATERarrête uniquement les mises à jour en arrière-plan tandis queclaude updatefonctionne toujours. - TLS : servez
public_urlvia HTTPS en production, soit à partir du propre écouteur de la passerelle vialisten.tls, soit à partir d'une ingress terminant TLS devant les répliques HTTP simples, aveclisten.public_urldéfini dans les deux cas. La passerelle ne refuse pas HTTP simple. L'IdP doit servir HTTPS en production, et Postgres supporte?sslmode=require. DéfinissezStrict-Transport-Securityà votre ingress. - Divulgation de vulnérabilité : suivez Signaler les problèmes de sécurité
Requêtes de marketplace de plugins
Claude Code récupère les marketplaces de plugins directement depuis la machine de chaque développeur, et non via la passerelle. Exigences d'accès réseau répertorie les hôtes.
La première fois qu'un développeur démarre une session de terminal interactive, Claude Code enregistre la marketplace officielle, claude-plugins-official. Il télécharge le catalogue depuis downloads.claude.ai et, en cas d'échec, le clone depuis github.com. Quelles marketplaces et quels plugins se mettent à jour automatiquement couvre les actualisations ultérieures.
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 n'empêche pas le premier enregistrement. L'un ou l'autre de ces paramètres gérés l'empêche :
- Une liste de marketplaces : une liste d'autorisation
strictKnownMarketplacesqui exclut la marketplace, ou une entréeblockedMarketplacesqui la nomme - Une variable d'environnement :
CLAUDE_CODE_DISABLE_OFFICIAL_MARKETPLACE_AUTOINSTALLdéfinie sur"1"dans le blocenvgéré
Le premier enregistrement peut s'exécuter avant que le développeur se connecte à la passerelle, lorsqu'aucune politique de passerelle n'est encore arrivée. Pour couvrir ce premier démarrage, fournissez votre choix dans les paramètres gérés côté client ainsi que dans le bloc cli ou code de la politique de passerelle.
Dépannage
Pour vos questions et commentaires, utilisez le support Claude Code, ou ouvrez une issue sur le dépôt GitHub de Claude Code. Vous pouvez également contacter l'équipe en charge de votre compte Anthropic. Lorsque vous signalez un problème, incluez :
- Problème de passerelle : la sortie stderr de la passerelle pour la période concernée, votre
gateway.yamlavec les secrets masqués, la version de la passerelle, affichée sur la page d'accueil à/et dans l'en-tête de réponsex-cc-gateway-versionsur/managed/settings, ainsi que ce qui a changé récemment - Problème de connexion : le développeur exécute
claude --debug-file ./claude-debug.txt, reproduit le problème, puis envoie ce fichier ainsi que le log d'audit de la passerelle pour la même période - Problème d'inférence : le modèle demandé, les upstreams configurés et le log d'audit de la passerelle pour la requête, qui indique quel upstream l'a servie et le statut de la réponse
La sortie stderr de la passerelle inclut le flux d'événements d'audit, le log d'audit enregistre les identités des développeurs, et le fichier de débogage enregistre la sortie des hooks et des serveurs MCP depuis la machine du développeur. Relisez et masquez ces éléments avant de les publier dans une issue publique.
| Symptôme | Cause | Solution |
|---|---|---|
La commande /login d'un développeur affiche le sélecteur de compte standard au lieu de l'écran Cloud gateway |
forceLoginMethod ou forceLoginGatewayUrl n'est pas défini dans les paramètres gérés de cette machine |
Déployez le fichier de paramètres gérés sur l'appareil ; /login y lit l'URL de la passerelle |
Les requêtes d'un développeur échouent avec Not signed in to the Cloud gateway — run /login. |
Les paramètres gérés de la machine définissent forceLoginMethod: "gateway" ou forceLoginGatewayUrl, et la session n'a pas de connexion à la passerelle. Une connexion claude.ai résiduelle ne satisfait pas cette exigence. |
Demandez au développeur d'exécuter /login et de terminer la connexion à la passerelle. Voir aussi Administrator policy requires a Cloud gateway sign-in. |
| Claude Desktop signale que sa configuration d'amorçage n'a pas pu être récupérée | /user/bootstrap a renvoyé 404 : la politique correspondant à l'utilisateur ne contient pas de clé desktop, ou aucune politique ne correspond. Le log d'audit de la passerelle enregistre chaque rejet sous la forme desktop_bootstrap.denied avec la raison. |
Ajoutez un bloc desktop à la politique qui correspond à l'utilisateur, ou à la couche de base match: {} ; un desktop: {} vide suffit. Voir Surcouche Claude Desktop. |
Le log d'audit affiche auth.denied avec reason: invalid_token sur /v1/logs ou /v1/metrics |
Vous avez défini otelHeadersHelper dans les paramètres gérés d'une machine. Dans une session Claude Desktop sur cette machine, Claude Code envoie l'en-tête Authorization provenant du helper au relais de télémétrie de la passerelle à la place du jeton de session. Lorsque Claude Desktop embarque une version de Claude Code antérieure à v2.1.307, vous obtenez le même refus si vous définissez un en-tête Authorization dans OTEL_EXPORTER_OTLP_HEADERS ou dans une forme propre à un signal dans ces paramètres. |
Retirez le helper de ces paramètres. Lorsque Claude Desktop embarque une version de Claude Code antérieure à v2.1.307, retirez la variable. |
Le démarrage affiche Gateway login is configured in managed settings, but this Claude Code build does not include Cloud gateway support. |
Le build de Claude Code installé est antérieur à la prise en charge de la passerelle | Demandez au développeur de mettre à jour Claude Code vers une version qui inclut la prise en charge de Cloud gateway |
Le démarrage se termine avec Administrator policy requires a Cloud gateway sign-in on this machine |
L'environnement du développeur définit ANTHROPIC_API_KEY ou ANTHROPIC_AUTH_TOKEN, ses paramètres configurent un apiKeyHelper, ou une clé API issue d'une ancienne connexion à la Claude Console est toujours enregistrée |
Demandez au développeur de corriger chaque cas applicable : supprimer la variable, retirer l'entrée apiKeyHelper, ou exécuter claude auth logout pour supprimer la clé enregistrée. Une session qui sélectionne un fournisseur cloud avec CLAUDE_CODE_USE_* démarre alors sans connexion ; pour toutes les autres sessions, demandez-lui de lancer claude et de se connecter avec /login. Voir aussi Administrator policy requires a Cloud gateway sign-in. |
Le démarrage ou /login signale Claude Code may not be enabled for your organization après un 403 lors du chargement des paramètres gérés |
La passerelle, ou un élément placé devant elle, a répondu 403 à la requête /managed/settings. La route de paramètres de la passerelle elle-même ne répond jamais 403. Ce statut provient des vérifications d'IP access_control ou d'un proxy ou WAF placé devant la passerelle. Le log d'audit enregistre un refus lié à la vérification d'IP sous la forme access.denied avec la raison. Le développeur reste connecté. |
Recherchez access.denied dans le log d'audit au moment de l'échec et corrigez les listes access_control ou le frontal, puis demandez au développeur de relancer claude |
/login dans la CLI : The gateway is limiting sign-in attempts right now, ou Request failed with status code 429 sur les anciennes versions. La page /device peut afficher Too many attempts à des développeurs qui n'ont encore jamais essayé |
La limite de débit de connexion par IP a été atteinte. Soit listen.trusted_proxies ne couvre pas le load balancer, si bien que tous les développeurs partagent son adresse, soit de nombreux développeurs partagent une même adresse de sortie NAT ou VPN. Les événements d'audit avec result: rate_limited affichent la ou les mêmes quelques valeurs client_ip. |
Définissez d'abord listen.trusted_proxies sur les plages source du load balancer, puis augmentez rate_limits si les développeurs partagent encore des adresses. Voir Déploiements à grande échelle. |
/login dans la CLI : Gateway hosts must be on your organization's private network; <host> resolves to the public (or unrecognized) address <ip> |
Le nom d'hôte de la passerelle se résout vers au moins une adresse IP publique. Claude Code vérifie chaque adresse résolue et exige qu'elles soient toutes privées. Une cause fréquente est un nom dual-stack dont une famille se résout vers une adresse publique, y compris les load balancers internes dual-stack d'AWS, qui renvoient des adresses AAAA dans des plages publiques. | Faites en sorte que le nom de la passerelle ne se résolve que vers des adresses privées sur les machines des développeurs. Pour un nom dual-stack, supprimez l'enregistrement de plage publique ou servez un nom DNS distinct, uniquement interne. Voir le prérequis de réseau privé. Si l'adresse fait partie d'un espace public que votre organisation possède et utilise en interne, déclarez ce bloc à la place. |
/login dans la CLI : Gateway login would go through proxy <proxy>, which is not on a private network |
Un HTTPS_PROXY ou HTTP_PROXY s'applique à l'hôte de la passerelle et le nom d'hôte du proxy se résout vers une adresse publique. Un proxy dont l'hôte se résout uniquement vers des adresses privées est autorisé et ne déclenche pas cette erreur |
Ajoutez l'hôte de la passerelle à NO_PROXY sur la machine du développeur pour que la connexion soit directe, ou utilisez un proxy dont le nom d'hôte se résout vers des adresses privées. Le message indique l'entrée NO_PROXY exacte à ajouter |
/login dans la CLI : Claude Code only signs in to <host> from inside its declared network <block> (managed settings), and this machine is connecting from <ip>, outside it |
La passerelle se trouve sur un bloc déclaré dans gatewayInternalNetworks, et la machine du développeur l'a atteinte depuis une adresse extérieure à ce bloc : un pool d'adresses VPN, un segment NAT de conteneur ou de WSL2, ou un réseau qui ne vous appartient pas |
Demandez au développeur d'exécuter /login depuis l'OS hôte sur votre réseau. Si l'adresse affichée fait également partie de l'espace public propre à votre organisation, remplacez l'entrée de la passerelle par un bloc qui couvre les deux, jusqu'à /8 ; une seconde entrée qui chevauche la première est refusée. Si aucun bloc ne couvre les deux, voir Choisir une adresse pour la passerelle |
/login dans la CLI : Every address for gateway host <host> must be inside its declared network <block>, and it also resolves to <ip> |
Le nom de la passerelle se résout vers une adresse extérieure au bloc déclaré dans gatewayInternalNetworks : un second site, ou un enregistrement IPv6 sur un nom dual-stack. Avec un bloc déclaré, chaque enregistrement doit se trouver dans ce seul bloc IPv4, adresses privées et IPv6 comprises |
Ne publiez pour le nom de la passerelle que des enregistrements situés dans le bloc sur les machines des développeurs, ou servez un nom distinct, uniquement interne |
/login dans la CLI : <host> is on the declared network <block>, which Claude Code checks over a direct connection, not through an HTTP proxy |
Un HTTPS_PROXY ou HTTP_PROXY s'applique à une passerelle située sur un bloc déclaré |
Sur la machine du développeur, ajoutez l'entrée NO_PROXY indiquée par le message |
/login dans la CLI : un message commençant par gatewayInternalNetworks in managed settings |
La valeur enfreint l'une des règles de validation, et le message indique laquelle. Tant que vous ne l'avez pas corrigée, Claude Code refuse toute nouvelle commande /login vers une passerelle sur la machine, y compris les passerelles sur des adresses privées ; les connexions existantes continuent de fonctionner |
Dans la source de paramètres gérés que vous déployez, corrigez l'entrée indiquée par le message, puis relancez /login |
/login dans la CLI : Could not resolve the configured HTTP proxy |
Le nom d'hôte dans HTTPS_PROXY ou HTTP_PROXY ne se résout pas depuis la machine du développeur, généralement parce qu'elle n'est pas connectée au réseau de l'entreprise |
Demandez au développeur de se connecter à votre réseau ou VPN et de réessayer, ou corrigez l'URL du proxy |
/login dans la CLI : Could not resolve gateway host <host> |
La machine ne parvient pas à résoudre le nom DNS interne de la passerelle, généralement parce qu'elle n'est pas sur le réseau de l'entreprise | Demandez au développeur de se connecter à votre réseau ou VPN, puis de réessayer /login |
Le démarrage se termine avec une erreur de validation de configuration mentionnant store.postgres_url |
Aucun Postgres n'est configuré ; la passerelle nécessite Postgres | Définissez store.postgres_url. Pour le développement local, utilisez un conteneur jetable : docker run --rm -p 5432:5432 -e POSTGRES_HOST_AUTH_METHOD=trust postgres. |
Le démarrage se termine : store.postgres_url in <path> is not a URL the gateway can read, ou avant v2.1.290 un simple Invalid URL ou URI error |
L'URL ne peut pas être analysée, par exemple parce qu'elle répertorie plus d'un hôte ou que son mot de passe contient un /, ?, # ou % non encodé |
Indiquez un seul hôte, et déplacez le mot de passe dans store.password |
Le démarrage se termine : requires the native binary |
Exécution sous Node au lieu du binaire natif | Installez Claude Code avec l'une des méthodes d'installation autonomes |
Le démarrage se termine avec une erreur de découverte OIDC après config.load |
oidc.issuer est injoignable, ou la chaîne TLS n'est pas approuvée |
Vérifiez que l'émetteur est joignable depuis le pod et qu'il sert /.well-known/openid-configuration. Définissez ca_cert_pem pour une PKI privée. Si le pod n'atteint l'IdP que via un proxy de transfert, définissez oidc.use_proxy: true ; sur les versions antérieures à v2.1.227, donnez plutôt au pod une route directe vers chacun des endpoints de l'IdP. Si le pod ne parvient pas non plus à résoudre le nom d'hôte de l'IdP, ou si le proxy refuse CONNECT vers une adresse IP, voir Sortie uniquement via proxy, qui nécessite v2.1.277 ou une version ultérieure. |
| Le démarrage se termine avec une erreur de permission Postgres | Le rôle de base de données ne dispose pas des droits DDL sur son schéma | Accordez au rôle CREATE sur le schéma de la passerelle afin qu'elle puisse créer et modifier ses tables au démarrage |
Log : remaining connection slots are reserved ou sorry, too many clients already, provenant de PostgreSQL. Cela apparaît dans les avertissements postgres connection closed des réplicas en cours d'exécution, ou dans le log de démarrage d'un nouveau réplica. Dans ce cas, remaining connection slots are reserved peut suivre attempt 1 of 3, et le réplica peut tout de même démarrer. |
Les réplicas demandent plus de connexions que la base de données n'en a encore de disponibles pour la passerelle, et PostgreSQL refuse les connexions supplémentaires | Faites en sorte que le total tienne, comme le décrit Dimensionner le pool de connexions : exécutez moins de réplicas, abaissez store.max_connections, ou augmentez le max_connections de la base de données. Si le total tient sauf pendant une mise à jour progressive, vous pouvez à la place demander à votre orchestrateur d'arrêter un ancien réplica avant d'en démarrer un nouveau, s'il le permet. |
Log : could not connect to Postgres at boot, attempt 1 of 3, avec une raison autre que remaining connection slots are reserved |
La base de données n'était pas encore joignable au démarrage de la passerelle, par exemple sur une instance à froid dont le réseau est encore en cours d'initialisation | Si la passerelle termine ensuite son démarrage, aucune action n'est nécessaire. Lorsque la base de données n'est pas joignable, la passerelle tente la connexion trois fois, à deux secondes d'intervalle, avant de se terminer. Si elle se termine avec could not connect to Postgres, vérifiez store.postgres_url, notamment qu'elle indique un seul hôte, ainsi que le chemin réseau vers la base de données. Si les tentatives expirent au lieu d'être refusées, augmentez store.connect_timeout_seconds pour accorder plus de temps à chacune. |
Log : Postgres <version> is below the supported floor |
La base de données exécute une version de PostgreSQL plus ancienne que celle prise en charge par votre version de la passerelle. La passerelle continue de fonctionner. | Mettez à niveau la base de données. Sur PostgreSQL 11, 12 ou 13, vous pouvez plutôt mettre à niveau la passerelle pour satisfaire l'exigence PostgreSQL. |
/oauth/callback affiche « Sign-in could not be completed » |
Domaine d'e-mail rejeté, échec de validation de l'id_token, ou email_verified explicitement à false, que la passerelle rejette toujours sans possibilité de remplacement |
Vérifiez allowed_email_domains et que l'IdP renvoie une claim email vérifiée. Pour email_verified: false, corrigez la vérification côté IdP. Si votre IdP émet l'e-mail sous un autre nom de claim, définissez oidc.email_claim. |
Log : token exchange failed request_id=<id>: id_token missing email claim |
L'IdP n'inclut pas email dans l'id_token par défaut. Ce rejet ne se produit que lorsque allowed_email_domains est défini ; sans lui, un e-mail manquant crée une session sans e-mail |
Configurez l'IdP pour qu'il émette email dans l'id_token. Okta : ajoutez email aux claims de l'ID token d'un serveur d'autorisation personnalisé. Entra : ajoutez email comme claim facultative dans l'inscription de l'application. PingFederate : activez une OpenID Connect Policy qui émet email. Si l'IdP fournit email depuis l'endpoint userinfo mais refuse de l'inclure dans l'id_token, comme le serveur d'autorisation d'organisation Okta, définissez oidc.userinfo_fallback: true. |
Log : refresh failed request_id=<id>: invalid_token (…) (at userinfo_no_id_token, …), et les développeurs voient Cloud gateway session expired toutes les session.ttl_hours |
L'IdP a accepté le jeton de rafraîchissement mais n'a renvoyé aucun id_token avec celui-ci, si bien que la passerelle a demandé les claims de l'utilisateur à l'endpoint userinfo de l'IdP. L'IdP y a rejeté le jeton d'accès rafraîchi. La passerelle répond temporarily_unavailable, donc Claude Code conserve le jeton de rafraîchissement mais ne peut pas renouveler la session. Les versions de la passerelle antérieures à v2.1.260 consignent la même ligne sans le détail (at …). |
Définissez oidc.scope_on_refresh: true, disponible dans la passerelle v2.1.260 ou ultérieure, afin que la requête de rafraîchissement redemande openid. Certains IdP, comme Okta, ne renvoient un id_token lors du rafraîchissement que sur demande. Sur PingFederate, activez plutôt Return ID Token On Refresh Grant sous Applications > OAuth > OpenID Connect Policy Management. La clé ne modifie pas le comportement de PingFederate. Pour les autres IdP qui l'omettent toujours, vérifiez si l'endpoint userinfo accepte les jetons d'accès émis par un rafraîchissement. En solution temporaire, augmentez session.ttl_hours. Voir Configuration du fournisseur d'identité pour le compromis lié au déprovisionnement. |
Un développeur se connecte, puis chaque requête de cette session échoue avec une erreur 431 |
Le jeton de session dans l'en-tête Authorization de chaque requête répertorie les groupes IdP du développeur ; pour un développeur membre de nombreux groupes, les en-têtes peuvent donc dépasser au total ce que la passerelle accepte |
Voir En-têtes de requête trop volumineux après la connexion pour savoir quelle limite s'applique et quoi modifier |
Chaque requête Amazon Bedrock renvoie 502 ; le log affiche Could not load credentials from any providers |
Sur EC2, la limite de sauts par défaut d'IMDSv2, égale à 1, bloque la requête de métadonnées d'instance depuis l'intérieur du conteneur. Le démarrage et /readyz réussissent malgré tout, car le SDK AWS résout les identifiants de l'instance lors de la première requête, et non à la construction du client |
Augmentez la limite de sauts avec aws ec2 modify-instance-metadata-options --instance-id <id> --http-put-response-hop-limit 2, ou définissez-la dans le modèle de lancement. La modification s'applique à chaque conteneur de l'instance. Préférez les rôles de tâche ECS lorsqu'ils sont disponibles : ils lisent les identifiants depuis l'endpoint d'identifiants de conteneur ECS et évitent entièrement cette modification. Sinon, appliquez la modification sur une instance dédiée à la passerelle pour limiter l'exposition. |
En pic de charge, les réponses tardent à démarrer ou semblent bloquées, ou échouent avec un 502 all upstreams failed alors que l'upstream est sain |
Un réplica a plus de requêtes ouvertes qu'il n'en envoie simultanément à l'upstream, si bien que les requêtes supplémentaires attendent dans la passerelle. Sur un upstream provider: anthropic, une requête qui attend plus longtemps que timeouts.upstream_ttfb_ms abandonne cet upstream, ce qui produit le 502 lorsqu'aucun upstream suivant ne la sert. Le log affiche un avertissement contenant client requests are open. |
Ajoutez des réplicas, ou augmentez la limite de chaque réplica. Voir Requêtes upstream simultanées. |
Sur un upstream autre que provider: anthropic, un tour comportant une longue pause de réflexion échoue. Le proxy placé devant la passerelle consigne une requête qui reste ouverte environ 12,5 minutes, puis une série d'erreurs 504 |
Claude Code a mis fin à un flux qui avait livré son premier événement de réponse puis ne transportait plus que des pings keepalive. Il a renvoyé la requête sans streaming, et chaque réponse prend plus de temps que le délai d'expiration du proxy. | Augmentez CLAUDE_STREAM_IDLE_TIMEOUT_MS pour vos développeurs. Voir Une longue réflexion se termine par des délais d'expiration du proxy. |
Sur provider: anthropic, un tour comportant une longue pause de réflexion échoue. Le proxy consigne une requête ouverte pendant environ 20 minutes, puis des erreurs 502 ou 504 |
Claude Code a mis fin à un flux qui avait livré son premier événement de réponse puis ne transportait plus que des pings keepalive. Il a renvoyé la requête sans streaming, et chaque réponse prend plus de temps que l'attente de la passerelle sur l'upstream, timeouts.upstream_ttfb_ms, ou que le délai d'expiration du proxy. |
Augmentez CLAUDE_STREAM_IDLE_TIMEOUT_MS pour vos développeurs. Voir Longue réflexion sur un upstream Anthropic API. |
| Erreur de l'IdP : scope inconnu ou non pris en charge | L'IdP rejette les scopes qu'il ne reconnaît pas | Définissez oidc.scopes exactement sur la liste acceptée par votre IdP ; elle doit inclure openid. La valeur par défaut est openid profile email offline_access. |
Les sessions ne se renouvellent pas silencieusement après la définition de oidc.scopes |
offline_access a été retiré lors du remplacement |
Rajoutez offline_access si votre IdP le prend en charge. Sans jeton de rafraîchissement, les développeurs doivent refaire la connexion dans le navigateur toutes les session.ttl_hours. |
| Le navigateur affiche « This request came from another site and was blocked » | POST de formulaire intersite, bloqué au titre de la protection CSRF. Comportement attendu pour les pages intégrées ou passant par un proxy | Ouvrez directement le lien de vérification |
| Chrome bloque le bouton Approve avec « Refused to send form data … violates … Content Security Policy directive: form-action », alors que la même page fonctionne dans Safari ou Firefox | Chrome applique form-action à toute la chaîne de redirection. Votre IdP redirige ensuite vers un second hôte qui ne figure pas dans la liste d'autorisation. |
Ajoutez chaque origine supplémentaire de la chaîne de redirection à oidc.form_action_origins. Ouvrez Chrome DevTools → Console sur la page Approve pour voir quelle origine a été bloquée. |
| La connexion aboutit auprès de l'IdP mais le callback échoue, avec une erreur CSP dans Chrome ou « this sign-in link has expired » dans Safari | L'IdP a renvoyé le code via response_mode=form_post, qui le soumet automatiquement en cross-origin via POST vers /oauth/callback. Chrome bloque cela avec une CSP stricte ; Safari autorise la soumission mais le callback ne lit que la query string. |
Assurez-vous que votre IdP respecte response_mode=query, que la passerelle demande explicitement pour que le callback soit une simple redirection |
| La connexion fonctionne en local mais échoue derrière un ALB | public_url indique toujours l'origine http:// locale ou interne, si bien que l'IdP reçoit un redirect_uri incorrect |
Définissez listen.public_url sur l'origine https:// externe et enregistrez <public_url>/oauth/callback auprès de l'IdP |
| Le développeur voit la demande de confiance à plusieurs reprises | Le certificat TLS change selon le réplica ou selon la requête | Utilisez un certificat stable au niveau de l'ingress, ou terminez TLS une seule fois et exécutez les réplicas en HTTP simple en interne |
/login dans la CLI : « Could not verify the gateway's TLS certificate » ou SELF_SIGNED_CERT_IN_CHAIN |
La chaîne TLS de la passerelle est signée par une CA privée absente du magasin de confiance de l'hôte de la CLI | Claude Code lit par défaut le magasin de confiance de l'OS avec le binaire natif et avec Node 22.15 ou ultérieur ; CLAUDE_CODE_CERT_STORE contrôle ce comportement. Si la CA est installée dans le magasin de confiance de l'OS, assurez-vous que les développeurs utilisent un runtime à jour. Sinon, définissez NODE_EXTRA_CA_CERTS sur le PEM du certificat de la CA avant le lancement. La demande d'empreinte lors de la première connexion s'applique toujours. |
/login dans la CLI termine la connexion dans le navigateur, puis la session se termine avec Cloud gateway sign-in was not completed et une non-concordance de certificat TLS |
Lors de la première requête après la connexion, la passerelle a présenté un certificat qui ne correspond pas à l'empreinte épinglée par Claude Code ; Claude Code n'a donc conservé aucun identifiant de passerelle. Les causes habituelles sont des réplicas derrière une même adresse qui servent des certificats différents, ou un élément sur le chemin réseau qui intercepte TLS. | Servez un seul certificat pour le nom d'hôte, par exemple en terminant TLS une seule fois au niveau de l'ingress, puis demandez au développeur d'exécuter à nouveau /login. Si ce certificat diffère de celui épinglé, Claude Code affiche à nouveau la demande de confiance avec un avertissement indiquant que le certificat a changé. |
/login dans la CLI s'arrête avec The gateway's TLS certificate changed during sign-in: it no longer matches the one you trusted |
Une requête de connexion a atteint un serveur dont le certificat ne correspond pas à celui que le développeur a accepté au démarrage de /login : réplicas derrière une même adresse servant des certificats différents, interception TLS sur le chemin, ou rotation de certificat pendant la connexion. |
Servez un seul certificat pour le nom d'hôte, puis demandez au développeur de relancer la connexion et d'examiner le nouveau certificat lors de la demande de confiance. |
Le message Cloud gateway sign-in was not completed indique le nom d'hôte de la passerelle. Lorsque Claude Code dispose à la fois de l'empreinte épinglée et de celle présentée, le message affiche également les 16 premiers caractères de chacune.
Si Claude Code signale couldn't load your organization's managed settings après une connexion à la passerelle, Claude Code indique la raison, redémarre sur place et reprend la conversation. Si Claude Code ne peut pas redémarrer, par exemple dans une session en arrière-plan, Claude Code met fin à la session et conserve la connexion.
En-têtes de requête trop volumineux après la connexion
Les requêtes d'un développeur peuvent échouer avec une erreur 431 après la connexion lorsque ce développeur appartient à de nombreux groupes IdP.
La passerelle répond 431 lorsque les en-têtes d'une requête dépassent au total 256 Kio, ou limits.max_request_header_bytes si vous le définissez. Elle n'écrit aucune ligne de log ni aucun événement d'audit pour ces requêtes. Les versions de la passerelle antérieures à v2.1.284 répondent 431 au-delà de 16 Kio.
Commencez par le premier de ces cas qui s'applique à votre passerelle :
- Passerelle antérieure à v2.1.284 : mettez à niveau la passerelle
limits.max_request_header_bytesdéfini : augmentez la valeur ou supprimez la clé- Aucun des deux ne s'applique, ou l'erreur
431persiste ensuite : faites en sorte que votre IdP émette moins de groupes. Configuration du fournisseur d'identité explique comment Okta, Microsoft Entra ID et Google Workspace fournissent les groupes
Lorsque vous réduisez la claim de groupes, conservez les groupes que vous avez indiqués dans ces paramètres, qui déterminent l'accès, la politique et les plafonds de dépenses d'un développeur :
oidc.allowed_groups: détermine qui peut se connecteradmin.admin_groups: détermine qui peut appeler l'API d'administration avec sa session de passerellematch.groupsdansmanaged.policies: détermine quelle politique s'applique à un développeur- Plafonds de dépenses
rbac_group: déterminent quels plafonds de groupe s'appliquent à un développeur
Une longue réflexion se termine par des délais d'expiration du proxy
Si votre upstream est provider: anthropic, consultez plutôt Longue réflexion sur un upstream Anthropic API : vous y augmentez également CLAUDE_STREAM_IDLE_TIMEOUT_MS, mais les durées et les erreurs diffèrent.
Si des tours échouent après une longue réflexion et que votre proxy consigne une requête ouverte pendant environ 12,5 minutes, puis une série d'erreurs 504, augmentez CLAUDE_STREAM_IDLE_TIMEOUT_MS dans une politique de la passerelle. Par exemple, avec un délai d'inactivité de 240 secondes sur le proxy, la série compte 10 requêtes, chacune coupée à 240 secondes.
- La première requête : un flux qui livre son premier événement de réponse,
message_start, puis uniquement des pings pendant que Claude réfléchit. Avec les paramètres par défaut, Claude Code met fin à ce flux au bout d'environ 12,5 minutes. - Les 10 autres : la même requête, envoyée sans streaming puis réessayée, soit 10 envois au total par défaut. Elles ne reçoivent aucun ping, donc une réponse lente atteint le délai d'expiration du proxy.
Vous n'avez pas besoin d'un délai d'expiration du proxy plus long pour cette correction. Si vous augmentez uniquement le délai d'expiration du proxy, les requêtes sans streaming échouent toujours dès qu'une réponse prend plus de temps que l'attente propre à Claude Code, 300 secondes par défaut.
Confirmer la cause
Demandez à un développeur de reproduire l'échec avec claude --debug-file ./claude-debug.txt, puis recherchez cette ligne dans ce fichier :
Error streaming, falling back to non-streaming mode: Stream idle timeout - no chunks received
Si vos développeurs définissent déjà CLAUDE_CODE_DISABLE_NONSTREAMING_FALLBACK sur 1, vous ne voyez aucune requête sans streaming, et le tour se termine par API Error: Stream idle timeout - no chunks received. La même correction s'applique.
Choisir une valeur
Choisissez une valeur de CLAUDE_STREAM_IDLE_TIMEOUT_MS dont la deuxième colonne couvre votre plus longue pause de réflexion, ou commencez par 1800000 si vous ne la connaissez pas. Un flux peut ne recevoir que des pings pendant environ 7,5 minutes de plus que la valeur :
CLAUDE_STREAM_IDLE_TIMEOUT_MS |
Un flux peut ne recevoir que des pings pendant |
|---|---|
300000, la valeur par défaut |
Environ 12,5 minutes |
900000 |
Environ 22,5 minutes |
1800000 |
Environ 37,5 minutes |
Si un upstream se bloque alors que la passerelle continue d'envoyer des pings, vos développeurs attendent également aussi longtemps avant que Claude Code n'abandonne le flux. Une connexion devenue totalement silencieuse se termine toujours au bout de 5 à 6 minutes, car le délai d'inactivité du corps ne suit pas cette variable.
Fournir la valeur dans une politique
Ajoutez l'entrée env à chaque politique de gateway.yaml qui fournit déjà des paramètres Claude Code aux développeurs que vous souhaitez couvrir. Placez-la sous la clé code, cli ou settings que cette politique possède déjà. Pour tester d'abord la valeur, commencez par une politique qui correspond à un seul groupe. Voir managed pour savoir comment les politiques correspondent et héritent. Cet exemple ajoute l'entrée à une politique match: {} dont la clé est cli :
managed:
policies:
- match: {}
cli:
env:
CLAUDE_STREAM_IDLE_TIMEOUT_MS: "1800000"
Avec la clé cli, vous couvrez les sessions du terminal, de l'extension IDE et de l'Agent SDK. Pour l'onglet Code de Claude Desktop, voir Choisir cli ou code.
Redémarrez la passerelle pour qu'elle lise le fichier modifié. Demandez ensuite aux développeurs de redémarrer Claude Code pour obtenir CLAUDE_STREAM_IDLE_TIMEOUT_MS.
Longue réflexion sur un upstream Anthropic API
Si provider: anthropic est le seul upstream du modèle et que votre proxy consigne une requête ouverte pendant environ 20 minutes, puis des erreurs 502 ou 504, augmentez CLAUDE_STREAM_IDLE_TIMEOUT_MS dans une politique de la passerelle.
- La longue requête : un flux qui livre
message_startpuis uniquement des pings pendant que Claude réfléchit. Claude Code y met fin au bout d'environ 20 minutes avec les paramètres par défaut, et plus tard une fois la variable augmentée. - Les erreurs : les requêtes que Claude Code envoie ensuite sans streaming. Chacune échoue avec un
502de la passerelle, ou avec le504de votre proxy si le délai d'expiration du proxy est plus court que l'attente de la passerelle. Cette attente esttimeouts.upstream_ttfb_ms, que vous n'avez pas besoin d'augmenter pour cette correction.
Pour confirmer la cause, voir Confirmer la cause.
Choisissez la valeur dont la durée couvre votre plus longue pause de réflexion : environ 20 minutes avec la valeur par défaut, 30 avec 900000 et 45 avec 1800000. Suivez ensuite Fournir la valeur dans une politique.
Connexes
- Aperçu de la passerelle Claude apps : démarrage rapide et connexion des développeurs
- Référence de configuration : chaque option du fichier
gateway.yaml