Skip to content

Configuration & Local Dev

Two practical things you need before running Auther: which environment variables it reads, and how to bring up a working instance locally. This page is the lookup table for both — keep it open while you configure a deployment or wire up the dev stack.

Auther is configured entirely through environment variables, validated at startup by a Zod schema in env.ts. The required set covers the auth secret, the database, JWT issuance, the reference Payload clients, the cron secret, the QStash and Redis backends, the webhook secrets, and email delivery. Anything missing here fails the boot, so treat this as the minimum viable config.

VariableDescriptionExample
BETTER_AUTH_SECRETEncryption key (min 32 chars). Used for session encryption, JWKS private-key encryption, and webhook-secret encryption.a-very-long-random-secret-string-here
BETTER_AUTH_DATABASE_URLTurso/libSQL connection URLlibsql://your-db.turso.io
JWT_ISSUERJWT issuer URL (must match your deployment URL)https://auth.example.com
JWT_AUDIENCEComma-separated JWT audience valuespayload-admin,my-app,my-spa
PAYLOAD_CLIENT_IDConfidential client IDmy-confidential-client
PAYLOAD_CLIENT_SECRETConfidential client secret (also used as the signup restriction secret)secret-at-least-32-chars
PAYLOAD_REDIRECT_URIConfidential client redirect URLhttps://myapp.com/auth/callback
PAYLOAD_SPA_CLIENT_IDPublic PKCE client IDmy-spa-client
PAYLOAD_SPA_REDIRECT_URISComma-separated SPA redirect URLshttps://spa.example.com/callback
CRON_SECRETSecret for internal cron endpoints (JWKS rotation, trace cleanup)cron-secret-value
QSTASH_TOKENUpstash QStash token for the webhook queueeyJ...
QSTASH_CURRENT_SIGNING_KEYQStash signature verification keysig_xxxxx
UPSTASH_REDIS_REST_URLUpstash Redis URL for idempotency/rate limitinghttps://your-redis.upstash.io
UPSTASH_REDIS_REST_TOKENUpstash Redis auth tokenAxxxxxxxxxxxxxxxxxxxQ==
PAYLOAD_WEBHOOK_URLDefault outbound webhook destinationhttps://myapp.com/api/webhooks
PAYLOAD_OUTBOUND_WEBHOOK_SECRETHMAC secret for outbound webhooks (min 32 chars)outbound-webhook-secret-32chars
PAYLOAD_INBOUND_WEBHOOK_SECRETHMAC secret for inbound webhooks (min 32 chars)inbound-webhook-secret-32chars
RESEND_API_KEYResend API key for sending emailsre_xxxxxxxxxxxxx
EMAIL_FROMSender email addressnoreply@example.com
EMAIL_FROM_NAMESender display nameAuther

These tune behavior or supply values that are only needed in specific environments (local Docker networking, Vercel deployments, preview origins, key rotation).

VariableDescriptionDefault
BETTER_AUTH_DATABASE_AUTH_TOKENTurso auth token(none)
PRODUCTION_URLProduction deployment URLFalls back to NEXT_PUBLIC_APP_URL
NEXT_PUBLIC_APP_URLCurrent deployment URL (used for CORS, trusted origins)http://localhost:3000
PAYLOAD_SPA_LOGOUT_URISComma-separated post-logout redirect URLs(none)
PAYLOAD_PREVIEW_ORIGIN_PATTERNSWildcard patterns for preview deployments (e.g. https://*.vercel.app)(none)
QSTASH_URLQStash API URL (for local dev)Default QStash cloud URL
QSTASH_NEXT_SIGNING_KEYNext QStash signing key (for key rotation)(none)
QUEUE_TARGET_BASE_URLBase URL for queue worker targets (for Docker networking)(none)
VERCEL_URLAuto-set by Vercel deployments(none)
SKIP_EMAIL_SENDINGSet to any value to skip actual email delivery (testing)(none)

You don’t need cloud accounts for Turso, Upstash, or Resend to develop locally. The docker-compose.yml stands up the whole system — including local replacements for each managed dependency — so a fresh checkout runs end to end with one command.

ServicePortPurpose
app (Next.js)3000The Auther application
libsql8080Turso-compatible SQLite database
redis6379Upstash Redis replacement
qstash8081Upstash QStash local server
mailhog8025 (UI), 1025 (SMTP)Email testing (catches all outbound email)
webhook-tester8082Webhook request inspector
  1. Bring the stack up. Development mode hot-reloads the app; production mode builds the app image first.

    Terminal window
    pnpm d:up-dev
  2. Wait for the supporting services to initialize. On startup, the db-migrate service runs the Drizzle schema push, and the db-seed service creates a test admin user and seeds OAuth clients for testing.

  3. Sign in at http://localhost:3000 with the seeded admin credentials:

    email: admin@test.local
    password: admin123
  4. Inspect captured email in the Mailhog UI at http://localhost:8025, and watch outbound webhook deliveries in the webhook-tester on port 8082.

When you’d rather run the Next.js server directly against your own services, these pnpm scripts cover the common tasks. Local dev outside Docker requires a populated .env.local.

Terminal window
pnpm dev # Local dev server (requires .env.local)
pnpm db:push # Push schema changes to the database
pnpm db:generate # Generate Drizzle migrations
pnpm user:create # Create a user via CLI
pnpm auth:test # Test the auth flow
pnpm clients:seed # Seed OAuth clients
pnpm lint # ESLint + TypeScript type checking