// Self-host a relay
Run your own relay
When your devices can't reach each other directly, they talk through a relay. It only ever forwards encrypted data. Running your own decides who sees the metadata: IP addresses, timing, sizes and device public keys.
Rather not run a server? Use the free public relay (see its rules), or have a managed relay run for you. Want a hand running your own? See setup help.
// What you run
Two small programs on one Linux host
iroh-relay
From the iroh project. Forwards encrypted traffic between devices that can't connect directly.
Inbound TCP 443. UDP 7842 optional.
voidwire-mailbox
Holds short-lived encrypted items for devices that are offline. It has no keys to decrypt them, keeps them in RAM only, and drops them after 60 minutes by default.
Outbound only. No open ports.
Linux, always on
x86_64 or arm64. A small machine is enough.
A public address
Not behind carrier-grade NAT, or use a tunnel you control.
A DNS name
Such as relay.example.com. Dynamic DNS is fine.
Port 443 forwarded
TCP 443 to the host. UDP 7842 helps direct connections.
// Quick start
Docker in five steps
No copy of the repository needed. Images come from the release.
Get the release bundle
bashrelease v1.1.0 $ curl -fsSL https://github.com/voidwire-app/voidwire/releases/download/v1.1.0/voidwire-relay-docker.tar.gz | tar -xz $ cd voidwire-relay
Fill in your settings
bash.env holds no secrets $ cp .env.example .env # then set these three in .env VOIDWIRE_RELAY_HOSTNAME=relay.example.com VOIDWIRE_RELAY_CONTACT=you@example.com VOIDWIRE_RELAY_UDP=true
The contact address is only given to Let’s Encrypt. Set
UDP=falseif you can’t forward UDP 7842. The defaults keep it private: token access, and the relay gets its own Let’s Encrypt certificate on port 443. The guide covers running it behind your own HTTPS proxy instead.Start it
bash $ docker compose up -d
Copy the relay link
bashrewritten on every start $ sudo cat config/relay-link.txt voidwire:relay?r=https%3A%2F%2Frelay.example.com&m=…
The link includes your relay's access token. Treat it like a password.
Add it in the apps
PC: Devices → Relays, paste the link, Add. Android: Settings → Relays → Add relay. Then choose Make home. New pairings use your relay; move an existing pairing with Change relay… and confirm on both devices.
// Defaults
Private by default
Token access
By default only devices that have your relay link can use the relay. You can open it to everyone, or keep it on your LAN or VPN.
No logs
The shipped configs log nothing: Docker's log driver is off and the services run with RUST_LOG=off. Turn off access logs on any proxy you put in front.
Limits you set
Files up to 25 MB go through the relay by default (up to 2 GB if you allow it), at 1 MB/s per device. Devices on the same network don't use the relay at all.
// Updates
Updating, and Watchtower
To update by hand, unpack the new release's compose.yml and templates over the old ones, then docker compose pull && docker compose up -d. Your .env, token and data are kept. Back up data/mailbox/identity.key: it is your relay's mailbox ID, and losing it means re-adding the link on every device.
ghcr.io/nicholas-fedor/watchtower; the original containrrr/watchtower is archived. Label only the mailbox container. The relay image is pinned by digest on purpose, and a release that needs a newer relay ships a new compose.yml. Watchtower only updates the latest tag, and latest moves only on stable releases. Watchtower needs the Docker socket, which is root-level access to the host.// Why not Cloudflare Tunnel
Keep TLS on your relay
A Cloudflare Tunnel or proxied (orange-cloud) DNS record is the easy way to expose a home server. For a Voidwire relay it works against the reason you're self-hosting.
- A third party sits in the path. Cloudflare terminates TLS, so it sees who connects to whom, when and how much, and it sees your relay's access token. Content stays end-to-end encrypted, but the metadata you meant to keep is now with Cloudflare.
- No UDP. Tunnels and the proxy don't carry UDP 7842, so devices lose address discovery and fewer connections go direct.
- Terms of service. Cloudflare's self-serve terms restrict serving large non-HTML files through its proxy or Tunnel, so big transfers can put your account at risk.
What works: a DNS-only (grey-cloud) record pointing at your public IP, with the relay keeping its own TLS on TCP 443. Using Cloudflare for DNS only is fine. Behind CGNAT, use a tunnel or reverse proxy on a host you control.
Full guide: plain binaries, TLS behind a proxy, access control, Portainer, troubleshooting