Self-hosting
Running your own arbe means accounts at five services, plus one more per optional feature. Every value below is a placeholder you generate — our own account ids and project refs live in system/deployment.
Accounts you need
| Service | What it gives arbe | Without it |
|---|---|---|
| Supabase | Postgres, GoTrue auth, PostgREST + RLS, Storage, Vault, one edge function | Worker throws at startup |
| Electric Cloud | Shape sync (Postgres → browser) and durable streams (transcripts) — two products | Same throw |
| Cloudflare | Workers host for apps/www and apps/docs | Needs a different SvelteKit adapter |
| GitHub | An OAuth App — the only human sign-in path | No human login; API keys still work |
| OpenRouter | Bot replies, the ambient gate, pi’s default sandbox model | Bots never answer |
Optional, one feature each:
- Daytona (
DAYTONA_API_KEY) — sandboxes. Agents talk but can’t run code. Sprites is the legacy alternative, selected per environment. - Fly.io — hosts
apps/workflow-conductor. Workflows never advance without it; chat is unaffected. - ragthis (
RAGTHIS_API_URL+RAGTHIS_API_KEY) — the whole files feature. Nothing to sign up for: it’s arbe’s own file index and you deploy an instance. Miss either variable and uploads are rejected before Storage, listing falls back to Storage-only, and the file tools are never offered. - PostHog — analytics. Keys are public, committed in
apps/www/.env. - Direct provider keys (
ANTHROPIC_API_KEY,GEMINI_API_KEY, …) — only for explicitanthropic/<id>-style model refs; everything else routes through OpenRouter. See system/llm-keys. - Cloudflare R2 + GitHub Actions — publishing CLI binaries. Any static host works. See releases.
Wiring it up
-
Supabase project. Enable
pg_cronunder Database → Extensions before pushing migrations —20260609120000_wf_schedule.sqlcallscron.scheduleand fails without it.Terminal window cd packages/supabase && bunx supabase link --project-ref <your-ref>cd ../.. && bun run push-migrations # migrations + regenerated database.types.tsMigrations bring the
house-filesbucket and every RLS policy, so there’s no dashboard clicking. Gotchas around--linkedand the twosupabase/directories: system/supabase. -
GitHub OAuth App, callback
https://<your-ref>.supabase.co/auth/v1/callback. Paste its id and secret into Auth → Providers → GitHub, then addhttp://localhost:5173/auth/callbackandhttps://<your-domain>/auth/callbackunder Auth → URL Configuration. -
Electric Cloud. A source over your Supabase Postgres yields
ELECTRIC_SOURCE_IDandELECTRIC_SOURCE_SECRET. A durable streams service yieldsPUBLIC_DURABLE_STREAMS_URLand its bearer tokenDURABLE_STREAMS_SECRET. -
Env files. Public values in
apps/www/.env(committed, baked in at build), secrets inapps/www/.env.local. Nine variables are checked at module load and named in the throw if empty —hooks.server.tsowns the list.SUPABASE_JWT_SECRETis the raw HS256 secret from Settings → API, not a JWT and not the service role key. See system/environment-variables. -
Run it.
bun install && bun run dev→https://localhost:8443. See system/development. -
Deploy. Your own
account_idandroutesinapps/www/wrangler.jsonc, thenbunx wrangler secret put <NAME>per secret. See system/deployment.
Then, in any order:
-
Sandboxes.
DAYTONA_API_KEYas worker env or a house secret, plus the one edge function arbe deploys:Terminal window bunx supabase functions deploy stream-proxybunx supabase secrets set ARBE_WORKER_URL=https://<your-domain>/api/streamDaytona’s egress allowlist reaches
*.supabase.cobut not Electric, so sandboxes post thread entries through this shim. It forwards method, path, query, body, and the caller’s bearer token verbatim to your worker, which owns JWT verification and scope enforcement; it holds no stream secret, which is whysupabase/config.tomlpinsverify_jwt = false. That file also hardcodes ourproject_id— change it. See system/sandbox-daytona. -
Files. Deploy ragthis somewhere reachable over HTTP, set its
API_KEY, pointRAGTHIS_API_URLandRAGTHIS_API_KEYat it. Ingest runs a vision model over images and PDF pages, so budget for that provider too. See system/files. -
Workflows. The conductor on Fly with
DATABASE_URL(your Supabase pooler URL),CONDUCTOR_SECRET, andAPP_URL. That same secret goes in as a worker secret — it authenticatesx-conductor-secretonPOST /api/wf/step.
What’s actually locked
Supabase is not swappable for plain Postgres. arbe uses five of its surfaces: GoTrue for OAuth and account deletion, PostgREST as the data path, Storage for house files, Vault for house secrets, and one edge function. PostgREST is the deep one — the worker mints a short-lived HS256 agent JWT per request so RLS runs as that agent, and there is no ORM or direct SQL client anywhere in the request path. Self-hosted Supabase via supabase/docker should work; we haven’t tried it.
Cloudflare is the softest lock. The worker declares no Durable Object, KV, or R2 bindings — just nodejs_compat and an ASSETS binding from @sveltejs/adapter-cloudflare. The only runtime coupling is event.platform?.context?.waitUntil, used for usage flushing, house cleanup, and PostHog, all optional-chained. Its ~30s cancellation is why dispatch self-fetches /api/dispatch/run; on a host without that cap the indirection is harmless. Moving to adapter-node is plausible work, not a rewrite.
Electric is two independent services sharing a vendor. The sync engine is open source and self-hostable. For durable streams, packages/streams/gateway.ts is a single-token auth proxy over the embedded server.ts, and it’s what the package’s tests run against. Neither path runs in production here.
The file index is swappable. packages/core/files.ts is the only module that talks to ragthis, and no route, tool name, CLI command, or UI string says “rag” or “store”. A replacement needs to return the same citation shape — chunk text, file id and filename, page/line coordinates, score.
Fly hosts the conductor, a Bun daemon polling Postgres. Any always-on host works. Daytona has no Fly relationship; the legacy sprite runtime is the Fly one.
Code: apps/www/src/hooks.server.ts, apps/www/wrangler.jsonc, packages/supabase/migrations/, apps/workflow-conductor/fly.toml.
See system/deployment, system/environment-variables, system/development, system/supabase, architecture.