Seeding
seed.ts runs as a standalone script. It creates the initial platform admin user.
What it does
- Calls better-auth's internal
auth.api.signUpEmail()(no HTTP, in-process). - Promotes the resulting user to
role = 'platform_admin'. - Logs the credentials to stdout.
Idempotent: if ADMIN_EMAIL already exists, it skips with [seed] admin already exists.
Env
| Var | Default |
|---|---|
ADMIN_EMAIL | admin@example.com |
ADMIN_PASSWORD | ChangeMe123! (change in prod) |
ADMIN_NAME | Platform 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
- Set
ADMIN_EMAILandADMIN_PASSWORDto real values via secrets manager. - Sign in once.
- Change the password through the admin UI (or
POST /api/auth/admin/set-password). - 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.