> ## Documentation Index
> Fetch the complete documentation index at: https://langwatch.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Post-install checklist

> What to do after `helm install` to get personal keys, the AI Gateway, and the unified `langwatch` CLI working end-to-end.

This page is the operational counterpart to the post-install
`NOTES.txt` that `helm install langwatch ...` prints, extra depth on
each step plus the `kubectl` probes self-hosters typically run to
verify the install.

If you haven't installed yet, start with [helm](./helm) and come back
here once the chart deploys cleanly.

## 1. Reach the UI as the bootstrap admin

```bash theme={null}
# Default service name (release name = `langwatch`)
kubectl -n langwatch port-forward svc/langwatch-app 5560:5560
open http://localhost:5560
```

Sign in with the email address that should own the bootstrap
organization. SSO (SAML, OIDC) can be configured later, for the
first sign-in any local-credential or Auth0 path is fine.

If you set `ingress.enabled=true` and your DNS is pointing at the
controller, replace the port-forward with the public URL.

## 2. Add at least one Model Provider credential

Personal keys reference a `RoutingPolicy` whose `modelProviderIds[]`
points at one or more `ModelProvider` rows. Without at least one
provider configured, no key, personal or service, can route traffic.

In the UI: **Settings → Model Providers → Add provider**.

Behind the scenes the chart materialises the encryption pepper
needed to seal the credential at rest:

```bash theme={null}
kubectl -n langwatch get secret langwatch-app-secrets \
  -o jsonpath='{.data.LW_VK_PEPPER}' | base64 -d
```

If the pepper rotates between deployments, previously-stored
credentials become unreadable. Treat it like a database root
password, bind it to your existing secret-management workflow.

## 3. Publish a default RoutingPolicy

In the UI: **Settings → Routing Policies → New policy**, scope =
`organization`. Mark it default. Pick the providers from step 2 in
your preferred fallback order. Optionally add a model allowlist —
e.g. `claude-3-5-*` and `gpt-4o*`, to keep personal keys out of the
expensive frontier models.

When a member runs `langwatch login --device`, their personal VK
gets bound to this policy automatically. They never see provider
plumbing.

If you skip this step, the CLI surfaces a clear error
(`policy not configured`) instead of silently routing to nothing.

## 4. Verify the AI Gateway is healthy

```bash theme={null}
# In-cluster probe via the Service
kubectl -n langwatch run curl --rm -it --image=curlimages/curl --restart=Never \
  -- curl -sS http://langwatch-gateway/healthz
# → {"status":"ok","version":"...", "uptime_s":...}

# Pod-level look at warmup + provider-cache
kubectl -n langwatch logs -l app.kubernetes.io/name=langwatch-gateway --tail 50
```

If the gateway can't reach the control plane, it logs
`auth_upstream_unavailable` and returns 503 for every VK call. The
fix is almost always `gateway.controlPlane.baseUrl`, defaults to
`http://langwatch-app:5560` on the assumption your release name is
`langwatch`. Adjust on a different release name or split-domain.

## 5. Expose the gateway and set its public URL

The gateway needs its **own** externally-reachable endpoint, separate
from the app. Your LLM clients (Claude Code, Codex, Cursor) hit the
gateway; the browser hits the app. So you provision two ingresses /
load balancers: one for `app.your-corp.com` and one for
`gateway.your-corp.com`.

Then tell the control plane where the gateway lives, so it can hand
that URL to CLI users at login. With the Helm chart, set the gateway's
own host and the chart derives the rest:

```yaml theme={null}
gateway:
  ingress:
    enabled: true
    host: gateway.your-corp.com   # your domain, not the SaaS default
  # publicUrl: https://gateway.your-corp.com   # or set explicitly
```

This populates `LW_GATEWAY_PUBLIC_URL` on the `langwatch-app`
container. **Without it, the control plane returns
`http://localhost:5563` to CLI users** and every `langwatch claude` /
`langwatch codex` call from a developer laptop fails with
`Cannot reach AI Gateway ... fetch failed`. Do NOT reuse
`LW_GATEWAY_BASE_URL` for this — that variable is the internal
control-plane URL the Go gateway dials back on, a different direction.

Verify it landed:

```bash theme={null}
kubectl -n langwatch get deploy langwatch-app -o jsonpath='{.spec.template.spec.containers[0].env[?(@.name=="LW_GATEWAY_PUBLIC_URL")].value}'
# → https://gateway.your-corp.com
```

## What to read next

* [Helm chart](./helm): chart structure, secrets, upgrade procedure.
* [Configuration](./config): env vars and tuning knobs.
* [Health checks](./health-checks): readiness, liveness wiring.
* [Scaling](./scaling): HPA, replicas, custom Prometheus metrics.

For the admin-side walkthrough of features (RoutingPolicies,
budgets, off-boarding policy), see
[admin setup](../governance/admin-setup) under the governance
section, same content, audience is the admin not the operator.
