Перейти к основному содержанию
Сначала спланируйте сеть для шлюза. При входе Claude Code отказывается подключаться к шлюзу Claude apps, имя хоста которого разрешается в публичный IP-адрес, даже если этот адрес недоступен из интернета.Шлюз Claude apps может отправлять настройки на машины пользователей, включая хуки, которые запускают shell-команды. Эта проверка помогает не допустить, чтобы пользователи случайно вошли в вредоносный шлюз в публичном интернете. Держите и свой собственный шлюз вне интернета.Выберите адрес шлюза до того, как выбирать, где он будет работать. Обычно это частный адрес, к которому пользователи обращаются во внутренней сети или через VPN. Если ваша внутренняя сеть использует публичные диапазоны IPv4, вы можете указать один диапазон, в который входят и шлюз, и машины ваших пользователей. Claude Code воспринимает такое совпадение как признак того, что шлюз находится в вашей внутренней сети. См. Выбор адреса для шлюза. Если ни один из вариантов не подходит для вашей сети, обратитесь к вашей команде по работе с клиентами Anthropic.
На этой странице рассматривается операционная сторона запуска шлюза Claude apps: регистрация клиента OAuth в вашем поставщике идентификации (IdP), развертывание шлюза как контейнера и его ежедневное управление. Для каждого параметра в файле gateway.yaml, который шлюз читает при загрузке, см. Справочник по конфигурации. Развертывание в производстве следует четырем этапам по порядку, и разделы ниже соответствуют им. Первые два — это места, где вы делаете выбор; вторые два — справочный материал, который следует консультировать после запуска.
  1. Настройка вашего поставщика идентификации: зарегистрируйте клиента OAuth и проверьте примечания для каждого IdP для Okta, Entra и Google
  2. Развертывание шлюза: создайте образ контейнера с закрепленной версией и запустите его на Kubernetes, Cloud Run или вашей собственной платформе. Этот раздел также охватывает решения по стоимости, обходу, нескольким шлюзам и бессерверным вычислениям
  3. Настройка операций: журналы, зонды здоровья, поведение при сбое, ротация секретов и обновления. Справочник для подключения мониторинга и runbooks
  4. Проверка позиции безопасности: какие данные куда передаются, модель угроз и ответы на вопросы соответствия. Справочник для проверки безопасности
Если вход или загрузка не удаются, перейдите прямо к Устранению неполадок, который организован по ошибкам, которые вы видите.

Настройка поставщика удостоверений

Зарегистрируйте конфиденциальное веб-приложение OAuth/OpenID Connect (OIDC) с одним URI перенаправления, https://<gateway>/oauth/callback, и назначьте его пользователям или группам, которые должны иметь доступ к шлюзу. Шлюз аутентифицируется в IdP с помощью секрета клиента из регистрации или с помощью сертификата, который вы загружаете в регистрацию, если ваш IdP вместо этого использует учётные данные на основе сертификата. Работает любой OIDC-совместимый IdP: Okta, Microsoft Entra ID, Google Workspace, Keycloak, Dex, PingFederate и другие. IdP должен соответствовать трем требованиям:
  • Обслуживает /.well-known/openid-configuration по HTTPS в production; шлюз принимает http:// издателя, и издатель loopback дополнительно требует CLAUDE_GATEWAY_ALLOW_LOOPBACK=1
  • Поддерживает поток authorization-code. PKCE (Proof Key for Code Exchange) включен по умолчанию; отключите его с помощью oidc.use_pkce: false для IdP, которые его не поддерживают
  • Возвращает email и опционально groups в id_token или обслуживает их из конечной точки userinfo с oidc.userinfo_fallback: true
Для приватной PKI установите oidc.ca_cert_pem. Несколько поставщиков обрабатывают утверждения email и group по-разному:
  • Okta: сервер авторизации организации в https://example.okta.com возвращает тонкий id_token, который опускает email и groups, поэтому установите oidc.userinfo_fallback: true всякий раз, когда вы используете его как issuer. Пользовательский сервер авторизации, такой как https://example.okta.com/oauth2/default, который включает email и опционально groups в id_token, выдает их напрямую и не требует fallback. Okta выдает groups только когда область groups запрашивается в oidc.scopes и фильтр утверждения groups приложения это позволяет; userinfo_fallback не может заполнить утверждение, которое IdP не был попрошен выдать.
  • Microsoft Entra ID: issuer = https://login.microsoftonline.com/<tenant-id>/v2.0. Entra выдает Object ID групп, а не имена, поэтому используйте GUID в managed.policies.match.groups или используйте App Roles для читаемых имен. Если ваш tenant выдает роли под roles вместо groups, установите oidc.groups_claim: roles.
  • Google Workspace: issuer = https://accounts.google.com. id_token Google не содержит groups. Чтобы использовать основанные на группах allowed_groups или managed.policies с Google в качестве IdP, настройте oidc.google_groups, которая ищет группы каждого пользователя через Admin SDK Directory API, используя сервисный аккаунт с делегированием на уровне домена. Без этого используйте oidc.allowed_email_domains для проверки членства и managed.policies.match.email_domain для назначения политики. Google также игнорирует стандартную область offline_access. Для refresh tokens установите oidc.scopes: [openid, profile, email] и oidc.extra_auth_params: { access_type: offline, prompt: consent }.
Refresh tokens позволяют шлюзу молча обновлять сеанс разработчика без отправки разработчика в браузер. Они также управляют deprovisioningом, потому что когда IdP отключает пользователя, следующее обновление не удается и сеанс заканчивается в течение ttl_hours. Шлюз запрашивает offline_access по умолчанию, чтобы получить refresh token. Если ваш IdP требует явного согласия для offline access, настройте клиент OAuth, чтобы это позволить.Если ваш IdP вообще не может выдавать refresh tokens, шлюз все еще работает, но нет молчаливого обновления, поэтому разработчики повторно запускают вход в браузер, когда их сеанс истекает. Чтобы это не происходило каждый час, поднимите session.ttl_hours на 8 или 12. Компромисс — это задержка deprovisioningа, потому что без refresh tokens отключенный пользователь сохраняет доступ до истечения более длительного TTL.

Развертывание

