Skip to content

Self-Hosted Installation

1. Prerequisites

Requirement Version Notes
Docker Engine 24.x+ docker --version
Docker Compose v2.x (the docker compose plugin) docker compose version
PostgreSQL 17 (bundled) Provided as the postgres service via pgvector/pgvector:pg17 — no separate install needed unless you point RAI_DATABASE_URL at your own instance
Disk ~2 GB+ Server image (incl. baked-in ONNX embedding model) + growing PostgreSQL volume

You do not need Python, uv, or Node installed on the host — everything runs inside the container.

2. Get the source

git clone https://github.com/humansys/raise-commons.git
cd raise-commons

3. Environment variables

The root docker-compose.yml sets sane defaults for every required variable except the ones only you should know. Nothing needs to be overridden for the default quick-start; the table below is for customizing a real deployment.

Variable Set where Default Purpose
RAI_DATABASE_URL docker-compose.yml (server env) postgresql+asyncpg://rai:dev@postgres:5432/rai AsyncPG connection string. Point this at an external managed PostgreSQL instead of the bundled postgres service by editing the compose file.
RAI_ENV docker-compose.yml development Controls a small number of env-gated behaviors (e.g. migration execution path in entrypoint.sh). Self-hosted operators should leave this as-is unless they know they need Fly/Cloud Run semantics — those paths assume a platform-managed release step that does not exist here.
RAI_PORT docker-compose.yml 8080 Port uvicorn binds to inside the container; mapped to the host via the compose ports: entry.
RAI_LOG_LEVEL docker-compose.yml DEBUG Lower to INFO or WARNING for a production-like deployment — DEBUG is chatty.
RAI_COOKIE_SECURE docker-compose.yml false Set to true once you terminate TLS in front of the server (e.g. a reverse proxy) — session cookies then require HTTPS.
UVICORN_RELOAD docker-compose.yml true Hot-reload on source changes. Turn this off ("false" or remove the line) for anything other than local development — it mounts packages/raise-server/src read-only into the container and watches it.
RAI_STRIPE_SECRET_KEY / RAI_STRIPE_PRICE_MONTHLY / RAI_STRIPE_PRICE_ANNUAL / RAI_STRIPE_WEBHOOK_SECRET Shell env, forwarded via ${VAR:-} empty Optional. Billing endpoints return 503 (not an error) when unset — self-hosted deployments typically don't need Stripe at all, since licensing/plan enforcement for a self-hosted instance is a local decision (see below).

There is no .env.example specific to docker-compose.yml (the .env.example at the repo root is for the separate team-infra compose file, docker-compose.yaml, which also runs the rai-agent Telegram daemon — not part of this self-hosted path). Override any of the variables above with a shell export before docker compose up, or by adding an environment: override in a docker-compose.override.yml.

4. Plans and licensing for self-hosted

Every authenticated member resolves to a plan (trial, community, pro, team, enterprise) via MemberContext, driven by the org's row in the licenses table — seed_dev.sql inserts an active team-plan license (no expiry until 2027, no Stripe involved). Any member with a resolved plan — community and up — is sufficient to call every endpoint in this story (/api/v2/export/*, /api/v2/metrics, /api/v2/adoption, /api/v2/audit): none of them impose a paid-tier minimum beyond authentication. There is no external license server call required — no network egress beyond what you configure yourself.

5. Networking

  • postgres is not exposed outside the Docker network by default beyond the 5432:5432 host port mapping already in docker-compose.yml — remove that mapping if you don't need host-side psql access.
  • server listens on 8080 inside the container, mapped to host 8080. Put a reverse proxy (nginx, Caddy, Traefik) in front for TLS termination in any deployment reachable outside localhost; set RAI_COOKIE_SECURE=true once you do.
  • No outbound network calls are required at runtime for the endpoints this story adds (export/metrics/audit/adoption are pure PostgreSQL reads). Other parts of the image have optional outbound dependencies only when explicitly configured — Stripe (billing) and the Atlassian/Google OAuth identity-broker flows are the two examples in this compose file; leave their env vars unset to keep the deployment fully offline.

6. First-run verification

docker compose up -d --build
docker compose logs -f server   # watch migrations run, then "Uvicorn running on..."
curl http://localhost:8080/health

A healthy response has "database": "connected". If migrations are still running you'll see connection refused briefly — see troubleshooting.md.

Continue to docker-compose.md for a field-by-field breakdown of the compose file, or straight to export-api-usage.md to try the bulk export API.