Self-hosting
Run the Claudium hub on your own infrastructure. Render-friendly, Postgres-optional, no vendor lock.
The hub is open source and runs on a single Node process. You can deploy it on Render, Fly, Railway, your own VPS, or a Kubernetes cluster — there's no managed-service dependency.
What you need
| Service | Required? | Notes |
|---|---|---|
| Node 18+ runtime | yes | The hub. |
| Postgres 14+ with pgvector | optional | Unlocks DB-backed sessions, sender persistence, per-org learning. Without it, the hub runs in env-var-only mode with stateless signed-cookie sessions. |
| Redis | optional | Multi-instance rate limiting. Single-instance hubs use in-process counters by default. |
| Resend account | optional | For OTP signup/login emails. Without it, login is disabled and signup degrades to lead-capture only. |
| Stripe account | optional | For paid tiers. Without it, billing endpoints return 503 and the hub stays on the Free tier. |
| OpenAI API key | optional | For the embedding pipeline. Without it, the embedding worker skips its ticks; everything else works. |
The pattern is: the hub starts cleanly with none of the optional services. Each one you add unlocks a feature. There's no "minimum viable provisioning" you have to complete before anything works.
Render (recommended)
The repo ships a render.yaml blueprint. The fastest path:
- Fork the repo to your GitHub account.
- In Render, New → Blueprint and point it at your fork.
- Render reads
render.yaml, provisions a web service + a free Postgres, and starts the hub. - Set the env vars listed below.
- Run the migrations (next section).
The included Postgres ships with pgvector available — CREATE EXTENSION vector works out of the box.
Database migrations
psql $DATABASE_URL -f db/migrations/0001_init.sql
psql $DATABASE_URL -f db/migrations/0002_rls.sql
psql $DATABASE_URL -f db/migrations/0003_signup_leads.sql
psql $DATABASE_URL -f db/migrations/0004_audit_events.sql
psql $DATABASE_URL -f db/migrations/0005_sessions.sql
psql $DATABASE_URL -f db/migrations/0006_newsletter_leads.sql
psql $DATABASE_URL -f db/migrations/0007_org_events.sql
psql $DATABASE_URL -f db/migrations/0008_turn_embeddings.sql
psql $DATABASE_URL -f db/migrations/0009_subscriptions.sql
Each migration is idempotent — safe to re-run. 0008 is the one that needs pgvector; if your provider doesn't ship it, ask them to enable it (Supabase, Neon, Render, RDS all support it).
Environment variables
# Required for any hub
PORT=4242
SESSION_SECRET=<random 64-byte hex>
# Database mode (recommended for prod)
DATABASE_URL=postgres://...
USE_DB_SESSIONS=1
USE_DB_TOKENS=1
# Email-based login (required for self-serve signup)
RESEND_API_KEY=re_...
LOGIN_FROM_EMAIL=noreply@yourdomain.com
# Per-org learning loop
OPENAI_API_KEY=sk-...
OPENAI_DAILY_BUDGET_USD=5
# Billing (optional)
STRIPE_SECRET_KEY=sk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...
STRIPE_PRICE_TEAM_MONTHLY=price_...
STRIPE_PRICE_TEAM_ANNUAL=price_...
# Observability (optional)
NEXT_PUBLIC_SENTRY_DSN=https://...
Generate SESSION_SECRET once and pin it:
node -e "console.log(require('crypto').randomBytes(64).toString('hex'))"
If SESSION_SECRET isn't set, the hub generates a random one per process — sessions then work within one run but don't survive a restart.
Bring your own domain
The hub serves both the marketing site (statically exported from landing/) and the app (/brain, /admin, /api/*) on the same origin. Point your DNS at the hub's public URL and you're done — no separate frontend/backend split to configure.
Multi-instance
For a single team, one hub instance is plenty. The watcher → hub → viewer fanout is cheap and the hub is mostly I/O bound.
If you need to scale horizontally:
- Set
REDIS_URLso rate limits, OTP state, and embedding-cost counters share across instances. - Add a Postgres read replica and route read-heavy admin queries to it (the
subscriptionslookup on every event ingest is the current hot path). - The turn stitcher + embedding worker need leader election so two instances don't double-stitch. There's a
LEADER_ELECTION_KEYenv var queued for that — not yet implemented.
For now, vertical scaling on a single instance handles a team of 50 contributors comfortably.
Upgrading
git pull origin main
npm install
psql $DATABASE_URL -f db/migrations/<new ones>.sql
# Render auto-restarts on push; others: kill + restart your service.
Migrations are append-only (we never DROP TABLE) so downgrades work by ignoring the new migrations on an old build.
Per-org learning loop
The intelligence layer learns from your team's activity and nobody else's. Schema, RLS, embedding pipeline, cost guardrails.
Custom domain per org
Map a hostname like claudium.acme.com to a workspace. Two TLS recipes — Cloudflare proxy (zero-config) and Caddy reverse proxy (self-hosted).