Шлюз — это один stateless бинарный файл Linux, который координирует работу через Postgres, поэтому развёртывайте его так же, как вы развёртываете любой другой stateless сервис в вашей среде. Держите его внутри вашей сети, где ваши разработчики могут обращаться к нему по HTTPS, а он может обращаться к вашему IdP, и относитесь к нему как к любому сервису, содержащему production учётные данные. Несколько решений формируют развертывание помимо того, где оно работает:
  • Стоимость: нет отдельной лицензии или платы за место. Шлюз является частью бинарного файла claude, поэтому вы платите за inference через ваше существующее обязательство, плюс вычисления, на которых он работает.
  • Обход: шлюз не требует, чтобы единственный маршрут к модели проходил через него. Разработчик со своими собственными учетными данными все еще может вызвать поставщика напрямую, поэтому закрытие этого пути — это решение политики сети, например блокировка выхода на api.anthropic.com кроме как от шлюза. Блокировка этого выхода также нарушает проверку безопасности домена WebFetch, которая вызывает api.anthropic.com с каждой машины разработчика. Установите skipWebFetchPreflight: true в управляемой политике, чтобы отключить это.
  • Несколько шлюзов: каждый — это отдельное развертывание со своей конфигурацией, и CLI хранит доверие и учетные данные для каждого имени хоста шлюза, поэтому команды могут использовать разные шлюзы без конфликтов. Чтобы обслуживать несколько издателей OIDC, запустите отдельные экземпляры.
  • Бессерверная архитектура: Cloud Run работает, если вы установите min-instances: 1, чтобы избежать холодного обнаружения OIDC. Lambda и Cloud Functions не работают, потому что шлюз — это долгоживущий HTTP сервер.
Каждая production топология здесь помещает прокси L7, такой как Ingress, фронтенд Cloud Run или ALB, перед простыми HTTP репликами. Установите listen.trusted_proxies на диапазоны источников прокси, чтобы шлюз читал IP клиентов из X-Forwarded-For. Шлюз соблюдает заголовок только когда TCP peer доверен. Пример Google Cloud и пример AWS содержат конкретные значения для каждой топологии. Без доверенных прокси каждый запрос выглядит как исходящий с IP прокси, что сворачивает ограничения скорости для каждого IP в один общий bucket и записывает IP прокси в события аудита. Не перенаправляйте запросы на конечные точки авторизации устройства и токена шлюза, например с переписыванием HTTP-в-HTTPS или канонизацией хоста на ingress. Claude Code не следует перенаправлениям на эти запросы, поэтому правило ingress, которое их перенаправляет, нарушает вход и обновление токена. Дайте прокси любой timeout неактивности, превышающий интервал keepalive шлюза, который зависит от upstream:
  • На каждом upstream кроме provider: anthropic, шлюз записывает SSE ping один раз, когда поток был молчалив около 15 секунд.
  • На provider: anthropic, шлюз пропускает ответ без изменений, включая собственные ping’и API Anthropic.
Значение по умолчанию, такое как 60 секунд ALB, достаточно, чтобы держать тихий поток открытым. Пример AWS поднимает его до часа в любом случае, и его строка troubleshooting охватывает шлюзы старше v2.1.229, которые не отправляли ничего во время тихих периодов на upstream’ах, которые теперь получают ping’и.

Выберите адрес для шлюза

Claude Code принимает адрес шлюза одним из двух способов:
  • Частный адрес: разместите шлюз за внутренним балансировщиком нагрузки или VPN с именем хоста, которое разрешается только в частные адреса, такие как RFC 1918 или CGNAT 100.64.0.0/10. Машины пользователей могут иметь любой адрес. Предварительное требование о частной сети перечисляет допустимые диапазоны.
  • Объявленный блок: если ваша внутренняя сеть использует публичное пространство IPv4, принадлежащее вашей организации, укажите этот блок в управляемой настройке gatewayInternalNetworks. И шлюз, и машина пользователя должны находиться в этом блоке. См. Разрешение шлюза в публичном адресном пространстве, которым вы владеете.
Если ни один блок не содержит их обоих, вместо этого назначьте шлюзу частный адрес.

Образ контейнера

Создайте свой собственный образ вокруг нативного бинарного файла claude из стандартного выпуска Claude Code:
  1. Загрузите сборку Linux для архитектуры вашего образа из закрепленного выпуска; см. Установка конкретной версии для URL загрузки.
  2. Проверьте его против подписанного GPG manifest.json выпуска, как описано в Целостность бинарного файла и подпись кода.
  3. Скопируйте его в контекст сборки.
Зеркалируйте выпуск в ваш внутренний реестр, если ваши сборки не могут достичь хоста выпуска, и закрепите версию, которую запускает ваш флот. Помимо бинарного файла, образу нужны:
  • Образ на основе glibc: единственные динамические зависимости сборки glibc — это библиотеки glibc. Образам на основе Musl нужна сборка linux-x64-musl или linux-arm64-musl, единственной динамической зависимостью которой является musl.
  • Записываемый каталог состояния: шлюз работает как любой пользователь, но минимальные образы не имеют записываемого home. Установите CLAUDE_CONFIG_DIR на записываемый путь, такой как /tmp/.claude.
  • Команда контейнера: claude gateway --config /etc/claude/gateway.yaml, с файлом конфигурации, смонтированным только для чтения, и секретами, предоставленными как переменные окружения; шлюз слушает на listen.port, по умолчанию 8080.

Kubernetes

Запустите шлюз как Deployment, как любой stateless сервис:
  • Смонтируйте конфигурацию из ConfigMap и секреты из Secret; ссылайтесь на секреты в YAML через ${file:/path/to/secret} или как переменные окружения
  • Завершите TLS на Ingress и установите listen.public_url на имя хоста Ingress
  • Укажите зонд готовности на GET /readyz и зонд живучести на GET /healthz
Для полного примера на AWS, охватывающего ECS Fargate или EKS, Amazon RDS и AWS Secrets Manager, см. Развертывание на AWS. Предпочитайте workload identity платформы вместо статических ключей; справочник upstreams содержит детали настройки для каждой платформы. Для кросс-облачного сопряжения, такого как upstream Bedrock на GKE, установите явные учетные данные в блоке auth upstream вместо этого.

Cloud Run

Настройте сервис следующим образом:
  • Оставьте listen.port на его значении по умолчанию 8080, которое соответствует PORT Cloud Run по умолчанию, или установите port: ${PORT}
  • Установите public_url на внешне доступное происхождение. Для production это обычно имя хоста внутреннего балансировщика нагрузки, потому что /login отклоняет публичные адреса и URL *.run.app разрешается на один, поэтому URL Cloud Run один работает только для curl или дымового теста браузера. Исключение — сеть, где *.run.app разрешается приватно через Private Service Connect и приватную зону Cloud DNS; в этой топологии URL Cloud Run — это действительный public_url. Пример Google Cloud охватывает оба.
  • Смонтируйте конфигурацию как том секрета
  • Установите min-instances: 1, чтобы избежать холодного обнаружения OIDC при первом запросе
