Relays

A little always-on helper
that can never read a thing.

Haven works beautifully with nothing extra. But a relay makes it even more reliable β€” a small, always-on program that holds your circle's encrypted messages for friends who are offline, and hands them over later. It only ever sees scrambled bytes. It's optional, and it's free to run on hardware you already own.

Think of it as a mailbox

When you post something and a friend is offline, their copy has to wait somewhere until they come back online. A relay is that waiting room: a sealed mailbox that holds the encrypted envelope and delivers it the moment your friend reappears β€” even if you've gone offline by then.

Every envelope in the mailbox is locked end-to-end to your circle. The relay holds the envelopes; it has no key to open them.

And a switchboard

Sometimes two phones are both online but can't reach each other directly because of how home routers work. A relay can act as a switchboard, passing the encrypted traffic between them β€” perfect for live calls and big file transfers.

Same rule applies: it forwards sealed bytes it cannot decrypt. It's a pipe, not a reader.

Important and true: a relay can never read your posts, messages, photos, or calls. Everything is end-to-end encrypted before it ever reaches the relay. The relay only sees opaque, circle-sealed blobs β€” which is exactly the point.
Do you even need one?

Optional β€” but lovely to have.

Haven runs fine without any relay. Here's when running one is worth it.

Offline delivery

You and your friend are rarely online at the same time. A relay holds your post until they're back, so nothing's missed.

Better reliability

Behind a stubborn home router, or on a flaky connection? A relay smooths over the rough spots for calls and large files.

Your infrastructure

Run it on an old laptop or a $35 Raspberry Pi and your circle depends on no outside company at all. Fully yours.

Cost: running your own relay is typically $0 β€” it needs no inbound ports, no domain, and no cloud. An old laptop, a Pi, a NAS, or a free-tier cloud VM is plenty. If you ever want a dedicated box, a ~$5/month VPS is the most you'd ever spend. There is no Haven subscription and no operator fee β€” ever.
The easy way

Set up your own relay in two commands.

The haven-relay binary does everything: it links to your circle and serves both jobs β€” the live switchboard and the sealed mailbox β€” straight off your machine's disk, over Haven's own encrypted network. No cloud, no S3, no ports, no domain, no config.

Install it (one line)

On any always-on machine you own β€” old laptop, Raspberry Pi, home server, free cloud VM:

curl -fsSL https://wemiller.com/apps/haven/relay/install.sh | sh

Grab a relay link from the app

