Repository navigation
Getting Started
This page walks through a local development setup from a fresh clone to a running app with seeded demo data.
- Docker for the database, and for the one-command Docker path below.
-
Node.js 26 (pinned via
.nvmrcandengines) only when running on the host. Themaketargets select it automatically via nvm.
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
make up # app on http://localhost:3000 with hot reload, database seededMigrations and the demo seed run on every start, so a fresh machine is ready
right after git pull.
The app container runs as an unprivileged user with uid 1000, which must own
the source folder. If your user is not 1000 (check with id -u), start it with
APP_UID=$(id -u) APP_GID=$(id -g) make up.
The demo data is fictional: invented employees on the reserved example.com
domain, exposed in real public breaches as reported by Have I Been Pwned, so a
demo scan can never reach a real person. make down stops the stack.
make up runs its own database. If the host one from make db-up is running,
stop it first with make db-down; if port 5432 is taken by another PostgreSQL,
run POSTGRES_PORT=5433 make up.
Every port the local stack publishes (app, database, make image) is bound to
127.0.0.1, so the default database password is never reachable from the
network.
Before an image is published, run exactly that image on your machine:
make image # build it from Dockerfile, run it on http://localhost:3001 with its own database
make image-scan # Trivy scan of the image, HIGH and CRITICAL
make image-down # stop it and wipe its database and generated secretsmake image generates the secrets, starts the image like a real deployment and
prints the invite link that sets the password of admin@example.com. It runs
next to make up, on another port. Set IMAGE_PORT to use one other than 3001.
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.
Since 1.4.0 the image is built on Alpine (node:26-alpine) instead of Debian.
If you extend it in your own Dockerfile, install packages with apk add, not
apt-get.
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
-hexfor 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.
make setup # install deps, create .env.local, start DB, migrate, seed
make run # start the dev servermake doctor diagnoses the setup and can auto-fix common issues, including
creating .env.local and switching to Node 26. 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 devOpen 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.
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 migrationsWhen you edit prisma/schema.prisma yourself, create the migration instead:
npx prisma migrate dev --name <change>| 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 |
Seed the admin, then the fictional demo data (breaches, employees, alerts); safe to rerun |
Point DATABASE_URL at your own PostgreSQL instance, then run:
npx prisma migrate deploy && npm run seed:devThe defaults in .env.example match compose.yml, so npm run db:init works
out of the box (postgresql://user:password@localhost:5432/gardik).
- Set environment variables to unlock optional features: see Configuration.
- Connect an identity provider: see Directory Integrations.
- Add a breach API key and run your first scan: see Breach Scanning.
Gardik is source-available software by Melvin PETIT (WhiteMuush). Live demo, read only, no signup.
Getting started
Architecture
Features
- Breach Scanning
- Risk Scoring
- Directory Integrations
- MFA Coverage
- SCIM Provisioning
- Dashboard and Widgets
- Reports
- Exposure Register
Integrations
Identity and access
Reference
Contributing