Для полного примера на Google Cloud, охватывающего Cloud Run или GKE, Cloud SQL и Secret Manager, см. Развертывание на Google Cloud.

Отправьте URL шлюза на машины разработчиков

Как только шлюз начнёт обслуживать, отправьте forceLoginMethod, forceLoginGatewayUrl и parentSettingsBehavior: "merge" на каждую машину разработчика через управляемые настройки, через MDM или путём прямой записи файла managed-settings.json для каждой ОС. Как только вы развернете ключи, Claude Code перестанет использовать оставшийся API ключ или вход claude.ai на машине, поэтому спланируйте отправку вместе с вашими инструкциями по входу. Политика администратора требует вход через Cloud шлюз описывает сообщения, которые видят разработчики. См. где каждый механизм хранит политику для путей файлов и Управляемые параметры на стороне клиента для эквивалента Claude Desktop bootstrapUrl.

Крупные развертывания

Вход ограничен по скорости для каждого IP адреса клиента, и значения по умолчанию подходят для небольшой команды. Каждый адрес получает 30 начал входа и 10 отправок кода каждые 10 минут. Развертывание для тысяч разработчиков может достичь этих ограничений в первое утро по одной из двух причин:
  • Шлюз не может видеть за вашим балансировщиком нагрузки. Без listen.trusted_proxies каждый разработчик выглядит как исходящий с адреса балансировщика нагрузки и делит один лимит. Шлюз логирует предупреждение в первый раз, когда он игнорирует заголовок X-Forwarded-For. Если балансировщик нагрузки должен быть указан в listen.trusted_proxies, укажите его, прежде чем менять что-либо ещё. Если разработчики всё ещё делят один адрес, поднимите rate_limits.
  • Много разработчиков делят несколько NAT или VPN адресов выхода. Они делят лимиты этих адресов даже когда trusted_proxies правильно установлен. Поднимите rate_limits, чтобы соответствовать.
Чтобы определить размер max, разделите разработчиков на адреса выхода, которые они делят. Оцените, сколько из них входят в один период window_seconds, который по умолчанию составляет 10 минут. Затем удвойте это, чтобы охватить повторные попытки и разработчиков, которые входят как в Claude Code, так и в Claude Desktop. Например, 10 000 разработчиков за 4 адресами выхода входят равномерно в течение часа. Это 2 500 разработчиков на адрес и около 420 из них в каждые 10 минут, которые вы удваиваете и округляете до 1 000. Пример ниже устанавливает оба лимита на 1 000:
device_verify — это то, что останавливает кого-то от угадывания кода входа другого разработчика, поэтому поднимайте его только настолько, насколько нужна ваша оценка. Даже при этих лимитах код состоит из 8 символов из 20-символного алфавита и истекает через 10 минут, поэтому угадывание остается непрактичным; см. Устойчивость к перебору кода пользователя. Когда ваш IdP выдает refresh токены, Claude Code молча обновляет сеансы, поэтому вы можете вернуть лимит после развертывания. Без refresh токенов разработчики входят снова каждые session.ttl_hours. Определите размер обоих лимитов и для этой стабильной скорости и оставьте их повышенными. Когда лимит достигнут, Claude Code v2.1.274 или позже показывает The gateway is limiting sign-in attempts right now. Шлюз на v2.1.274 или позже показывает Too many attempts came from your network address на странице проверки, с параметрами для проверки. Он также записывает строку логирования sign-in refused, которая называет параметр для изменения.

Эксплуатация

Когда шлюз начинает обслуживать трафик, повседневная эксплуатация сводится к чтению его логов, проверке его работоспособности и ротации его секретов по вашему графику. В подразделах описано каждое из этих действий, а также то, что хранится в Postgres и как ведут себя обновления и откаты.

Логи

Шлюз пишет два потока в stderr, оба удобны для обработки в формате JSON:
  • События аудита: однострочный JSON для каждого события, значимого для безопасности. Направьте stderr в ваш агрегатор логов. Генерируемые события включают 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.upsert и admin.limit.delete. Поля зависят от события:
    • Успешные события выпуска и обновления содержат sub, email, client_ip и результат
    • auth.denied и access.denied содержат причину и IP-адрес клиента, а для auth.denied ещё и путь запроса, поскольку при этих отказах идентификатор пользователя отсутствует. Две причины access.denied меняют содержимое события:
      • xff_unparseable: событие также содержит запись X-Forwarded-For, которую не удалось прочитать
      • client_ip_unknown: событие не содержит IP-адреса клиента, поскольку у соединения не было адреса пира, а список access_control был задан
    • access.public_client содержит IP-адрес клиента первого запроса в рамках процесса, пришедшего с публичного адреса, когда access_control.allow_cidrs пуст. Шлюз обслуживает запрос как обычно; событие сигнализирует о том, что шлюз может быть доступен из публичного интернета. Что считается публичным адресом и какой список разрешённых адресов рекомендуется, см. в справочнике по access_control.
    • inference фиксирует, какой вышестоящий сервер обслужил запрос, и статус ответа
    • desktop_bootstrap.denied фиксирует отклонённый запрос начальной загрузки Claude Desktop с указанием причины (not_configured, policy_not_opted_in или no_policy_matched) и идентификатора пользователя
    • guardrail.trace фиксирует, какой фильтр сработал, без совпавшего текста
    • admin.denied фиксирует отклонённую попытку аутентификации в API администратора с IP-адресом клиента, методом, путём и причиной, без предъявленного ключевого материала: invalid_key, если был предъявлен x-api-key, не совпавший ни с одним настроенным ключом; bearer_rejected, если был предъявлен только заголовок Authorization и он не прошёл проверку как сессия шлюза в admin.admin_groups; или no_credentials, если не был предъявлен ни один из заголовков
  • Операционные логи: удобочитаемые строки с префиксом [gateway] о запуске, предупреждениях и ошибках вышестоящих серверов. Переменная окружения CLAUDE_GATEWAY_LOG_LEVEL управляет уровнем детализации и принимает значения debug, info, warn или error; по умолчанию используется info. На уровне debug при каждом входе и обновлении также записываются в лог имена (но не значения) claims в id_token, а также имена claims userinfo, если userinfo_fallback их предоставил, что позволяет диагностировать настройки email_claim и groups_claim без записи персональных данных в лог. На события аудита эта переменная не влияет — они генерируются всегда.

