Valcraven Docs
Getting Started

Environment variables

The handful of variables you need to run Valcraven locally, and where to set them.

This page covers the environment variables you need to get Valcraven running locally, plus the optional ones that switch on individual features. It's the getting-started subset — for the complete list of every variable across the app, deploy, email, AI, and monitoring, see /docs/reference/environment-variables.

Where env vars live

  • apps/web/.env — the app's runtime variables. Copy it from the example to start: cp apps/web/.env.example apps/web/.env. Docker Compose loads this file into the app-dev and realtime-dev containers, and Next.js loads it (along with .env.local) when you run directly with Node. The /configure-sso skill writes OAuth credentials to .env.local.
  • A root-level .env (next to docker-compose.yml) — a few variables are consumed by Docker Compose itself, not the app: TS_AUTHKEY, TS_HOSTNAME, and DEV_PORT for the Tailscale sidecar. Put those here.

.env and .env.local are gitignored — never commit real secrets. .env.example is committed and documents every variable inline.

To run locally

Only one variable is truly required; the rest have working local defaults.

VariableRequiredWhat it does
BETTER_AUTH_SECRETYesSigns auth sessions. Must be 32+ chars — generate with openssl rand -base64 32.
BETTER_AUTH_URLRecommendedBetter Auth's base URL and a trusted origin. Docker Compose defaults it to http://localhost:3013. Set it explicitly (it isn't reliably inferred behind a proxy), and to your tailnet URL for phone QA.
APP_URLRecommendedPublic URL used in emails and Stripe/redirect links. Compose defaults it to http://localhost:3013.
APP_NAMEOptionalDisplay name in the UI and emails. Defaults to Valcraven.
DATABASE_PATHOptionalLocal SQLite file path. Defaults to ./data/valcraven.db; Compose sets the in-container path automatically.
ADMIN_EMAILSOptionalComma-separated emails auto-promoted to admin on signup. Set this to your own email to get an admin account.

That's enough to start the app, sign up, and use the core flows. See the Quickstart for the run commands.

To enable optional features

Each feature stays dormant until you set its variables — the app degrades gracefully when they're absent.

FeatureVariablesNotes
OAuth sign-inGOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET, GITHUB_CLIENT_ID / GITHUB_CLIENT_SECRET, APPLE_CLIENT_ID / APPLE_CLIENT_SECRET, FACEBOOK_CLIENT_ID / FACEBOOK_CLIENT_SECRETSee OAuth setup. Apple is production-only.
AI chatANTHROPIC_API_KEYEnables the Claude (BYOK) tier. Read by the realtime Worker; can also be set at runtime from /admin/ai-models. Without it, chat falls back to an open Workers AI model.
Realtime Worker authAGENTS_INTERNAL_SECRETShared secret for the web app ↔ realtime Worker server-to-server calls. Must match apps/realtime/.dev.vars. Used for live notification push and scheduled wakes.
PaymentsSTRIPE_SECRET_KEY, STRIPE_PRICE_ID, STRIPE_WEBHOOK_SECRETStripe checkout, subscriptions, and webhooks.
Voice (TTS)ELEVENLABS_API_KEYOptional text-to-speech for chat. Voice is text-only when unset.
Phone QA (Tailscale)TS_AUTHKEY, TS_HOSTNAME, DEV_PORTSet in the root .env — read by Docker Compose for the Caddy sidecar. See the Quickstart's "Remote dev" section.

Production (Cloudflare Workers)

On Cloudflare Workers, secrets are not read from your local .env — set them with wrangler secret put VAR_NAME, and non-secret vars go in the [vars] block of apps/web/wrangler.toml. Email uses the Workers send_email binding (no key needed). See Secrets & env on Cloudflare and Deploy to Cloudflare Workers.

On this page