Installation
Run ChatAI locally with Docker, pnpm + Neon/Postgres, or deploy to common hosts.
Quick start (Docker)
Fastest path with Postgres included:
cp .env.example .env
# Set BETTER_AUTH_SECRET (openssl rand -base64 32) and AI_API_KEY
docker compose up --buildOpen http://localhost:3000. Migrations run on app startup. Details: Docker self-hosting.
Optional demo data after health is green:
pnpm seed:demo
# demo@chatai.local / DemoPass123!Docker demo shortcut (not for production): set SEED_DEMO_ON_START=1 in .env before docker compose up --build.
Quick start (development)
cp .env.example .env
# DATABASE_URL — Neon pooled URL, or local Docker Postgres
# BETTER_AUTH_SECRET, AI_API_KEY
# Local Postgres only (skip if using Neon):
docker compose up -d db
pnpm install
pnpm db:migrate # or: pnpm migrate
pnpm devOpen http://localhost:3000.
Password reset
From the sign-in page, use Forgot password?. Set RESEND_API_KEY (and preferably EMAIL_FROM) to email reset links. Without Resend, the server logs the reset URL so you can recover accounts in local or self-hosted setups.
Neon
- Create a Neon project with pgvector enabled
- Set
DATABASE_URLto the pooled connection string - Set
DATABASE_URL_UNPOOLEDto the direct URL for migrations - Run
pnpm db:migratethenpnpm dev
Keep Compose db for fully local offline work.
Local models (Ollama)
docker compose --profile local-models up --buildSee Ollama for hybrid chat (recommended) vs fully offline embedding limits.
Deployment stubs
These are short checklists — same env vars as local, plus a public BETTER_AUTH_URL.
Vercel + Neon
- Neon: pooled
DATABASE_URL, directDATABASE_URL_UNPOOLED, pgvector on - Vercel project from this monorepo; root directory / build for
apps/web(or your monorepo settings) - Set
BETTER_AUTH_SECRET,BETTER_AUTH_URL(production origin),AI_API_KEY, and other provider keys - Run migrations against Neon (
pnpm migrate/DATABASE_URL_UNPOOLED) in CI or a one-off job — the Docker entrypoint migrator is for the Compose image, not Vercel serverless cold starts - Configure durable upload storage if you outgrow ephemeral disk (
UPLOAD_DIR)
Railway
- Add a Postgres (pgvector) plugin or external Neon URL
- Deploy from the Dockerfile or connect the repo and set the start command to the image entrypoint
- Set env vars from Environment reference
- Map public HTTPS to port
3000; setBETTER_AUTH_URLto that origin - Confirm
GET /api/healthafter deploy
Fly.io
- Create an app and a Postgres volume or attach Managed Postgres with pgvector
- Use the repo
Dockerfile; allocate a volume for uploads if needed - Set secrets (
fly secrets set …) for auth and AI keys - Set
BETTER_AUTH_URLtohttps://<app>.fly.dev(or custom domain) - Smoke
curl https://<app>.fly.dev/api/health