Запись операционных логов в формате JSON

Если ваш сборщик логов считывает уровень каждой строки из поля JSON, задайте CLAUDE_GATEWAY_LOG_FORMAT=json в окружении шлюза. Требуется Claude Code v2.1.319 или новее на сервере шлюза. Тогда каждая строка операционного лога представляет собой один объект с полями severity, time и message:
severity — это уровень лога заглавными буквами, причём warn записывается как WARNING. Неудачный запуск отображается строкой ERROR. События аудита, которые также направляются в stderr, не меняются. Они содержат ts и evt, но не содержат severity.

Работоспособность

Шлюз обслуживает GET /healthz как проверку жизнеспособности (liveness probe) и GET /readyz как проверку готовности (readiness probe). /readyz проверяет доступность хранилища. Если вы задали store.readiness_grace_seconds, /readyz продолжает сообщать о готовности в течение указанного числа секунд после того, как хранилище перестало отвечать. Оба эндпоинта исключены из действия access_control.allow_cidrs, поэтому проверки продолжают работать на слушателе с ограниченным доступом. Документ обнаружения OAuth по адресу /.well-known/oauth-authorization-server также возвращает 200 только после успешной загрузки конфигурации, обнаружения OIDC, создания клиентов вышестоящих серверов и миграции Postgres, поэтому он одновременно служит сквозной проверкой запуска.

Одновременные запросы к вышестоящим серверам

По умолчанию каждая реплика шлюза одновременно отправляет вышестоящим серверам не более 256 запросов. Потоковый ответ учитывается в этом лимите до завершения потока. Запрос, пришедший в момент, когда реплика достигла лимита, ожидает внутри шлюза освобождения слота. Разработчик видит ответ, который долго не начинается или кажется зависшим. Для вышестоящего сервера provider: anthropic запрос, ожидающий дольше timeouts.upstream_ttfb_ms, отказывается от этого вышестоящего сервера и завершается ошибкой 502, если ни один из последующих вышестоящих серверов его не обслужит. Строка лога при запуске, содержащая upstream requests:, показывает действующий лимит. Пока у реплики открыто больше запросов, чем позволяет лимит, она также записывает в лог предупреждение, содержащее client requests are open, не чаще одного раза в минуту. Чтобы обслуживать больше запросов одновременно, у вас есть два варианта:
  • Добавить реплики.
  • Повысить лимит на каждой реплике. Задайте переменную окружения BUN_CONFIG_MAX_HTTP_REQUESTS в контейнере шлюза целым числом от 1 до 65535, затем перезапустите контейнер.
Реплика заполняет свой лимит при частоте запросов, примерно равной лимиту, делённому на среднее число секунд, в течение которых запрос остаётся открытым. Например, если запросы в среднем остаются открытыми 10 секунд, реплика с лимитом по умолчанию 256 заполняет его примерно при 26 запросах в секунду. Если вы используете автомасштабирование по CPU, реплика, достигшая лимита, ставит запросы в очередь, не вызывая масштабирования, поэтому задайте целевое значение ниже того уровня CPU, который показывают ваши реплики, когда записывают в лог предупреждение client requests are open.
Каждый открытый запрос занимает память в процессе шлюза во время потоковой передачи и во время ожидания слота. Даже если оставить лимит равным 256, память перегруженной реплики всё равно растёт, поскольку ожидающие запросы хранят свои тела. Рассчитывайте объём памяти контейнера на число запросов, открытых в пиковый момент, и следите за памятью при изменении лимита. Реплика, у которой заканчивается память, принудительно завершается и обрывает все удерживаемые ею потоки.
При нагрузочном тестировании с load_test_mode запросы не ожидают на этом лимите, но реплика всё равно записывает в лог предупреждение client requests are open.

Держите API_TIMEOUT_MS выше времени до первого байта шлюза

Если вы уменьшаете API_TIMEOUT_MS, чтобы быстрее повторять попытку для запроса без ответа, держите его значение выше времени, которое требуется шлюзу для отправки первых байтов потокового ответа. Запрос, ожидающий дольше, завершается по таймауту, как и каждая повторная попытка, ожидающая столько же, пока ход не завершится с Request timed out, если его раньше не завершит крайний срок первого байта.
  • provider: anthropic: задайте API_TIMEOUT_MS выше максимального времени, за которое ваш вышестоящий сервер отправляет первое событие.
  • Любой другой вышестоящий сервер: задайте значение более чем на 20 секунд выше максимального времени, за которое ваш вышестоящий сервер возвращает заголовки ответа. Шлюз отправляет свой первый keepalive ping примерно через 15 секунд после этих заголовков, если первое событие вышестоящего сервера не придёт раньше. Шлюз версии старше v2.1.229 не отправляет ping, поэтому для него используйте правило для provider: anthropic.
Помимо этого времени, учитывайте возможное ожидание свободного слота и ожидание на недоступном вышестоящем сервере перед переключением при отказе. Также держите значение выше самого долгого непотокового запроса.

Более быстрая повторная попытка для запроса без ответа с помощью крайнего срока первого байта

Чтобы Claude Code быстрее повторял попытку для потокового запроса без ответа, задайте для него крайний срок первого байта с помощью CLAUDE_STREAM_FIRST_BYTE_TIMEOUT_MS на машинах ваших разработчиков. Крайний срок ограничивает время, в течение которого первая попытка ожидает заголовки ответа. Без него эта попытка может ждать от 5 до 6 минут. Требуется Claude Code v2.1.307 или новее на машине разработчика. Задайте переменной положительное целое число миллисекунд в блоке env политики шлюза или в оболочке разработчика. Держите значение выше максимального времени до первого байта вашего шлюза, иначе Claude Code может прерывать и повторно отправлять исправные запросы, заголовки которых приходят дольше. В этом примере в оболочке разработчика задаётся 60 секунд:
Повторная отправка без ответа может ждать от 5 до 6 минут, пока её не завершит таймаут простоя тела ответа, после чего Claude Code повторит попытку в рамках бюджета повторных попыток. Если вы уменьшили API_TIMEOUT_MS только ради более быстрых повторных попыток, удалите это значение, иначе одна повторная отправка без ответа может завершить ход с No response from API. Чтобы убедиться, что крайний срок сработал, попросите разработчика запустить Claude Code с отладочным логированием, затем найдите в логе [first-byte] no response headers.

