Skip to content

Self-hosting overview

The whole product, on your machine, free forever. One Postgres, two containers, one command.

  • Docker with Compose v2
  • 1 GB RAM / 1 vCPU is plenty for a small team
  • (Optional) a domain + reverse proxy with TLS for real deployments
Terminal window
git clone https://github.com/StoryFunnels/storyOS.git storyos && cd storyos
echo "BETTER_AUTH_SECRET=$(openssl rand -hex 32)" > .env
docker compose up -d

Open http://localhost and sign up — the first account creates its own workspace. Migrations run automatically when the API boots.

docker compose up -d starts:

  • postgres — PostgreSQL 16, the only datastore.
  • api — the REST API (NestJS/Fastify); runs migrations on boot.
  • web — the Next.js web app.
  • caddy — a reverse proxy that serves everything on one origin (port 80): the web app at / and the API at /api/*.
  • mcp (optional) — the hosted MCP endpoint; route a subdomain to it.
  • minio (optional, --profile minio) — S3-compatible attachment storage.

For a real deployment, set API_URL and WEB_URL in .env to your public URL (e.g. https://os.example.com for both). Auth validates request origins against WEB_URL, so a mismatch shows “Invalid origin” at login.

TLS — two common options:

  • Put the domain behind Cloudflare (proxied, SSL mode Flexible), or
  • Edit docker/Caddyfile to use your domain name and let Caddy issue certificates itself (needs ports 80 + 443 reachable).