Self-hosting overview
The whole product, on your machine, free forever. One Postgres, two containers, one command.
Requirements
Section titled “Requirements”- 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
Quickstart
Section titled “Quickstart”git clone https://github.com/StoryFunnels/storyOS.git storyos && cd storyosecho "BETTER_AUTH_SECRET=$(openssl rand -hex 32)" > .envdocker compose up -dOpen http://localhost and sign up — the first account creates its own workspace. Migrations run automatically when the API boots.
What’s in the box
Section titled “What’s in the box”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.
Going to production
Section titled “Going to production”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/Caddyfileto use your domain name and let Caddy issue certificates itself (needs ports 80 + 443 reachable).
Next steps
Section titled “Next steps”- Configuration — the full environment matrix.
- Attachments — local disk vs S3/MinIO.
- Backup & upgrade.