跳到主要内容

Local Setup

Prerequisites​

  • Node.js 22 (the WebSocket package targets Node 22)
  • pnpm 9.15.5 through Corepack
  • Docker 24+ with Docker Compose v2
  • Git
corepack enable
corepack prepare [email protected] --activate

Clone and Install​

git clone https://github.com/obeya-cloud/obeya.git
cd obeya
pnpm install --frozen-lockfile
cp .env.example .env

The template contains safe local database URLs but also contains production placeholders. Do not deploy it unchanged.

Start Local Infrastructure​

The base Compose file is the local infrastructure model:

docker compose -f docker/docker-compose.yml up -d
docker compose -f docker/docker-compose.yml ps
ServiceHost portPurpose
PostgreSQL 165433Primary database
Redis 76380Cache and pub/sub
PgBouncer6432Optional connection-pool testing
MinIO9010 / 9011S3 API / console
ClamAV3311Attachment scanning

The non-standard host ports avoid common conflicts with locally installed PostgreSQL, Redis, MinIO, and ClamAV.

Apply the Database Contract​

Run all three database steps. db:migrate applies the immutable, hash-verified Drizzle journal; the apply/check pair installs and verifies the reviewed functions, constraints, indexes, grants, and RLS policies.

pnpm db:migrate
pnpm --filter @probeya/db apply-rls
pnpm --filter @probeya/db check-rls

The migration runner requires DATABASE_ADMIN_URL, serializes concurrent operators with a PostgreSQL advisory lock, and applies all pending migrations and ledger rows in one transaction. It never falls back to DATABASE_URL.

Optionally seed demo data after the RLS check passes:

pnpm db:seed

The current seed prints its available accounts when it completes. The primary demo account is [email protected] / demo1234.

Provision Local Object Storage​

The base MinIO container uses the development root identity probeya_minio / probeya_minio_secret. Configure distinct local application credentials in .env and keep the root values only for the bootstrap:

MINIO_ROOT_USER=probeya_minio
MINIO_ROOT_PASSWORD=probeya_minio_secret
S3_ACCESS_KEY=probeya_local_app
S3_SECRET_KEY=<generate-a-distinct-local-secret>
S3_BUCKET=probeya-uploads
S3_ENDPOINT=http://localhost:9010
S3_PUBLIC_URL=http://localhost:9010

Then replay the same least-privilege bootstrap used in production:

docker compose \
-f docker/docker-compose.yml \
-f docker/docker-compose.prod.yml \
run --rm --no-deps minio-init

This creates the private bucket and application user. Anonymous reads are limited to avatar and logo prefixes; attachment objects stay private.

Start the Applications​

pnpm dev
ApplicationURLPurpose
Webhttp://localhost:8000Next.js UI and tRPC/HTTP API
WebSocketws://localhost:8003Real-time collaboration
Docusaurus (when started)http://localhost:3002Product documentation dev server
Mintlifyhttp://localhost:3003Developer docs dev server

There is no separate apps/api process. API procedures from packages/api are hosted by the Next.js application.

Useful Commands​

pnpm dev
pnpm lint
pnpm type-check
pnpm test
pnpm build

pnpm db:generate
pnpm db:migrate
pnpm --filter @probeya/db apply-rls
pnpm --filter @probeya/db check-rls
# Destructive: disposable database only
DATABASE_APP_URL="$DATABASE_URL" \
PROBEYA_RLS_ACCEPTANCE_DISPOSABLE=1 \
pnpm --filter @probeya/db test:rls
pnpm db:seed
pnpm db:studio

The live RLS lane connects directly as exact probeya_app and probeya_admin. It verifies the identities before test discovery and refuses to run unless the database is explicitly marked disposable.

Troubleshooting​

PostgreSQL is not ready​

docker compose -f docker/docker-compose.yml ps postgres
docker compose -f docker/docker-compose.yml logs postgres

Wait for probeya-postgres to report healthy, then replay the failed schema step.

Resetting disposable local data​

This deletes every local Compose volume, including database and object data:

docker compose -f docker/docker-compose.yml down -v
docker compose -f docker/docker-compose.yml up -d
pnpm db:migrate
pnpm --filter @probeya/db apply-rls
pnpm --filter @probeya/db check-rls
pnpm db:seed

Never use this reset procedure against a shared or production environment.

Port conflict​

Find the conflicting process or change the host-side mapping in docker/docker-compose.yml:

lsof -i :5433
lsof -i :8000

Authentication secret error​

Generate a development secret and place it in .env:

openssl rand -base64 32

See Database Schema Operations for schema authoring and Docker Deployment for the production sequence.