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.

Variable Description Example
BETTER_AUTH_SECRET Encryption 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_URL Turso/libSQL connection URL libsql://your-db.turso.io
JWT_ISSUER JWT issuer URL (must match your deployment URL) https://auth.example.com
JWT_AUDIENCE Comma-separated JWT audience values payload-admin,my-app,my-spa
PAYLOAD_CLIENT_ID Confidential client ID my-confidential-client
PAYLOAD_CLIENT_SECRET Confidential client secret (also used as the signup restriction secret) secret-at-least-32-chars
PAYLOAD_REDIRECT_URI Confidential client redirect URL https://myapp.com/auth/callback
PAYLOAD_SPA_CLIENT_ID Public PKCE client ID my-spa-client
PAYLOAD_SPA_REDIRECT_URIS Comma-separated SPA redirect URLs https://spa.example.com/callback
CRON_SECRET Secret for internal cron endpoints (JWKS rotation, trace cleanup) cron-secret-value
QSTASH_TOKEN Upstash QStash token for the webhook queue eyJ...
QSTASH_CURRENT_SIGNING_KEY QStash signature verification key sig_xxxxx
UPSTASH_REDIS_REST_URL Upstash Redis URL for idempotency/rate limiting https://your-redis.upstash.io
UPSTASH_REDIS_REST_TOKEN Upstash Redis auth token AxxxxxxxxxxxxxxxxxxxQ==
PAYLOAD_WEBHOOK_URL Default outbound webhook destination https://myapp.com/api/webhooks
PAYLOAD_OUTBOUND_WEBHOOK_SECRET HMAC secret for outbound webhooks (min 32 chars) outbound-webhook-secret-32chars
PAYLOAD_INBOUND_WEBHOOK_SECRET HMAC secret for inbound webhooks (min 32 chars) inbound-webhook-secret-32chars
RESEND_API_KEY Resend API key for sending emails re_xxxxxxxxxxxxx
EMAIL_FROM Sender email address noreply@example.com
EMAIL_FROM_NAME Sender display name Auther

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

Variable Description Default
BETTER_AUTH_DATABASE_AUTH_TOKEN Turso auth token (none)
PRODUCTION_URL Production deployment URL Falls back to NEXT_PUBLIC_APP_URL
NEXT_PUBLIC_APP_URL Current deployment URL (used for CORS, trusted origins) http://localhost:3000
PAYLOAD_SPA_LOGOUT_URIS Comma-separated post-logout redirect URLs (none)
PAYLOAD_PREVIEW_ORIGIN_PATTERNS Wildcard patterns for preview deployments (e.g. https://*.vercel.app) (none)
QSTASH_URL QStash API URL (for local dev) Default QStash cloud URL
QSTASH_NEXT_SIGNING_KEY Next QStash signing key (for key rotation) (none)
QUEUE_TARGET_BASE_URL Base URL for queue worker targets (for Docker networking) (none)
VERCEL_URL Auto-set by Vercel deployments (none)
SKIP_EMAIL_SENDING Set 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.

Service Port Purpose
app (Next.js) 3000 The Auther application
libsql 8080 Turso-compatible SQLite database
redis 6379 Upstash Redis replacement
qstash 8081 Upstash QStash local server
mailhog 8025 (UI), 1025 (SMTP) Email testing (catches all outbound email)
webhook-tester 8082 Webhook 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