Поведение при сбоях

Если Postgres становится недоступен, сам шлюз продолжает обслуживать разработчиков, уже выполнивших вход, а новые входы завершаются ошибкой. Смогут ли разработчики действительно продолжать работу, зависит от того, как ваш оркестратор обрабатывает готовность:
  • Существующие сессии: Bearer-токены проверяются локально с помощью секрета JWT, обновления сессий не обращаются к хранилищу, и процесс шлюза по-прежнему может обслуживать запросы инференса
  • Новые входы: завершаются ошибкой до восстановления Postgres, поскольку поток авторизации устройства и его счётчики ограничения частоты запросов хранятся в Postgres
  • Применение лимитов расходов: по умолчанию во время сбоя работает в открытом режиме (fail open), то есть запросы пропускаются и инференс продолжает работать; переключите его в закрытый режим (fail closed), если предпочитаете блокировать запросы, а не пропускать их без учёта расходов
  • Готовность: по умолчанию /readyz сообщает о неготовности, как только Postgres становится недоступен, поэтому все реплики одновременно не проходят проверку готовности. Если трафик направляется только на реплики, прошедшие проверку, весь трафик, включая инференс, который шлюз ещё мог бы обслужить, отклоняется до восстановления Postgres. Проверка жизнеспособности на /healthz всё это время продолжает проходить успешно.
Если ваш IdP становится недоступен, существующие сессии работают до истечения ttl_hours, а новые входы завершаются ошибкой. Обновление сессии получает ответ с предложением повторить попытку и завершается успешно, как только IdP снова станет доступен. Задайте более длительный ttl_hours, если у вашего IdP часто бывают окна обслуживания.

Льготный период готовности

Чтобы разработчики, уже выполнившие вход, продолжали работать во время кратковременного сбоя Postgres, например при переключении базы данных на резервный узел, задайте store.readiness_grace_seconds больше длительности такого переключения, например 300. Если лимиты расходов включены и используется поведение по умолчанию (fail open), запросы через реплику, остающуюся в состоянии готовности, не учитываются до восстановления Postgres, поэтому держите значение минимальным, достаточным для покрытия переключения. Если вы задали enforcement.fail_closed_on_error: true, шлюз отклоняет запросы инференса от разработчиков, выполнивших вход, с сообщением 429 spend limit unavailable до восстановления Postgres, даже пока реплики продолжают проходить проверку готовности. Эта настройка требует Claude Code v2.1.282 или новее на сервере шлюза. Более ранняя версия шлюза отказывается запускаться, обнаружив этот ключ, поэтому обновите все реплики, прежде чем добавлять его. Об откате см. в разделе Обновления. Если вместо этого направить проверку готовности на /healthz, реплики также продолжат проходить её во время сбоя, но /healthz никогда не сообщает о неготовности, поэтому реплика, чьё соединение с Postgres не восстанавливается, тоже продолжит её проходить.

Ротация секрета JWT

Выполняйте ротацию секрета подписи поэтапно, чтобы существующие сессии оставались действительными:
  1. Сгенерируйте новый секрет. Добавьте его в начало массива session.jwt_secret.
  2. Выполните повторное развёртывание. Новые токены подписываются новым секретом; старые токены по-прежнему проходят проверку.
  3. По истечении ttl_hours с запасом удалите старый секрет и снова выполните развёртывание.
Ротация — также единственный способ принудительно завершить сессии до истечения их срока действия: Bearer-токены проверяются локально по секрету JWT, поэтому отзыв отдельных сессий невозможен. Полная замена секрета без сохранения старого в массиве сразу делает недействительными все активные сессии. Чтобы отключить отдельного пользователя, деактивируйте его учётную запись в вашем IdP; его сессия завершится в течение ttl_hours.

Postgres

Шлюз хранит своё состояние в базе данных PostgreSQL:
  • База данных: сам PostgreSQL, самостоятельно размещённый или управляемый, минимальной версии или новее. Базы данных, которые лишь реализуют протокол Postgres, например распределённые SQL-базы данных, не поддерживаются.
  • Адрес: store.postgres_url принимает один хост. Если база данных состоит из нескольких узлов, используйте адрес перед ними, например эндпоинт вашего управляемого сервиса, балансировщик нагрузки или виртуальный IP-адрес. Задайте льготный период готовности дольше, чем длится переключение на резервный узел.
Шлюз использует пять таблиц данных и таблицу _migrations; все они создаются миграциями при запуске: Цикл с интервалом 30 секунд удаляет строки kv с истёкшим TTL, а ежечасная очистка применяет сроки хранения к таблицам расходов, поэтому ничто не растёт неограниченно. Если лимиты расходов не настроены, запись ведётся только в kv. Шлюз сам применяет миграции своей схемы при запуске и при каждом обновлении, поэтому его роли в базе данных нужны права на создание и изменение таблиц. Выделите для шлюза отдельную базу данных или схему, чтобы сузить эти права. При использовании лимитов расходов потеря базы данных означает потерю учёта расходов и лимитов, а не только повторный вход разработчиков, поэтому регулярно делайте резервные копии. Чтобы немедленно удалить данные ушедшего разработчика, не дожидаясь истечения срока хранения, выполните напрямую DELETE FROM principal_emails WHERE principal = '<sub>'; это удаляет единственную таблицу, содержащую его адрес электронной почты, имя и группы. Строки spend и admin_audit ссылаются только на псевдонимный OIDC sub.

Определение размера пула соединений

Каждая реплика открывает до store.max_connections соединений с Postgres, по умолчанию пять. Следите, чтобы произведение числа реплик на store.max_connections не превышало число соединений, оставшихся в базе данных для шлюза:
  • Реплики: учитывайте максимальное число одновременно работающих. Начните с максимума автомасштабирования или с числа реплик, если автомасштабирование не используется, и добавьте дополнительные реплики, которые поэтапное обновление запускает до остановки старых. В Amazon ECS с настройками по умолчанию и в Cloud Run их может быть столько же.
  • Оставшиеся соединения: возьмите значение max_connections базы данных, затем вычтите то, что резервирует база данных, и то, что удерживают другие клиенты. PostgreSQL резервирует superuser_reserved_connections, по умолчанию три. Управляемый сервис может резервировать больше, поэтому сверьтесь с его документацией.
