spacehub

surshar / claude-code

Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.

Built by Anthropic · github.com/anthropics

claude-code / examples / gateway / gcp / gateway.yaml.example
155 lines · 9.2 KBRaw
1# gateway.yaml.example — Claude Gateway config template, GCP-shaped (walkthrough §6).
2#
3# Google Workspace IdP + Vertex upstream, following the walkthrough at
4# https://code.claude.com/docs/en/claude-apps-gateway-on-gcp. The active sections
5# below are a strict subset of the full configuration reference at
6# https://code.claude.com/docs/en/claude-apps-gateway; optional keys are included
7# commented-out.
8#
9# USAGE — this is the shippable TEMPLATE. Copy it to gateway.yaml and fill it in:
10# cp gateway.yaml.example gateway.yaml
11# setup.sh and terraform/ read gateway.yaml (your filled-in copy, which is
12# gitignored). It is published as the Secret Manager secret `gateway-config`
13# (§6) and mounted at /etc/claude/gateway.yaml — the container ENTRYPOINT runs
14# `claude gateway --config /etc/claude/gateway.yaml`.
15#
16# Secret expansion: ${ENV_VAR} reads an env var; ${file:/path} reads a mounted file.
17# On Cloud Run, setup.sh injects the JWT / OIDC / Postgres secrets as ENV VARS
18# (Cloud Run can't mount multiple secrets into a single directory), and mounts
19# only gateway.yaml itself as a file at /etc/claude. On GKE you may use file mounts.
20#
21# BEFORE DEPLOY — replace every REPLACE_ME placeholder below (setup.sh refuses to
22# publish the config secret while any remain), and create the referenced secrets:
23# gateway-jwt-secret (setup.sh generates this)
24# gateway-oidc-client-secret (from the Google Cloud Console OAuth client)
25# gateway-postgres-url (setup.sh generates this)
26
27# ── Listener ─────────────────────────────────────────────────────────────────
28listen:
29 host: 0.0.0.0
30 port: 8080 # Cloud Run sets PORT=8080; leave as-is
31 # Required. Fixes the IdP redirect_uri, the OIDC discovery doc, and the
32 # gateway-token issuer so none are derived from the client-controlled Host
33 # header (X-Forwarded-Host/-Proto are likewise never trusted). On Cloud Run
34 # the run.app URL is only assigned on the first deploy, so this starts as a
35 # placeholder for the provisioning-only first pass (login does NOT work until
36 # the real URL is set). After the first deploy, setup.sh prints the run.app
37 # URL: set it here (or your LB hostname) and re-run; setup.sh republishes the
38 # config and redeploys. Register the same host's /oauth/callback on the
39 # Google OAuth client.
40 public_url: https://set-after-first-deploy.invalid
41 # Register this exact redirect URI on the Google OAuth client:
42 # https://<public_url host>/oauth/callback
43 #
44 # On Cloud Run (or behind any L7 LB) every request arrives via Google's front
45 # end, so the gateway sees one peer IP for all developers — set trusted_proxies
46 # so X-Forwarded-For from those proxies is trusted and per-IP rate limiting /
47 # audit IPs record the real client. 169.254.0.0/16 is Cloud Run's fixed
48 # link-local serving range; the proxy-only subnet is the one your internal ALB
49 # uses in this VPC.
50 # trusted_proxies:
51 # - 169.254.0.0/16 # Cloud Run serving proxy (link-local peer)
52 # - <proxy-only-subnet-cidr> # add if fronted by your internal ALB (its proxy-only subnet)
53 #
54 # Alternative — terminate TLS in the gateway itself instead of at a proxy:
55 # tls:
56 # cert: /certs/gateway.crt
57 # key: /certs/gateway.key
58
59# ── Identity provider — Google Workspace ─────────────────────────────────────
60oidc:
61 issuer: https://accounts.google.com
62 client_id: REPLACE_ME # Google OAuth client ID (not secret; from Cloud Console)
63 client_secret: ${OIDC_CLIENT_SECRET}
64 allowed_email_domains: [REPLACE_ME] # e.g. [example.com] — reject id_tokens outside your org
65 # Google ignores the default offline_access scope; these two are what actually
66 # yield refresh tokens (silent renewal + the deprovision leash) from Google.
67 scopes: [openid, profile, email]
68 extra_auth_params: { access_type: offline, prompt: consent }
69 # NOTE: Google id_tokens carry NO groups claim. For group-based RBAC with
70 # Google as IdP, set `google_groups` (below) and the gateway fetches each
71 # user's Workspace groups at login via the Admin SDK Directory API.
72 # Otherwise, use email_domain matching (see managed.policies below).
73 # google_groups:
74 # service_account_json_path: /secrets/google-sa.json # SA with domain-wide delegation on admin.directory.group.readonly
75 # admin_email: admin@example.com # a Workspace admin the SA impersonates
76 # groups_claim: groups # Okta=groups, Entra app roles=roles — NOT Google
77 # ca_cert_pem: ${file:/secrets/idp-ca.pem} # only for an IdP behind a private CA
78
79# ── Sessions ─────────────────────────────────────────────────────────────────
80session:
81 jwt_secret: ${GATEWAY_JWT_SECRET} # >= 32 bytes; openssl rand -base64 32
82 # Google issues refresh tokens (above), so sessions renew silently and this
83 # mainly bounds deprovision latency. 8 is a sane default; lower toward 1 for
84 # tighter revocation. Array form rotates keys: [new, old] (index 0 signs, all verify).
85 ttl_hours: 8
86
87# ── Store (REQUIRED — the gateway refuses to boot without it) ─────────────────
88store:
89 postgres_url: ${GATEWAY_POSTGRES_URL} # private-IP Cloud SQL; built with ?sslmode=require by setup.sh
90
91# ── Upstreams — Vertex AI ────────────────────────────────────────────────────
92upstreams:
93 - provider: vertex
94 region: us-east5 # a region where the Claude models you need are published in Model Garden
95 project_id: REPLACE_ME # your GCP project ID for Vertex access
96 auth: {} # ADC via Cloud Run SA / GKE Workload Identity (preferred — no static keys)
97 # base_url: https://us-east5-aiplatform.p.googleapis.com # Private Service Connect endpoint
98 # Add more upstreams for failover (tried top→bottom on 5xx/timeout/501): a
99 # second region, or an anthropic/bedrock fallback. See
100 # https://code.claude.com/docs/en/claude-apps-gateway.
101
102# ── Telemetry fan-out (OPTIONAL) ─────────────────────────────────────────────
103# The CLI sends OTLP/HTTP to the gateway; the gateway fans out, stamping
104# user.id/user.email/user.groups server-side. On GCP, point at an OpenTelemetry
105# Collector with the googlecloud exporter (-> Cloud Trace / Managed Prometheus).
106# Takes effect after the second pass (once public_url is the real URL, not the
107# placeholder): when forward_to and public_url are both configured the gateway pushes
108# CLAUDE_CODE_ENABLE_TELEMETRY and the OTEL exporter selectors to every client
109# automatically — no per-developer config needed.
110# telemetry:
111# forward_to:
112# - url: https://otel-collector.internal.example.com:4318
113# headers:
114# Authorization: ${file:/secrets/otlp-token}
115# metrics: true # safe aggregate counters (default)
116# logs: false # carries bash commands / tool inputs — opt in deliberately
117# traces: false
118
119# ── RBAC + managed settings (OPTIONAL; first-match-wins, top -> bottom) ───────
120# With Google as IdP, match on email_domain, or on group email addresses
121# (e.g. eng@example.com) once oidc.google_groups is configured above.
122# managed:
123# policies:
124# - match: { email_domain: example.com }
125# cli:
126# availableModels: [claude-opus-4-8, claude-sonnet-4-6, claude-haiku-4-5]
127# permissions: { deny: ["Read(./.env)", "Read(./secrets/**)"] }
128# - match: {} # catch-all floor — keep LAST
129# cli:
130# availableModels: [claude-sonnet-4-6, claude-haiku-4-5]
131
132# ── Admin API (OPTIONAL — enables db-mode runtime config + spend caps) ───────
133# admin_groups needs a groups claim — with Google as IdP, set
134# oidc.google_groups (above) so Workspace group email addresses populate the
135# claim, or use the bootstrap keys below instead. Named keys for
136# attribution in the audit log; 32-char minimum on key values. On Cloud Run add
137# these as env vars to --set-secrets (or terraform env value_source blocks),
138# same as the JWT/OIDC/Postgres secrets above; on GKE you may use ${file:...}.
139# admin:
140# write_keys:
141# - id: terraform
142# key: ${GATEWAY_ADMIN_WRITE_KEY}
143# read_keys:
144# - id: reporting
145# key: ${GATEWAY_ADMIN_READ_KEY}
146# # admin_groups: [platform-finops@example.com] # group emails via oidc.google_groups, or any groups-capable IdP
147
148# ── Model catalog (OPTIONAL) ─────────────────────────────────────────────────
149# Default true: every built-in Claude model is exposed and auto-translated per
150# upstream. Set false + a models: list to pin IDs (e.g. provisioned throughput).
151# auto_include_builtin_models: true
152# models:
153# - id: claude-opus-4-8
154# label: Claude Opus 4.8
155# upstream_model: { vertex: claude-opus-4-8 }