Auth, tokens & the admin API

Two separate doors: a per-deployment sign-in gate on the data plane, and a two-tier gate on the admin API. App-tokens open both, each within their scope.

The sign-in gate

Any deployment can put a gate in front of everything it serves. It runs in the proxy, before a backend is chosen, so the application behind it needs to know nothing about it:

"auth": {
  "provider": ["google", "app-token"],
  "client_id": "…apps.googleusercontent.com",
  "client_secret": { "secret": "google", "key": "client_secret" },
  "allowed_domains": ["example.com"],
  "public_paths": ["/healthz", "/api/webhook"],
  "forward_identity": true
}
The gate runs before the cold-start wait. An unauthenticated request never boots a VM. An API client hitting a Google-only gate gets an immediate 401 {"error":"authentication required"} from app-lb itself — the request never reaches the deployment and never wakes it. If a scale-from-zero deployment is "not waking up" for programmatic callers, check the gate's provider list and public_paths first.

App-tokens

The credential a program carries. Minted through the admin API (or serverctl token mint), scoped, optionally expiring, revocable instantly. The shape is applb_<id>_<secret> — greppable on purpose, and only the secret's SHA-256 is stored, so the token file is not a fleet compromise and there is no "reveal" endpoint.

Scope axisValuesGoverns
adminnone / view / admin What the token may do on the admin API. none still passes data-plane gates — the shape for a token handed to an application.
deploymentsids, or ["*"] Which deployments it may touch — both the per-deployment admin routes (exec, shell, scale, delete) and data-plane gates.
namespaceone namespace A wall around everything: see Namespaces.
# a token for CI to reach one deployment's data plane, expiring in a week
serverctl token mint ci-secrets -d secret-service --expires-in 168 -q

# a fleet-wide operator token
serverctl token mint ops --admin admin --all-deployments

serverctl token set re-scopes a token without changing its secret; serverctl token revoke takes effect on the next request.

The admin API's two tiers

Unset, the admin listener is open (it binds loopback). Setting APP_LB_DASHBOARD_PASSWORD gates the view tier — the directory, /metrics, the dashboard, /security, /feeds. Setting APP_LB_ADMIN_AUTH=1 extends the gate to the CRUD tier — everything that changes state or reads specs.

Scoped tokens are narrowed rather than refused where that makes sense: a token scoped to one deployment sees a directory, /metrics and /security filtered to that deployment, and is refused fleet-wide routes (creating deployments, reading secrets, minting tokens) outright — a token cannot widen itself.

Block rules and detection

Operators can arm block rules (by client IP, host, path, method, user-agent) that the proxy enforces with an anonymous 403 — the refusal deliberately does not say which property matched. A built-in analyzer (on unless APP_LB_SIEM=0) watches access and auth failures, folds repeats, and raises findings on GET /security with suggested rules.