Например, возьмём максимум автомасштабирования шесть, поэтапные обновления, запускающие не более двух дополнительных реплик, и пул по умолчанию размером пять. Это требует (6 + 2) × 5 = 40 соединений. У базы данных с max_connections равным 50 и двумя соединениями, удерживаемыми другими клиентами, остаётся 50 − 3 − 2 = 45, поэтому итоговое число укладывается. Если итоговое число не укладывается, измените одно из следующего:
  • База данных: увеличьте её max_connections
  • Реплики: запускайте меньше реплик или настройте оркестратор на запуск меньшего числа дополнительных реплик при поэтапном обновлении
  • Пул: уменьшите store.max_connections, но при включённых лимитах расходов сохраняйте его достаточным для нагрузки каждой реплики. Иначе проверки расходов могут завершаться по таймауту в ожидании соединения, а шлюз будет записывать в лог spend check failed: spend precheck timed out.

Обновления

Реплики не хранят состояния, поэтому поэтапный перезапуск не приводит к потере состояния шлюза. Шлюз выполняет миграции схемы при запуске, а значит, развёртывание нового бинарного файла само мигрирует базу данных. Одновременно работающие реплики упорядочиваются с помощью рекомендательной блокировки Postgres, поэтому каждую миграцию применяет только одна из них. Когда ваш оркестратор останавливает реплику сигналом SIGTERM, например при поэтапном перезапуске или уменьшении масштаба, шлюз перестаёт принимать новые соединения и позволяет уже выполняющимся запросам и потокам завершиться перед выходом. Он ждёт до 25 секунд — это называется окном завершения (drain window), — а затем закрывает всё, что ещё открыто. Сигнал SIGINT, например Ctrl+C в терминале, запускает такое же завершение, а второй сигнал во время завершения закрывает открытые запросы и немедленно завершает работу. Завершение с ожиданием требует шлюза v2.1.274 или новее. Длинная генерация может передаваться потоком в течение нескольких минут. В Kubernetes и Amazon ECS увеличьте одновременно оба параметра, чтобы дать таким потокам больше времени:
  • Окно завершения: задайте переменную окружения CLAUDE_GATEWAY_DRAIN_TIMEOUT_MS в контейнере шлюза положительным целым числом миллисекунд, например 120000. Шлюз игнорирует значение в любой другой форме, например 120s, и сохраняет значение по умолчанию 25 секунд
  • Льготный период вашего оркестратора: terminationGracePeriodSeconds в Kubernetes или stopTimeout в Amazon ECS
На обеих платформах льготный период по умолчанию составляет 30 секунд. Держите его как минимум на 5 секунд длиннее окна завершения, иначе оркестратор принудительно завершит шлюз до окончания завершения. В Kubernetes также прибавьте длительность любого хука preStop, поскольку отсчёт льготного периода начинается до запуска хука, а не в момент получения шлюзом SIGTERM. Ваша платформа также может ограничивать длительность завершения:
  • Amazon ECS на Fargate: stopTimeout допускает не более 120 секунд
  • Cloud Run: останавливает экземпляр через 10 секунд после SIGTERM, поэтому открытые потоки получают там не более 10 секунд независимо от окна завершения
Если окно завершения заканчивается, а запросы всё ещё открыты, шлюз записывает в лог предупреждение, содержащее drain window over after, подсчитывает прерванные запросы и называет обе настройки, которые следует увеличить. Миграции только добавляются, поэтому откат к предыдущему бинарному файлу, знающему меньше миграций, безопасен; он игнорирует лишние строки. При откате YAML также повторно проверяется по схеме более старого бинарного файла, поэтому конфигурация, использующая ключ, появившийся в более новом выпуске, не позволит запуститься старой версии. Удалите новый ключ перед откатом.
Если удалить у вышестоящего сервера только ключ groups, он станет доступен всем разработчикам. См. что удалить перед откатом.
Поскольку вы закрепляете версию шлюза в собственном образе, исправления из новых выпусков Claude Code, включая исправления безопасности, попадают в ваше развёртывание только после того, как вы обновите закреплённую версию и выполните повторное развёртывание. Включите шлюз в тот же график установки обновлений, который вы используете для других сервисов, хранящих производственные учётные данные.

Безопасность

Этот раздел отвечает на вопросы, которые задает проверка безопасности: какие данные проходят через шлюз и куда они идут, какие атаки защищает дизайн и какие ответы принадлежат в опроснике соответствия.

Поток данных

Краткое резюме модели угроз

Шлюз находится внутри периметра вашей сети, но отдельные ноутбуки разработчиков не рассматриваются как доверенные. Дизайн учитывает это тремя способами:
  • Разработчики держат краткосрочные JWT вместо сырых ключей upstream. Ветвь CLI-к-шлюзу использует грант устройства RFC 8628, и обмен авторизацией шлюза с IdP запускает PKCE в конфигурации по умолчанию, поэтому перехваченный код авторизации IdP бесполезен.
  • Страница проверки устройства применяет same-origin POST и ограничение скорости для каждого IP согласно RFC 8628 §5.1. См. Сопротивление brute-force пользовательского кода.
  • Исходящие запросы шлюза к вашему IdP, вашим сборщикам OTLP и provider: anthropic upstreams проходят через защиту от подделки запроса на стороне сервера (SSRF), которая разрешает DNS, блокирует link-local и адреса облачных метаданных плюс loopback по умолчанию и закрепляет соединение на разрешенный IP, поэтому управляемые оператором URL не могут быть перенаправлены на конечные точки облачных метаданных. Диапазоны приватных RFC 1918 намеренно разрешены, потому что IdP и сборщики OTLP обычно живут на приватных IP. Для других поставщиков шлюз отказывает в base_url, который называет один из этих адресов или имя хоста метаданных при загрузке конфигурации, и SDK поставщика затем подключается без проверки DNS. Если вы включите только прокси выход, эта проверка адреса переходит к вашему forward proxy: шлюз передает ему имена хостов и список разрешений прокси должен отказать этим назначениям. Установите CLAUDE_GATEWAY_ALLOW_LOOPBACK=1 в окружении шлюза только когда что-то, что шлюз должен достичь, легитимно живет на loopback, такое как локальная разработка IdP или сборщик OTLP sidecar на localhost. Переменная ослабляет блокировку loopback для каждого настроенного оператором URL и также пропускает предупреждение при загрузке, которое проверяет, может ли pod достичь конечной точки облачных метаданных, поэтому предпочитайте давать сборщику его собственный внутренний адрес.
