Your relay. Your server. Your rules.
Remoude’s default relay already sees only ciphertext. If that’s not enough, run the relay yourself — it’s a single zero-dependency file, and the encryption never depended on trusting it in the first place.
A relay that cannot read what it carries
The whole design assumes the relay is untrusted. Every message body is sealed with ChaCha20-Poly1305 using a key derived from your pairing secret via HKDF-SHA256 — and that key never leaves your Mac and your phone.
So a fully compromised relay still can’t read a single request or forge an “Allow.” Self-hosting doesn’t add a security guarantee so much as shrink the one piece of metadata anyone else could ever see: that a pairing id and a device token are linked.
- Sealed bodies — the AEAD key is on your devices only.
- The topic id is a one-way HKDF of the secret — never the secret.
- Zero dependencies, one file, Node ≥ 18 — auditable in an afternoon.
Two independent planes
Remoude splits into two hops you can host separately. Only one of them is unavoidably centralized — and even that one sees nothing but an opaque blob.
Message relay — fully yours
Carries questions, verdicts, and instructions, all sealed. No Apple key required. Self-host it and even the routing metadata stays on your own box.
Push wake-up — one hop
Only wakes your phone. An APNs key belongs to an Apple team, so the App Store build can only be woken by the author’s key — which sees a device token and an encrypted blob, nothing else.
From “just works” to “fully independent”
Default
Both planes on the hosted relay. Simplest — and it still only ever sees ciphertext.
Privacy-max
Self-host the message relay. Only the wake-up push touches the author’s service, and it learns nothing but a token and a blob.
Fully independent
Build the app with your own bundle id and APNs key, then run both planes. Nothing of the author’s is in the path.
One file. No npm install.
The relay is built-ins only. Point the Mac installer at your host and the pairing QR carries the URL to the phone — no app rebuild.
# relay-only (pub/sub, no pushes) — good for a quick look node server.mjs # turnkey on a fresh Ubuntu/Debian VPS: Node + Caddy + hardened systemd scp -r backend your.p8 root@vps:/root/ ssh root@vps cd backend && sudo bash deploy/setup-vps.sh # prompts for domain + APNs # then point your Mac at it — the QR hands the URL to the phone REMOUDE_RELAY=https://your-relay bash mac/install.sh
TLS is required — the pairing QR embeds an https:// relay URL. Fly.io, Railway, and Render work too: point them at server.mjs and mount the .p8 as a secret.
Don’t take our word for it. Read the relay.
It’s one zero-dependency file. The trust boundary is right there in the source.