Skip to content

Self-host

The relay is dumb, zero-knowledge transit: it moves ciphertext and queues it for offline devices, and never holds a key. That’s true whether it’s the managed relay at api.chime.sh or one you run yourself — self-hosting is a deployment choice, not a different security posture. See Security for exactly what the relay can and can’t see.

Out of the box, chime points at the managed relay — zero infra for you. This is what Quickstart uses. If you want zero third parties in the path, or you’re offline/air-gapped, run your own relay instead; the two paths below are for that.

Terminal window
chime init --local

Starts a local chime relay instance and prints its URL. Subsequent pairing uses it once you export CHIME_RELAY_URL=... as instructed. This is the fastest way to develop against Chime without touching the managed relay.

Terminal window
chime relay [-addr :8080] [-db PATH]

The relay is a sub-command of the same single chime binary you already installed — there’s nothing extra to download. It’s a self-contained zero-knowledge transit server with an embedded SQLite store (-db :memory: for an ephemeral instance, useful for testing).

To make it reachable from your phone:

  • Behind a Cloudflare Tunnel (outbound-only, no inbound port to open) — bind the relay to 127.0.0.1:8080 and let cloudflared front it, with TLS terminated at the Cloudflare edge.
  • On a plain LAN or VPS URL — point the app at that URL directly during pairing.

Either way, the app is told the relay’s URL once, at pairing time, and uses it from then on.

A self-hosted relay has no accounts, no Chime Cloud, and no managed push gateway attached — the app gets messages while it’s foregrounded (or via its normal reconnect/poll behavior), rather than a background push wakeup. That tradeoff is the whole point for a “zero third parties” or air-gapped setup; end-to-end encryption is identical either way.

If you want to run your own copy of the exact production stack — Cloudflare Workers + Durable Objects, the same topology api.chime.sh runs — the relay/ and infra/ directories in the repo are the whole thing. Briefly, because the full runbook belongs in the repo, not copied here and left to go stale:

  • No VM, no SSH, no inbound port, no tunnel to operate. The relay is a stateless Cloudflare Worker in front of Durable Objects; Cloudflare runs the compute.
  • Two tools, two disjoint ownership boundaries. wrangler deploys the Worker script, the Durable Object classes, their bindings/migrations, and the push-gateway secrets. OpenTofu (infra/) owns the surrounding zone resources — the DNS custom domain that points your domain at the Worker, edge SSL/HSTS, a WAF ruleset, and an edge rate-limit ruleset. Tofu state is encrypted and stored in R2; secrets live in your OS keychain, never in files.
  • Ordering matters. The Worker has to be deployed with wrangler deploy before the first tofu apply — the custom domain binds to an already-existing Worker by name.

The full first-time-setup runbook, token scopes, rotation procedures, and troubleshooting table live in infra/README.md in the repo.

  • Security — the encryption stack and what the relay can and can’t see.
  • CLI — the full chime relay / chime daemon flag reference.