Если вы добавляете свои собственные элементы управления выходом, шлюз должен достичь сервера метаданных всякий раз, когда он использует учетные данные метаданных экземпляра, такие как workload identity. Две угрозы выходят за рамки, потому что это ваша инфраструктура для защиты:
  • Скомпрометированный хост шлюза: хост как содержит upstream учетные данные, так и распределяет управляемые параметры каждому подключенному разработчику, поэтому контроль над конфигурацией шлюза сравним с контролем над вашим MDM. Диалог одобрения CLI для параметров, способных к shell, ограничивает молчаливые изменения, но не заменяет безопасность хоста.
  • Вредоносный поставщик OIDC: поставщик подписывает id_tokens, которым шлюз доверяет, поэтому он может утверждать любую идентификацию. Проверка и защита вашего IdP — это ваша ответственность.

Сопротивление brute-force пользовательского кода

user_code, который разработчик вводит на странице проверки /device, — это 8 символов, взятых из алфавита из 20 символов, что дает 20⁸ или около 2,56×10¹⁰ комбинаций, и он истекает через 10 минут. Шлюз применяет ограничения скорости для каждого IP на конечных точках грантов устройства, настраиваемые через rate_limits. Поднимите лимиты, если много разработчиков входят с одного общего корпоративного NAT адреса. Крупные развертывания показывает, как их размер. Лимиты применяются только к потоку входа, а не к inference.

Позиция соответствия

  • Резидентность данных: собственная плоскость данных шлюза не отправляет ничего Anthropic, если только API Anthropic не является настроенным upstream; когда это так, ваше существующее соглашение об обработке данных применяется к пути inference. Телеметрия, аудит, идентификация и параметры идут только к назначениям, которые вы настраиваете.
  • Трафик хост-процесса: хост-процесс — это Claude Code CLI. claude gateway работает под теми же правилами третьих сторон, что и развертывания Amazon Bedrock и Google Cloud’s Agent Platform, и не отправляет ничего Anthropic. До v2.1.227 хост-процесс отправлял телеметрию запуска, такую как версия продукта и платформа, которую установка CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 в окружении контейнера отключала. Эти выпуски также отправляли один запрос HEAD при загрузке, без тела или учетных данных, на /api/hello на https://api.anthropic.com, или на ANTHROPIC_BASE_URL когда окружение установило его, если только окружение также не установило переменную прокси, такую как HTTPS_PROXY или сертификат клиента mTLS. Они игнорировали ответ, поэтому блокировка этого запроса на брандмауэре выхода не влияла на шлюз.
  • Аналитика клиента: CLI отключает свою собственную аналитику использования и отчеты об ошибках при входе в шлюз. До первого входа CLI все еще отправляет события запуска Anthropic, включая на машинах, чьи управляемые параметры принуждают вход в шлюз. Чтобы отключить и их, доставьте DISABLE_TELEMETRY в тех же управляемых параметрах на стороне клиента, которые принуждают вход в шлюз.
  • Отчеты об ошибках: CLI отключает отчеты об ошибках всякий раз, когда его запросы модели идут на любую конечную точку, отличную от первоклассного API Anthropic, такую как Amazon Bedrock или пользовательский ANTHROPIC_BASE_URL.
  • Машины клиентов: CLI разработчиков все еще отправляют проверки имени хоста WebFetch и проверки версии Anthropic, если не установлены CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 и skipWebFetchPreflight: true. У запросов к маркетплейсам плагинов есть собственные способы отключения. См. использование данных.
  • Рейтинги опроса: при входе в шлюз CLI отключает загрузку рейтингов, привязанную к Anthropic, вместе с потоками аналитики, поэтому он не отправляет рейтинги Anthropic.
  • Обмен транскриптом: выбор Yes на подсказке обмена транскриптом опроса записывает локальный файл в ~/.claude/feedback-bundles/ вместо загрузки Anthropic.
  • Обновления клиента: проверки обновлений отделены от трафика шлюза. Закрепите версии через вашу собственную дистрибуцию и установите DISABLE_UPDATES, если ноутбуки не должны получать выпуски. DISABLE_AUTOUPDATER останавливает только фоновые обновления, в то время как claude update все еще работает.
  • TLS: обслуживайте public_url по HTTPS в production, либо из собственного слушателя шлюза через listen.tls, либо из TLS-завершающего ingress перед простыми HTTP репликами, с установленным listen.public_url в обоих случаях. Шлюз не отказывает простой HTTP. IdP должен обслуживать HTTPS в production, и Postgres поддерживает ?sslmode=require. Установите Strict-Transport-Security на вашем ingress.
  • Раскрытие уязвимостей: следуйте Отчету о проблемах безопасности

Запросы к маркетплейсам плагинов

Claude Code загружает маркетплейсы плагинов напрямую с машины каждого разработчика, а не через шлюз. Список хостов приведён в разделе Требования к сетевому доступу. Когда разработчик впервые запускает интерактивную сессию в терминале, Claude Code регистрирует официальный маркетплейс claude-plugins-official. Он загружает каталог с downloads.claude.ai, а если это не удаётся, клонирует его с github.com. Последующие обновления описаны в разделе Какие маркетплейсы и плагины обновляются автоматически. CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 не останавливает первую регистрацию. Её останавливает любая из этих управляемых настроек:
  • Список маркетплейсов: список разрешённых маркетплейсов strictKnownMarketplaces, в который этот маркетплейс не входит, или запись blockedMarketplaces, которая его называет
  • Переменная окружения: CLAUDE_CODE_DISABLE_OFFICIAL_MARKETPLACE_AUTOINSTALL со значением "1" в управляемом блоке env
Первая регистрация может выполниться до того, как разработчик войдёт в шлюз, когда политика шлюза ещё не получена. Чтобы охватить этот первый запуск, доставьте выбранную настройку в управляемых настройках на стороне клиента, а также в блоке cli или code политики шлюза.

Устранение неполадок

Для вопросов и обратной связи используйте поддержку Claude Code или откройте issue в репозитории Claude Code на GitHub. Вы также можете связаться с командой, обслуживающей ваш аккаунт в Anthropic. При сообщении о проблеме включите:
  • Проблема шлюза: stderr шлюза для соответствующего окна, ваш gateway.yaml с редактированными секретами, версию шлюза, показанную на целевой странице в / и в заголовке ответа x-cc-gateway-version на /managed/settings, и что недавно изменилось
  • Проблема входа: разработчик запускает claude --debug-file ./claude-debug.txt, воспроизводит и отправляет этот файл плюс журнал аудита шлюза для того же окна
  • Проблема inference: запрошенная модель, настроенные upstreams и журнал аудита шлюза для запроса, который записывает, какой upstream обслужил его и статус ответа
