Skip to main content

Seeding

seed.ts runs as a standalone script. It creates the initial platform admin user.

What it does

  1. Calls better-auth's internal auth.api.signUpEmail() (no HTTP, in-process).
  2. Promotes the resulting user to role = 'platform_admin'.
  3. Logs the credentials to stdout.

Idempotent: if ADMIN_EMAIL already exists, it skips with [seed] admin already exists.

Env

VarDefault
ADMIN_EMAILadmin@example.com
ADMIN_PASSWORDChangeMe123! (change in prod)
ADMIN_NAMEPlatform Admin

Running

pnpm seed

In Docker, docker-entrypoint.sh runs it automatically after migrations:

node dist/src/db/migrate.js
node dist/seed.js
exec node dist/src/main.js

So a fresh container always has at least one admin.

Production checklist

  1. Set ADMIN_EMAIL and ADMIN_PASSWORD to real values via secrets manager.
  2. Sign in once.
  3. Change the password through the admin UI (or POST /api/auth/admin/set-password).
  4. Optionally, demote the seed admin and promote a personal account.

The default password is a footgun — every deploy gets ChangeMe123! if you don't override it.

Resetting

If the admin password is lost in dev:

DELETE FROM "user" WHERE email = 'admin@example.com';
DELETE FROM session WHERE user_id NOT IN (SELECT id FROM "user");

Then pnpm seed again.

In production, use POST /api/auth/admin/set-password from another admin or forget-password flow.