Environment Variables
Environment Variables — Master Reference
Every environment variable used across all services, its purpose, and where it should be stored.
Variable Reference
| Variable | Service(s) | Secret? | Storage Location |
|---|---|---|---|
DATABASE_URL | web-app, api, worker | Yes | GCP Secret Manager (Neon connection string) |
BETTER_AUTH_SECRET | web-app | Yes | GCP Secret Manager |
BETTER_AUTH_JWKS_URL | api, worker | No | Cloud Run env / GitHub Actions variable |
VITE_API_URL | web-app | No | Docker build arg (inlined at build time) |
NEXT_PUBLIC_API_URL | marketing | No | Docker build arg (inlined at build time) |
EXPO_PUBLIC_API_URL | ios | No | Build-time public config |
GCP_PROJECT_ID | api, worker, infra | No | GitHub Actions variable |
BIGQUERY_DATASET | worker | No | GitHub Actions variable |
WELLSKY_CLIENT_ID | worker | Yes | GCP Secret Manager |
WELLSKY_CLIENT_SECRET | worker | Yes | GCP Secret Manager |
OTEL_EXPORTER_OTLP_ENDPOINT | api, worker | No | GitHub Actions variable / Cloud Run env |
RESTATE_* (runtime endpoint + identity/signing keys) | worker | Yes | GCP Secret Manager |
Auth is Better Auth on the applications-UI server (the Vite + TanStack ui/web-app), storing its tables in Neon. The app server needs DATABASE_URL + BETTER_AUTH_SECRET; the FastAPI backend validates the issued JWTs via BETTER_AUTH_JWKS_URL. There are no Supabase Auth keys. See Frontend and Backend.
Durable-execution engine: Restate Cloud (managed). The Restate Cloud environment endpoint plus its request-signing / identity keys (RESTATE_*) live in GCP Secret Manager. PHI never travels as plaintext through Restate Cloud — it is encrypted at the serde boundary inside the handler (GCP-KMS-backed encrypting Serde), so the journal and virtual-object state hold ciphertext only (an encrypted conduit, no BAA required). Never commit secrets. See Backend.
PR Environment Secrets
Additional secrets required for ephemeral PR preview environments:
| Variable | Secret? | Storage Location |
|---|---|---|
GCP_PROJECT_ID | No | GitHub Actions variable |
GCP_REGION | No | GitHub Actions variable |
NEON_API_KEY | Yes | GitHub Actions secret |
NEON_PROJECT_ID | No | GitHub Actions variable |
GCP authentication uses Workload Identity Federation — no GCP_CREDENTIALS JSON key secret is needed. The per-PR Neon branch DATABASE_URL and branch-scoped Better Auth config are minted in CI and destroyed with the branch. See PR Preview Environments.
Storage Locations
Cloud Run Environment Variables
Used for the web-app, marketing, api, and worker service configuration. Non-secret values are set directly as Cloud Run env vars; secrets are stored in GCP Secret Manager and mounted at deploy time. Note: VITE_* / NEXT_PUBLIC_* / EXPO_PUBLIC_* variables used in client-side code are inlined at build time and must be passed as Docker build arguments — they cannot be changed via runtime Cloud Run env vars.
Pulumi ESC + GCP Secret Manager
Pulumi ESC is the declarative source of truth for every environment's config + secrets; it materializes them into GCP Secret Manager, the IAM-scoped runtime store (inside the Google BAA). Cloud Run mounts secrets from Secret Manager at deploy time. There is no database-resident vault — Neon does not support supabase_vault / pgsodium, and a DB-resident secret would be copied into every preview branch. See Secret Management.
GitHub Actions Variables / Secrets
- Variables (non-secret): Used in CI/CD workflows for configuration like project IDs, regions, and dataset names.
- Secrets: Used for deployment credentials (
NEON_API_KEY) and service connection strings minted per-PR.
.env.example Files
Each service must have a .env.example file listing all required variables with placeholder values:
| Location | Variables |
|---|---|
ui/web-app/.env.example | DATABASE_URL, BETTER_AUTH_SECRET, VITE_API_URL |
ui/marketing/.env.example | NEXT_PUBLIC_API_URL |
backend/api/.env.example | DATABASE_URL, BETTER_AUTH_JWKS_URL |
backend/worker/.env.example | DATABASE_URL, BETTER_AUTH_JWKS_URL, BIGQUERY_DATASET, WELLSKY_CLIENT_ID, WELLSKY_CLIENT_SECRET, OTEL_EXPORTER_OTLP_ENDPOINT, RESTATE_* (runtime endpoint + identity keys) |
Root .env.example | Dev-time defaults for process-compose |
Security Rules
- Never commit secrets to the repository. Use
.gitignoreto exclude.envfiles. - Never log secret values. The
pydantic-settingsBaseSettingsclass prevents accidental logging. Never logDATABASE_URL. - Use the
VITE_/NEXT_PUBLIC_/EXPO_PUBLIC_prefixes only for values safe to expose in client-side JavaScript. - Rotate secrets regularly and audit access logs. Add a new Secret Manager version, then destroy the old one after cutover.
See HIPAA Compliance for additional security requirements.