In Haven, go to You β†’ Advanced β†’ Relay β†’ β€œAdd a relay.” It shows you a relay link for your circle (it starts with haven-relay://circle#…). Copy it.

Go live (paste the link)

On the relay machine, paste your link in:

haven-relay run --link "haven-relay://circle#…"

That's it. It prints a QR + the link (so you can re-add it in the app any time), creates its own identity, makes a ~/.haven-relay/store folder, and starts serving your circle's sealed mailbox over Haven Net. Leave it running.

Restarting later? Just haven-relay run with no arguments β€” it remembers your link.

The relay only ever moves ciphertext. It cannot read your circle's content β€” that guarantee is proven by a test in the codebase where a relay stores a sealed blob and is shown to be unable to decrypt it.
For the brave

Deep dives, one click away.

Want it always-on, on specific hardware, or hosted in the cloud? Open whichever fits you.

Keep it always-on (a real background daemon)β€Ί

macOS β€” one command (installs a launchd agent, starts at login, auto-restarts):

sh setup-macos.sh                  # daemonize a relay already on your PATH
sh setup-macos.sh --link "haven-relay://circle#…"   # attach to your circle, then daemonize
# stop:
launchctl bootout gui/$(id -u)/com.haven.relay
rm ~/Library/LaunchAgents/com.haven.relay.plist

Linux β€” systemd user service (haven-relay.service ships in the relay/ folder):

mkdir -p ~/.config/systemd/user
cp haven-relay.service ~/.config/systemd/user/
loginctl enable-linger "$USER"          # keep running after logout
systemctl --user enable --now haven-relay
systemctl --user status haven-relay     # the relay's node id is in the log

Dead-simplest (cron at reboot):

( crontab -l 2>/dev/null; echo "@reboot $HOME/.local/bin/haven-relay run >/dev/null 2>&1" ) | crontab -
Self-host on a Raspberry Piβ€Ί

A Pi is the perfect always-on relay: tiny, silent, and yours. The install script auto-detects your Pi and downloads the right static binary:

  • 64-bit Raspberry Pi OS (Pi 3/4/5) β†’ aarch64-unknown-linux-musl
  • 32-bit Raspbian (Pi 2/3/4) β†’ armv7-unknown-linux-musleabihf
  • Pi Zero / Pi 1 β†’ arm-unknown-linux-musleabihf
curl -fsSL https://wemiller.com/apps/haven/relay/install.sh | sh
haven-relay run --link "haven-relay://circle#…"

Then keep it alive with the systemd-user or @reboot cron recipe above. Because the relay needs no inbound ports, your Pi works behind a normal home router with zero port-forwarding or firewall fiddling.

Run it on a VPS or a free cloud tierβ€Ί

Don't want to leave a machine on at home? Any always-on box works, and several are free forever β€” the relay needs no public endpoint, so even free tiers behind NAT are fine:

  • Oracle Cloud Always-Free β€” $0 forever, a generous Arm VM (use the aarch64 binary).
  • Fly.io β€” ~$0 on the free allowance; outbound-only, no public service needed.
  • Google Cloud e2-micro β€” free in one region; small but plenty for a relay.
  • A $5/mo VPS (Hetzner, RackNerd, etc.) β€” if you want a dedicated box. Still no public host required.

Install + run is identical to the easy path. To automate it, drop the two commands into the host's own provisioning β€” a cloud-init runcmd:, a Docker CMD ["haven-relay","run"], or an Ansible play that templates the systemd unit.

Storage backends β€” local disk, rclone, or S3β€Ί

Local disk is the default and needs nothing. If you'd rather park the sealed blobs elsewhere, the relay can use any of rclone's ~70 backends or a plain S3 endpoint:

haven-relay run --link "…"                                  # local disk (default)
haven-relay run --link "…" --rclone-remote mydrive:haven    # any rclone backend
haven-relay run --link "…" --s3 --s3-port 8333              # rclone serve s3 of a local dir
haven-relay run --link "…" --no-storage                     # connection relay only
haven-relay run --config relay.json                         # everything from a file

Important: rclone owns the provider auth (it reads its own rclone.conf). Neither the relay nor the Haven app ever holds a provider OAuth or refresh token. The sealed blobs are encrypted regardless of where they land.

The classic way β€” self-host or rent an S3 bucketβ€Ί

The original model: point Haven at any S3-compatible bucket. Spin one up locally with rclone serve s3 (rclone is MIT-licensed, one cross-platform binary):

curl -fsSL https://wemiller.com/apps/haven/relay/install.sh | sh -s -- --bucket          # Docker (any OS)
# or, from the relay/ folder:
sh install.sh --bucket            # Docker
sh install.sh --bucket --native   # native rclone binary (no Docker)

Or rent a managed bucket β€” you still hold the keys, the provider only ever sees sealed blobs:

  • Cloudflare R2 β€” no egress fees, generous free tier
  • Backblaze B2 β€” very cheap storage
  • AWS S3 β€” the original

Then in the app: You β†’ Advanced β†’ Storage β†’ Custom S3 bucket, paste the endpoint / bucket / keys, and turn on β€œVolunteer as tribute.” To reach it from outside your home network, expose the port via a router port-forward, Tailscale, or a small VPS β€” the traffic is already sealed, so plain HTTP is fine (HTTPS is nicer).

Build from sourceβ€Ί

The binary lives in the monorepo at core/haven-relay. It composes the existing haven-net (iroh transport, the local-disk blob mailbox, the S3-over-iroh tunnel) and p2pcore (crypto/identity) crates β€” it reinvents nothing.

cd core
cargo build --release -p haven-relay     # single static binary at target/release/haven-relay
cargo test  -p haven-net -p haven-relay   # forwarding + blob-store + tunnel + link tests

# cross-compile, e.g. a fully static Linux binary or Windows:
cargo build --release -p haven-relay --target x86_64-unknown-linux-musl
cargo build --release -p haven-relay --target x86_64-pc-windows-gnu
No surprises

Exactly what a relay can and cannot see.

Total honesty β€” because trust is the whole product.

What it can see

  • + The public node ids of frames it forwards (routing data that's already public)
  • + A random message id and hop count, used only to prevent loops and replays
  • + That a connection or upload happened, and the IP that made it (briefly, to move bytes)
  • + The opaque byte size of a sealed frame or blob

What it cannot see

  • Γ— The content of any post, comment, message, or media β€” all sealed end-to-end
  • Γ— Any content key or circle secret β€” relay links carry zero keys, by design
  • Γ— Which sealed blob is which post, or who's in a circle by name
  • Γ— Anything that would let it impersonate a member or read history
On your IP address, honestly: a relay does briefly handle your IP β€” that's physically how bytes reach you. Haven's hardened defaults mean it's never logged, never persisted, and never linked to your identity (peers authenticate to each other, never to the relay). For full IP hiding today, run Haven behind your own VPN; a built-in onion/Tor mode is on the roadmap, not yet shipped. The relay link itself carries no content key, no roster secret β€” so adding a relay can never turn it into a content reader. Read the full threat model.
Where your media lives

Your media, on storage you control.

Haven keeps your media in one of exactly two places β€” both yours, neither ours. A Haven relay (the free app on a PC, Mac, or a Raspberry Pi you leave running β€” or a friend's) holds it on its own disk, or you point Haven at your own S3-compatible bucket (AWS S3, Cloudflare R2, Backblaze B2, MinIO). Either way your media is end-to-end sealed before it's stored, so the relay or bucket only ever holds ciphertext β€” and Haven never holds a single one of your credentials.

  • A Haven relay β€” any official Haven app can host it, or run the tiny haven-relay on a Pi/server. Stores sealed blobs on its own disk; no cloud account.
  • Your own S3 bucket (S3 / R2 / B2 / MinIO) β€” endpoint + keys stored only in your device's secure store.
  • Run several relays β€” media is mirrored across them and reads fall back, so a circle survives any one relay going down.
  • We can't read, list, or revoke it β€” we hold no credentials and run no storage, by design.

Be the always-on home
for your circle.

One old laptop. Two commands. A more reliable Haven for everyone you love.