Skip to content

Getting Started

Melvin PETIT edited this page Sep 16, 2026 · 4 revisions

Getting Started

This page walks through a local development setup from a fresh clone to a running app with seeded demo data.

Prerequisites

  • Docker for the database, and for the one-command Docker path below.
  • Node.js 22 (pinned via .nvmrc and the engines field) only when running on the host. The make targets select it automatically via nvm.

With Docker (recommended)

Needs only Docker, no Node on the host. Builds the app, starts PostgreSQL, applies migrations and seeds demo data in one command.

make env            # create .env.local with generated secrets
docker compose up   # app on http://localhost:3000, database seeded

Migrations and the demo seed run on every start, so a fresh machine is ready right after git pull.

Deploying the published image

The sections above are for working on Gardik. To run it on a server, use the published image and the compose file on its Docker Hub page.

One step there has no equivalent in development. A deployed image seeds nothing and public sign-up is disabled, so there is no account to sign in with until you create one. Set both of these before the first start:

Variable Value
BOOTSTRAP_ADMIN_EMAIL The first administrator's address, e.g. admin@acme.com. Its domain becomes the company.
BOOTSTRAP_INVITE_TOKEN The output of openssl rand -hex 32.

The container then logs a link, and no secret:

[bootstrap] Created company acme.com and administrator admin@acme.com.
[bootstrap] Open https://gardik.example.com/invite with the token you supplied.

Open <BETTER_AUTH_URL>/invite?token=<BOOTSTRAP_INVITE_TOKEN>, choose a password, and enrol a second factor if the company requires one. Remove both variables once you are signed in.

Use -hex for this one, not -base64. The token travels in a URL, and base64 output contains + and /, which a query string decodes as something else. The link would fail with "no longer valid" and give you no clue why.

No password is ever read from the environment, and there is no default account to change: an image nobody has bootstrapped has no way in at all. The step is skipped for good as soon as any account has a password, so it cannot be used later to add an administrator to a running instance. Until then a restart reissues the same token with a fresh 24 hour window, so a lost link costs you a restart and nothing else.

Install and run on the host

make setup   # install deps, create .env.local, start DB, migrate, seed
make run     # start the dev server

make doctor diagnoses the setup and can auto-fix common issues, including creating .env.local and switching to Node 22. The underlying npm steps work too:

# 1. Install dependencies (also runs `prisma generate` via postinstall)
npm install

# 2. Configure the environment
cp .env.example .env.local
# then set BETTER_AUTH_SECRET and DIRECTORY_ENCRYPTION_KEY
# to real random values: openssl rand -base64 32

# 3. Start the database, apply migrations and seed demo data
npm run db:init

# 4. Run the development server
npm run dev

Open http://localhost:3000 and sign in with the seeded admin account:

admin@gardik.local / ChangeMe123!

Override the seeded account with SEED_ADMIN_EMAIL and SEED_ADMIN_PASSWORD before seeding if you want different credentials.

Switching machines / after git pull

The Prisma client is regenerated automatically on npm install via the postinstall hook. The database is not migrated automatically: npm run dev only warns if migrations are pending (the predev hook runs prisma migrate status), it never applies them on boot.

After pulling changes that add a migration, apply it explicitly:

npm run db:migrate   # prisma migrate deploy, applies pending migrations

When you edit prisma/schema.prisma yourself, create the migration instead:

npx prisma migrate dev --name <change>

Database commands

Command Effect
npm run db:init Start Postgres container, apply all migrations, seed demo data
npm run db:up Start the Postgres container
npm run db:down Stop the container
npm run db:migrate Apply pending migrations (prisma migrate deploy)
npm run seed Seed only the admin account
npm run seed:dev Reseed full demo data (breaches, employees, alerts)

Without Docker

Point DATABASE_URL at your own PostgreSQL instance, then run:

npx prisma migrate deploy && npm run seed:dev

The defaults in .env.example match compose.yml, so npm run db:init works out of the box (postgresql://user:password@localhost:5432/gardik).

Next steps

Clone this wiki locally