Run it locally
Getting Inbox up on your machine is five commands. Two of them are the ones people skip, and both fail in ways that do not name the real cause — read the gotchas below before you debug anything.
Prerequisites
- Node 22+
- Yarn 1.x (this is a Yarn workspaces monorepo, not pnpm or npm)
- PostgreSQL on
localhost:5432 - Redis on
127.0.0.1:6379 - A
.envat the repo root — not inapps/service/
First run
# 1. Install
yarn install
# 2. Build the workspace packages FIRST.
# Skip this and the service dies with: Cannot find module '@~inbox/types'
yarn build
# 3. Create the database (once)
createdb axis_inbox
# 4. Apply migrations
yarn prisma migrate dev --schema apps/service/prisma/schema.prisma
If Prisma complains that PrismaClientKnownRequestError does not exist on type 'typeof Prisma', the
generated client is stale: run yarn prisma generate, then rebuild.
Migrations are hand-managed from a baseline. Use prisma migrate dev — never db push, which
desyncs the migration history.
Required environment
Two variables are hard requirements, checked at boot by loadConfig:
| Variable | Requirement |
|---|---|
INBOX_KEK |
32 bytes / 64 hex characters. The key-encryption key for provider credentials at rest. |
INBOX_REALTIME_JWT_SECRET |
At least 32 characters. Signs short-lived realtime tokens. |
Anything shorter throws at startup with an explicit message. Beyond those, INBOX_DATABASE_URL,
INBOX_REDIS_URL and INBOX_PORT (default 3000) select the backing stores and the listen port; the
service's local development port is 6979 in the checked-in setup.
The gotcha that costs the most time
Nothing in the application loads .env. dotenv is a devDependency that is never imported. The
start scripts pass Node's own flag instead:
"start": "nest start --env-file ../../.env",
"start:dev": "nest start --watch --env-file ../../.env",
"start:prod": "node --env-file-if-exists=../../.env dist/main"
Two consequences. First, ../../.env resolves from apps/service/, so the file lives at the repo
root; putting it in apps/service/.env loads nothing. Second, running nest start directly, without
the flag, dies with Missing required env var INBOX_KEK — which reads like a missing variable rather
than a missing loader.
start:prod and the scripts use --env-file-if-exists so CI and production, where configuration comes
from the real environment, do not fail on an absent file.
Start it
cd apps/service && yarn start:dev # watch mode
or from the repo root:
yarn dev
Smoke tests
curl -s localhost:6979/v1/ping
# → { "ok": true }
curl -s localhost:6979/v1/health
GET /v1/ping and GET /v1/health are both public. Health reports which backends are wired:
{
"status": "ok",
"env": "development",
"backends": { "database": true, "redis": true, "aggregator": true }
}
If database is false, stop and fix it. INBOX_DATABASE_URL did not reach the process, and
common/persistence.ts silently falls back to in-memory stores. The service boots, accepts writes,
answers reads within a single run — and persists nothing. There is no error, only data that is gone
after a restart. The same env-driven fallback applies to the Redis-backed queues.
Once you have a credential and a tenant, confirm the whole auth chain:
curl -s -H "authorization: Bearer $KEY" -H "x-axis-tenant: ws_<userGroupId>" \
localhost:6979/v1/whoami
# → { "data": { "appId": "…", "mode": "bearer", "scopes": [...], "tenantId": "…" } }
whoami is the one call that tells you what the service thinks you are. See
Connect an app for getting $KEY.
Stopping it
pkill -f 'dist/main'
Target the server process, not the watcher. pkill -f 'nest start' kills the CLI wrapper and leaves the
re-parented child holding the port, which then blocks the next start with EADDRINUSE.
Gotcha table
| Symptom | Cause |
|---|---|
Missing required env var INBOX_KEK |
.env not loaded — use the yarn scripts, or pass --env-file ../../.env |
Cannot find module '@~inbox/types' |
Workspace packages not built — yarn build at the root |
health.backends.database = false |
INBOX_DATABASE_URL absent, silent in-memory fallback |
EADDRINUSE on the service port |
Orphaned dist/main from a previous run |
INBOX_SKIP_AUTH appears to be ignored |
Honoured only when the env is exactly development |
| Data disappears between restarts | See database: false above |