Local Development Environment
This compose stack is the Sprint 1 local scaffold for the standalone target.
Services
- PostgreSQL with pgvector on port
5432. Thevectorextension is enabled automatically on a fresh data volume byinfra/local/postgres-init/01-enable-pgvector.sql(mounted into/docker-entrypoint-initdb.d), sopnpm local:db:migratesucceeds without a manual step. - MinIO S3-compatible object storage on ports
9000and9001. - A one-shot MinIO bootstrap container that creates
${MINIO_BUCKET:-knowledge-fs}. - Self-hosted Unstructured API on port
8000. - Optional API and Admin app containers behind the
appsprofile.
Commands
pnpm dev:infra
Starts PostgreSQL, MinIO, the MinIO bucket bootstrap, and Unstructured from infra/local/compose.middleware.yaml.
This is the preferred local mode when the API and Admin Console should run from the checked-out source tree on the host.
pnpm local:db:migrate
Applies checked-in PostgreSQL migrations to the configured DATABASE_URL before running the source API against database-backed repositories. Migrations are not run by the API container, the Docker entrypoint, or on server startup — run this explicitly after the database is up. The initial migration relies on the vector extension; on a fresh volume the init script above provides it. If your Postgres volume predates that script, enable it once with:
docker compose --env-file infra/local/.env -f infra/local/compose.yaml exec postgres \
psql -U "${POSTGRES_USER:-knowledge_fs}" -d "${POSTGRES_DB:-knowledge_fs}" -c 'CREATE EXTENSION IF NOT EXISTS vector;'
Full Docker Compose startup
docker compose --env-file infra/local/.env.example -f infra/local/compose.yaml --profile apps config
docker compose --env-file infra/local/.env -f infra/local/compose.yaml --profile apps up -d --build
pnpm dev:stack runs the same full stack in the foreground when you want attached Compose logs.
Starts PostgreSQL, MinIO, the MinIO bucket bootstrap, Unstructured, the production API container, and the production Admin Console container.
Default local endpoints:
- Admin Console / control panel:
http://localhost:3000 - API health:
http://localhost:8788/health - API readiness:
http://localhost:8788/ready - Admin BFF health:
http://localhost:3000/api/bff/health - MinIO console:
http://localhost:9001 - Unstructured API:
http://localhost:8000
If a default host port is already in use, override only the conflicting port for the startup command:
API_PORT=8787 ADMIN_PORT=3003 UNSTRUCTURED_PORT=8002 docker compose --env-file infra/local/.env -f infra/local/compose.yaml --profile apps up -d --build
The API service is built from apps/api/Dockerfile as knowledge-fs-api:local and runs the standalone Hono server. The Admin service is built from apps/admin/Dockerfile as knowledge-fs-admin:local and runs the Next.js standalone server.
If Docker Hub auth or rate limiting blocks another build and the app images already exist locally, start from cached local images without rebuilding:
docker compose --env-file infra/local/.env -f infra/local/compose.yaml --profile apps up -d --no-build
Use the same port overrides with --no-build when needed:
API_PORT=8787 ADMIN_PORT=3003 UNSTRUCTURED_PORT=8002 docker compose --env-file infra/local/.env -f infra/local/compose.yaml --profile apps up -d --no-build
Verify the full stack after startup:
docker compose --env-file infra/local/.env -f infra/local/compose.yaml --profile apps ps
curl http://localhost:${API_PORT:-8788}/health
curl --fail http://localhost:${API_PORT:-8788}/ready
curl http://localhost:${ADMIN_PORT:-3000}/api/bff/health
The API container uses /ready for its Compose health check, and Admin waits for that check to
pass. In this development profile, the explicit local verifier is installed and the Dify/plugin-daemon
transports are optional until their corresponding model or datasource features are exercised. /health
remains a liveness endpoint and always uses HTTP 200 to expose component diagnostics.
For the source-run local happy path, keep pnpm dev:infra running and start these in separate
terminals:
pnpm local:db:migrate
pnpm dev:api
pnpm --filter @knowledge/admin dev
pnpm local:happy-path
pnpm dev:api loads infra/local/.env automatically, so it sees the same database, object storage, and local auth settings used by pnpm local:db:migrate.
The smoke command validates Compose config, Admin build, API health, Admin BFF health, workspace bootstrap,
single Markdown upload through the Admin BFF proxy, document status read, parse artifact read, and a bounded query evidence
check without manual database edits. Set LOCAL_SMOKE_ADMIN_BASE when the Admin dev server is not running at http://127.0.0.1:3000.
Set LOCAL_SMOKE_SKIP_ADMIN_BUILD=1 to skip the Admin build when you only want to recheck the live API/upload/artifact path.
Set LOCAL_SMOKE_RUN_MIGRATIONS=1 pnpm local:happy-path when you want the smoke run to apply checked-in PostgreSQL migrations before API health, upload, artifact, and query checks.
Run pnpm local:happy-path:durable when you want the smoke to require DATABASE_URL, MinIO env, healthy database, and healthy object storage instead of silently accepting memory fallback.
Run pnpm local:happy-path:api when you want the same bounded API upload, artifact, and query evidence checks without requiring the Admin dev server or Admin BFF.
pnpm compose:config
Validates the resolved compose configuration without starting containers.
pnpm compose:middleware:config
pnpm compose:middleware:test
Validates the middleware-only Compose file and asserts that it does not include api or admin.
pnpm compose:apps:test
Validates the full app profile contract for API image build wiring, middleware readiness dependencies, and the Admin source-run BFF base URL without starting containers.
docker compose --env-file infra/local/.env -f infra/local/compose.yaml up -d minio minio-bootstrap
pnpm test:minio
Runs the live MinIO object-storage smoke test against the bootstrapped local bucket.
Notes
-
Runtime secrets are intentionally local defaults only. Put overrides in
infra/local/.env, which is ignored by git. -
Copy
infra/local/.env.exampletoinfra/local/.envfor a fresh local setup. The tracked example leaves provider API keys blank. -
With the default
infra/local/.env.examplevalues, source-run Node can use PostgreSQL throughDATABASE_URL, database-backed core repositories unlessKNOWLEDGE_DATABASE_REPOSITORIES=off, MinIO throughMINIO_ENDPOINT,MINIO_BUCKET,MINIO_ACCESS_KEY, andMINIO_SECRET_KEY, and local Admin-to-API auth throughKNOWLEDGE_DEV_AUTH_TOKEN. -
In the full Docker stack the Admin container also receives
KNOWLEDGE_DEV_AUTH_TOKENso its server-side BFF can authenticate to the API. Because the Admin image runs withNODE_ENV=production, without this tokengetAdminServerToken()returnsnulland the token-gated panels (Control plane, Operations diagnostics, Publish readiness) render as "Unavailable". The default matches the API service so both resolve todev-tokenunless overridden ininfra/local/.env. -
First run against an empty database: after
pnpm local:db:migrate, the Admin Console still has no knowledge space, so per-space panels show "Unavailable". Create one (or upload a document, which bootstraps a space) to populate them. The default active workspace is the space whose slug isworkspace:curl -X POST -H "Authorization: Bearer ${KNOWLEDGE_DEV_AUTH_TOKEN:-dev-token}" -H 'Content-Type: application/json' \ -d '{"name":"workspace","slug":"workspace"}' "http://localhost:${API_PORT:-8788}/knowledge-spaces"Publish readiness stays empty ("No document selected") until a document is uploaded through the Upload intake panel.
-
Dense-vector indexing/search is disabled until
KNOWLEDGE_EMBEDDING_PROVIDERis set toopenai,cohere,voyage, orstatic. SetKNOWLEDGE_EMBEDDING_MODELwhen you need a non-default model. -
For OpenAI-compatible embeddings, prefer
OPENAI_EMBEDDING_BASE_URL;OPENAI_BASE_URLis accepted as a fallback and a trailing/v1is normalized before the embedding client appends/v1/embeddings. -
The API production image bundles the TypeScript compute package, so containerized ingestion can create KnowledgeNodes without an external runtime artifact.
-
R2-compatible runtime wiring is available through
R2_ACCOUNT_ID,R2_BUCKET,R2_ACCESS_KEY_ID,R2_SECRET_ACCESS_KEY, and optionalR2_REGION. -
The API and Admin containers run from standalone local images. Use
infra/local/compose.middleware.yamlwhen you want middleware containers only and API/Admin from the host source tree. -
Build the API image directly with
pnpm docker:api:buildand the Admin image withpnpm docker:admin:buildwhen you want to validate Dockerfiles outside Compose. -
The Unstructured API image follows the upstream self-hosted API image path.
-
The live MinIO smoke test is intentionally separate from
pnpm checkso normal CI does not require long-running local containers. -
Run
pnpm docker:api:bundle-smoketo start the built API image underNODE_ENV=testand verify/healthreportscomponents.compute === true. This isolated bundle check does not validate production fail-closed configuration or durable dependencies.pnpm docker:api:http-smokeis retained only as a compatibility alias. -
Run
pnpm docker:admin:http-smokeafterpnpm docker:admin:buildto start the production Admin image and verify the Next.js standalone homepage renders. -
Run
pnpm docker:apps:smoketo build both app images, run the isolated API bundle check, and run the Admin image homepage check. Validate production API wiring through the Compose-backed durable happy path and tenant-scoped upload/query checks.