Claudium
Operations

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

ServiceRequired?Notes
Node 18+ runtimeyesThe hub.
Postgres 14+ with pgvectoroptionalUnlocks DB-backed sessions, sender persistence, per-org learning. Without it, the hub runs in env-var-only mode with stateless signed-cookie sessions.
RedisoptionalMulti-instance rate limiting. Single-instance hubs use in-process counters by default.
Resend accountoptionalFor OTP signup/login emails. Without it, login is disabled and signup degrades to lead-capture only.
Stripe accountoptionalFor paid tiers. Without it, billing endpoints return 503 and the hub stays on the Free tier.
OpenAI API keyoptionalFor 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.

The repo ships a render.yaml blueprint. The fastest path:

  1. Fork the repo to your GitHub account.
  2. In Render, New → Blueprint and point it at your fork.
  3. Render reads render.yaml, provisions a web service + a free Postgres, and starts the hub.
  4. Set the env vars listed below.
  5. 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_URL so 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 subscriptions lookup 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_KEY env 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.

On this page