stderr шлюза включает поток событий аудита, журнал аудита записывает идентификаторы разработчиков, а файл отладки записывает выходные данные хуков и MCP-серверов с машины разработчика. Проверьте и удалите эту информацию перед публикацией в общедоступную проблему. Сообщение Cloud gateway sign-in was not completed называет имя хоста шлюза. Когда у Claude Code есть и закреплённый отпечаток, и представленный, сообщение также показывает первые 16 символов каждого. Если Claude Code сообщает couldn't load your organization's managed settings после входа в шлюз, Claude Code называет причину, перезапускается на месте и возобновляет диалог. Если Claude Code не может перезапуститься, например в фоновой сессии, Claude Code завершает сессию и сохраняет вход.

Слишком большие заголовки запросов после входа

Запросы разработчика могут завершаться ошибкой 431 после входа, если разработчик состоит во многих группах IdP. Шлюз отвечает 431, когда заголовки запроса в сумме превышают 256 KiB или значение limits.max_request_header_bytes, если вы его задали. Для таких запросов он не записывает ни строки в лог, ни события аудита. Версии шлюза до v2.1.284 отвечают 431 при превышении 16 KiB. Начните с первого из следующих пунктов, который применим к вашему шлюзу:
  • Шлюз старше v2.1.284: обновите шлюз
  • Задан limits.max_request_header_bytes: увеличьте значение или удалите ключ
  • Ни то, ни другое не применимо, или 431 продолжает возникать после этого: сделайте так, чтобы ваш IdP выдавал меньше групп. В разделе Identity provider setup описано, как Okta, Microsoft Entra ID и Google Workspace передают группы
Сокращая утверждение groups, сохраните группы, указанные в следующих настройках, которые определяют доступ разработчика, применяемую к нему политику, upstream и лимиты расходов:
  • oidc.allowed_groups: определяет, кто может войти
  • admin.admin_groups: определяет, кто может вызывать admin API со своей сессией шлюза
  • match.groups в managed.policies: определяет, какая политика применяется к разработчику
  • groups у upstream: определяет, какие upstream обслуживают разработчика
  • rbac_group лимиты расходов: определяют, какие групповые лимиты применяются к разработчику

Долгое мышление заканчивается таймаутами прокси

Если ваш upstream — provider: anthropic, вместо этого используйте раздел Долгое мышление на upstream Anthropic API: там вы тоже увеличиваете CLAUDE_STREAM_IDLE_TIMEOUT_MS, но время и ошибки отличаются. Если ходы завершаются сбоем после долгого мышления, а ваш прокси записывает в лог один запрос, открытый около 12,5 минуты, затем серию ошибок 504, увеличьте CLAUDE_STREAM_IDLE_TIMEOUT_MS в политике шлюза. Например, при таймауте простоя 240 секунд на прокси серия состоит из 10 запросов, каждый из которых обрывается через 240 секунд.
  • Первый запрос: поток, который доставляет первое событие ответа, message_start, а затем только пинги, пока Claude думает. С настройками по умолчанию Claude Code завершает этот поток примерно через 12,5 минуты.
  • Остальные 10: тот же запрос, отправленный без потоковой передачи, а затем повторно, всего 10 отправок по умолчанию. Они не получают пингов, поэтому медленный ответ упирается в таймаут прокси.
Для этого исправления не нужен более длинный таймаут прокси. Если увеличить только таймаут прокси, запросы без потоковой передачи всё равно будут завершаться сбоем, как только ответ займёт больше собственного времени ожидания Claude Code — 300 секунд по умолчанию.

Подтвердите причину

Попросите разработчика воспроизвести сбой с claude --debug-file ./claude-debug.txt, затем найдите в этом файле следующую строку:
Если ваши разработчики уже установили CLAUDE_CODE_DISABLE_NONSTREAMING_FALLBACK в 1, вы не увидите запросов без потоковой передачи, а ход завершится с API Error: Stream idle timeout - no chunks received. Применяется то же исправление.

Выберите значение

Выберите значение CLAUDE_STREAM_IDLE_TIMEOUT_MS, у которого второй столбец покрывает вашу самую долгую паузу на мышление, или начните с 1800000, если вы её не знаете. Поток может держаться только на пингах примерно на 7,5 минуты дольше, чем это значение: Если upstream зависает, а шлюз продолжает отправлять пинги, ваши разработчики тоже ждут столько же, прежде чем Claude Code откажется от потока. Соединение, которое полностью замолкает, по-прежнему завершается через 5–6 минут, потому что таймаут простоя тела не зависит от этой переменной.

Передайте значение в политике

Добавьте запись env в каждую политику в gateway.yaml, которая уже передаёт настройки Claude Code разработчикам, которых вы хотите охватить. Поместите её под ключ code, cli или settings, который уже есть в этой политике. Чтобы сначала опробовать значение, начните с политики, соответствующей одной группе. О том, как политики сопоставляются и наследуются, см. managed. В этом примере запись добавляется в политику match: {} с ключом cli:
С ключом cli вы охватываете сессии в терминале, расширении IDE и Agent SDK. Для вкладки Code в Claude Desktop см. Выбор cli или code. Перезапустите шлюз, чтобы он прочитал изменённый файл. Затем попросите разработчиков перезапустить Claude Code, чтобы получить CLAUDE_STREAM_IDLE_TIMEOUT_MS.

Долгое мышление на upstream Anthropic API

Если provider: anthropic — единственный upstream модели, а ваш прокси записывает в лог один запрос, открытый около 20 минут, затем ошибки 502 или 504, увеличьте CLAUDE_STREAM_IDLE_TIMEOUT_MS в политике шлюза.
  • Долгий запрос: поток, который доставляет message_start, а затем только пинги, пока Claude думает. С настройками по умолчанию Claude Code завершает его примерно через 20 минут, а после увеличения переменной — позже.
  • Ошибки: запросы, которые Claude Code затем отправляет без потоковой передачи. Каждый из них завершается ошибкой 502 от шлюза или ошибкой 504 от вашего прокси, если таймаут прокси короче времени ожидания шлюза. Это время ожидания — timeouts.upstream_ttfb_ms, и для этого исправления увеличивать его не нужно.
Чтобы подтвердить причину, см. Подтвердите причину. Выберите значение, время которого покрывает вашу самую долгую паузу на мышление: около 20 минут при значении по умолчанию, 30 при 900000 и 45 при 1800000. Затем выполните шаги из раздела Передайте значение в политике.