Skip to content
Docs menu

Self-host

Boot the whole hub on one machine from a checkout — Postgres, S3, API and web — and what a local stack does not have.

The hub is one FastAPI service, one Next.js app, a Postgres and an S3 API. This page boots all four on one machine from a checkout of the source repository — the same code a hosted hub runs — for development, or for a lab that wants its own. The commands were run verbatim against that local stack.

You need Docker, uv, Node ≥ 24 and the checkout.

Boot a local hub

One command builds the whole thing — database, object storage, migrations, seed data, API on :8000, web on :3000:

make dev-local

Leave it running and open a second terminal for everything below. A Postgres runs in Docker and the S3 API is moto, in memory.

It seeds repos under the org lucen: a robot card built from the real Laika v2 MJCF, a dataset, a model, and one deliberately private repo so you can check that "invisible" really means invisible. The dataset is synthetic — generated at seed time — and the seeder says so on every run and writes the warning into the repo's own README.

The local S3 is in-memory. If you restart it without also resetting Postgres, the database will still hold blob rows whose bytes are gone and downloads will fail. docker rm -f lucen-hub-pg && make dev-local resets both.

A key without a browser session

On a hub with sign-in configured, keys are minted in API keys, which requires a signed-in session by design — no API key may mint another. A local stack runs with authentication unconfigured, so there is no session and no button; tools/dev_api_key.py is the local-only door around it and refuses to run against a database that is not on localhost:

NEON_DATABASE_URL=postgresql://postgres:lucen@127.0.0.1:5433/lucen uv run --no-sync python tools/dev_api_key.py --user you --scopes train | lucen auth login --stdin --url http://127.0.0.1:8000
Signed in as you (scopes: read, write, train) at http://127.0.0.1:8000
Saved to /Users/you/.config/lucen/credentials (mode 0600)

From here every step of From a terminal works against the local stack, with http://127.0.0.1:8000 as the API and http://localhost:3000 as the web app.

What a local stack does not have

  • Sign-in. Clerk is unconfigured, so the browser is always signed out: public pages work, but the Quickstart's browser steps — adding a robot, training from its page, confirming a pairing, deploying — belong to an account and cannot be done from the page.
  • The paid backends. Cloud training, hosted rollouts and hosted endpoints (executor: modal) answer 503 naming MODAL_APP_NAME; the Coach's diagnosis answers 503 without ANTHROPIC_API_KEY. Everything that runs on your own machine — lucen worker run, lucen rollout --local, lucen serve — works.

Deploying a hub of your own to the cloud (Fly, Vercel, Neon, R2, Upstash, Clerk) is described step by step in the repository's docs/RUNBOOK.md.