Self-hosting guide
OrangeRails is Apache 2.0. The hosted service at orangerails.com runs the same code as the public repo — there is no closed enterprise fork. This is the single guide for running OrangeRails on your own infrastructure.
Why self-host
- Zero trust in OR the company. Even though OR can't decrypt your data (zero-knowledge architecture), some teams need the operator to also be themselves.
- Compliance. Regulated entities running their own Supabase or Postgres deployment.
- Cost. Skip the hosted billing entirely at any scale.
- Hackability. Patch adapters, add private sources, bend the API.
What you get with the self-host build
Feature parity with hosted, with the exception of:
- The hosted Stealth Sync filter CDN (
stealth.orangerails.com) and Bitcoin block fetcher (blocks.orangerails.com) — you point your self-host at our public-good CDN or run your own. See below. - SOC 2 attestation (only applies to the hosted service).
- The MCP layer (Phase 2 work — both hosted and self-host get it at the same time).
Everything else — privacy tiers, ZKA, 100+ source adapters, admin pages, the dashboard — is in the repo.
The pieces
OrangeRails is a Vite SPA + a Supabase backend (edge functions + Postgres). Two ways to run it:
| Approach | When |
|---|---|
| Supabase Cloud + Cloudflare Pages | Easiest. Matches how we run prod. Free tier covers small deployments. |
| Self-host Supabase (or any Postgres) + any static host | Maximum sovereignty. More moving parts. |
Pick based on your taste for ops. Both deploy from the same code.
Path A — Supabase Cloud + Cloudflare Pages (recommended)
1. Fork the repo
gh repo fork MorningRevolution/orangerails --clone=true
cd orangerails
2. Create two Supabase projects
In the Supabase dashboard, create <yourname>-dev and <yourname>-prod. Note both project refs (xxxxxxxxxxxxxxxxxxxx.supabase.co).
3. Apply migrations
Install the Supabase CLI, then:
supabase link --project-ref <your-dev-ref>
supabase db push
Repeat for prod.
4. Set environment variables
In your fork, set GitHub Actions repo variables (Settings → Secrets and variables → Actions → Variables):
VITE_SUPABASE_PROJECT_ID_DEV = <your-dev-ref>
VITE_SUPABASE_URL_DEV = https://<your-dev-ref>.supabase.co
VITE_SUPABASE_PUBLISHABLE_KEY_DEV = <your-dev-anon-key>
VITE_SUPABASE_PROJECT_ID_PROD = <your-prod-ref>
VITE_SUPABASE_URL_PROD = https://<your-prod-ref>.supabase.co
VITE_SUPABASE_PUBLISHABLE_KEY_PROD= <your-prod-anon-key>
And secrets:
CLOUDFLARE_API_TOKEN = <your-cf-token-with-pages-edit>
CLOUDFLARE_ACCOUNT_ID = <your-cf-account-id>
5. Create two Cloudflare Pages projects
Manually in the CF dashboard (one-time): <yourname>-dev and <yourname>-prod. Don't connect them to Git — the GitHub Actions workflow handles deploys.
6. Push
git push origin dev
Within ~60 seconds your dev site is live. Promote to prod with:
git checkout prod && git merge --ff-only dev && git push origin prod
Path B — Self-hosted Supabase + any static host
The repo includes a docker-compose.yml to run Supabase locally and a dist/ build that's static HTML/JS — drop it on any web host (nginx, Caddy, S3 + CloudFront, your home server).
Quick start
git clone https://github.com/MorningRevolution/orangerails
cd orangerails
docker compose up -d # starts Postgres + Kong + GoTrue + PostgREST + Realtime
supabase db push --db-url postgres://... # apply migrations
bun install && bun run build
# serve dist/ from your static host
A reference Caddy config is in caddy/Caddyfile.example.
Stealth Sync filter CDN
For on-chain xpub connections to work, the browser needs BIP 158 compact block filters. By default, the self-host build fetches them from stealth.orangerails.com (public CDN, no auth, no logs). You can:
- Use ours (default, recommended for most). Privacy posture is the same as Sparrow's default behavior with public Esplora.
- Run your own. Point your Bitcoin Core node at the filter generator in
tools/stealth-filter-server/and update the env varVITE_STEALTH_FILTER_CDN. Detailed setup: Stealth Sync — Architecture.
Upgrades
The repo follows the standard dev (staging) and prod (live) branch model. To pick up upstream changes:
git remote add upstream [email protected]:MorningRevolution/orangerails.git
git fetch upstream
git checkout dev
git merge upstream/dev
git push origin dev # auto-deploys to your dev URL
# verify
git checkout prod && git merge --ff-only dev && git push origin prod
Backup + restore
Same as any Postgres / Supabase deployment. The data at rest is ciphertext — backups are similarly opaque. Make sure your age / vault keys are backed up off-server, otherwise a database backup is useless to you.
A reference backup script: scripts/backup-vault.sh (writes encrypted dumps to S3-compatible storage).
Help
- Self-hosting questions → feedback.orangerails.com (tag: self-host)
- Security issues → SECURITY.md
- General support → support.orangerails.com