Skip to content
BoringStack
GitHub

Quickstart

5 min read

Local boot

Clone the BoringStack monorepo, run ./setup.sh --up, and Compose starts Postgres, Valkey, api-dev (migrations + OpenAPI), and ui-dev (Vite on :3001 with generated client). Optional overlays: Mailpit, Bull Board, observability, GlitchTip.

1

git clone

Docker

only prerequisite

0

local Node or Bun installs

01

Clone the monorepo

One repo contains apps/api, apps/ui, infra/compose, and apps/docs.

02

Run setup

`./setup.sh --up` seeds compose/.env and boots the dev stack.

03

Sign in

Open http://localhost:3001; use SUPERUSER_* from compose/.env or register.

04

Ship changes

From repo root: `bun run regen` then `bun run check` before you push.

You now have Postgres, Valkey, the API, and the UI running locally with hot reload.

  • Docker + Docker Compose v2 (docker compose version reports v2.x or newer).
  • About 4 GB of free RAM.
  • No local Node or Bun needed for the default path; everything runs in containers.
Terminal window
git clone https://github.com/boringstack-xyz/boringstack.git
cd boringstack

Fork the monorepo on GitHub if you want your own copy under your org. API, UI, docs, Compose, and bootstrap infrastructure all live in this one tree.

Monorepo layout
boringstack/
  • apps/api/Bun + Elysia + Drizzle API
  • apps/ui/Vite + React SPA
  • apps/docs/boringstack.xyz site source
  • infra/compose/
    • compose/
      • docker-compose.ymlbuild.context → ../../../apps/api | apps/ui
      • dev.shdev stack entrypoint
  • infra/bootstrap/optional OpenTofu VPS bootstrap
Boot locally
$ ./setup.sh --up

ok  postgres ready on 5432
ok  valkey ready on 6379
ok  api-dev migrated and serving /openapi.json
ok  ui-dev generated client and started Vite

Or manually:

Terminal window
cd infra/compose/compose
cp .env.example .env
chmod +x dev.sh ../scripts/*.sh
./dev.sh up -d --build

First boot pulls base images, builds the api/ui dev images, and runs migrations. If you set SUPERUSER_EMAIL + SUPERUSER_PASSWORD in compose/.env, an admin user is also created. About 3 minutes on a fast laptop.

Open http://localhost:3001.

If you set SUPERUSER_EMAIL + SUPERUSER_PASSWORD in compose/.env before booting, sign in with those credentials. Otherwise hit “Sign up” on the form and register a new account; that user is the first user in the system. You land on the dashboard, which is minimal on purpose. Start building from here.

postgres (port 5432)

App database; schemas auth, billing, audit, app, notifications.

valkey (port 6379)
Cache and BullMQ queues.
api-migrate (one-shot)

db:push and optional superuser seed, then exits.

api-dev (port 3000)

Bun + Elysia API with hot reload via bind mount.

ui-dev (port 3001)

Vite dev server; proxies /api/* to api-dev.

Traefik runs only in the prod profile. In prod it terminates TLS and path-routes /api/* + /health to the api container, everything else to ui, on one domain.

  • Regenerate cross-app contracts: bun run regen from repo root (api must be on :3000 for OpenAPI).
  • Observability: WITH_OBSERVABILITY=1 ./scripts/compose-up.sh from infra/compose/compose. Details.
  • Self-hosted error tracking: WITH_GLITCHTIP=1 ./scripts/compose-up.sh. Details.
  • Local email testing: WITH_MAILPIT=1 ./scripts/compose-up.sh. Details.
  • Production deploy: Deployment when you are ready for GHCR images, TLS, firewall, and backups.
Stop, keep data

From infra/compose/compose: ./dev.sh down. Volumes stay on disk.

Stop and wipe data

./scripts/compose-down-clean.sh from infra/compose. Prompts before delete; CONFIRM=yes to skip the prompt.