Run your own node
One command on a small server, and no request reaches us on the path between your phone and your Mac.
What a node is for
On a local network nothing of ours takes part: the phone and the Mac find each other directly. A node matters away from home, and it does two things.
| Signalling | Two devices that already trust each other learn how to reach each other. The node sees fingerprints and addresses; it cannot read anything they say. |
|---|---|
| Relay | When the networks refuse a direct connection, the node forwards an opaque encrypted stream. It cannot decrypt it and keeps nothing. |
Roles are separate. A node with signalling only is a working configuration: relay is what costs bandwidth, and you can leave it off or take it from elsewhere.
What running your own gives you
- No metadata reaches us. Who connected to whom and when is the one thing our nodes can see; on yours, they cannot.
- Your node asks nobody for permission. The entitlement check is there to protect our bandwidth, so your node does not run it at all — it answers to you.
- We cannot suspend it. When the vendor's own services are paused, your node is untouched — by design, not by courtesy.
- Your region, your provider. Latency depends on distance; a node next to you beats a node next to us.
What it does not give you
Being straight about this is the point of the page. It does not replace the subscription. Connecting from outside your own network needs an active subscription wherever the traffic goes, because you are paying for the app and not for our bandwidth — the app checks that on your device before it dials anyone. It does not change the encryption — that was already end to end. And it does not remove work: the machine, its bandwidth and its updates are yours.
What you need
- A server with a public address. The smallest tier of any provider is enough: signalling is a few kilobytes per connection, and relay costs only what you actually relay.
- Docker, or nothing at all if you take the static binary.
- Five open ports: 7443/TCP, 3478/UDP, 3479/UDP for signalling, 7444/UDP and 7445/TCP for relay.
How
Issue a key, then run the node:
docker run --rm -v "$PWD/tls:/tls" ghcr.io/zavsegdatai/rendezvous keygen --out /tls
docker run -d --name rendezvous --restart unless-stopped \
-p 7443:7443 -p 3478:3478/udp -p 3479:3479/udp \
-p 7444:7444/udp -p 7445:7445 \
-v "$PWD/tls:/tls:ro" \
ghcr.io/zavsegdatai/rendezvous \
--tls-certificate /tls/cert.pem --tls-key /tls/key.pem \
--advertise your.server.address --roles signaling,relay
The first command prints the key fingerprint. Enter the address and that fingerprint in the agent's settings on the Mac, under the list of nodes. A public certificate authority is not involved: the device trusts the node by its pinned fingerprint, the way it trusts your Mac.
The image and the binary are published with each release of the node. Until that release is out, build from source — the step-by-step guide ships with the repository.
Keeping it current
The signalling exchange is versioned, and an unknown field is ignored rather than rejected — a node a version behind keeps working. A node several versions behind eventually will not, and updating is pulling a newer tag.