Setup guide
Use your own relay
RelayKey ships with a shared relay so tunnels work out of the box. If you would rather not depend on ours, you can point the app at a relay you control or pay for. Fifteen minutes, no code.
Reasons
Why you might do this
A relay only comes into play when your two machines cannot reach each other directly — most often when both ends sit behind a strict NAT, a corporate firewall, or mobile CGNAT. When that happens, every byte of your session travels through the relay, and someone pays for that bandwidth.
On the shared relay, that someone is us. So it is best-effort, rate-limited and metered: request too many credentials too quickly and you are throttled, and we make no promise about how much relayed time you get. It is there so that RelayKey works on day one, not so that you can run a workday of remote desktop through it.
Configure your own relay and two things change:
- Effectively unlimited relay time. Your limits become your provider's limits (or your own server's), not our fair-use brake. Cloudflare's free tier alone is generous enough for ordinary use.
- Your traffic stops transiting infrastructure we operate. Both the relay itself and the credential request move off our systems — see the next section for exactly how much that is worth.
You configure this in Settings → Relay. Choose a provider, paste the two fields it asks for, and use Test to confirm the relay answers before you rely on it. Leave it alone and you stay on the shared relay; there is nothing wrong with that.
The honest part
What a relay can and cannot see
Being accurate about this matters, because it is easy to oversell.
A relay cannot read your session. Everything RelayKey sends over WebRTC is encrypted end to end (DTLS) between your two machines. The relay forwards ciphertext and holds none of the keys. Your keystrokes, your screen, your files: not readable by the relay operator, ours included.
A relay does see who is talking, when, and how much. It necessarily observes the IP addresses of both endpoints, the times you connect, and the volume and timing of the traffic. That is metadata, and it is genuinely revealing — enough to show that a particular home connection talks to a particular office machine every evening, and for how long.
So the honest summary of moving to your own relay is: the confidentiality of your session content does not change — it was already end-to-end encrypted — but the party who gets to observe that metadata changes.
| Choice | Who observes your connection metadata |
|---|---|
| RelayKey shared relay | Cloudflare, plus us as the account holder |
| Your own Cloudflare or Twilio key | That provider, on your account. Not us. |
| Your own coturn server | Only you (and whoever hosts the machine) |
One more difference worth knowing: with your own Cloudflare or Twilio key, the app talks to that provider's API directly from your device to mint short-lived credentials. Your provider secret is never sent to us. With coturn there is no API call at all — see below.
Which should you pick?
They are good at different things, so we will not pretend one wins. Cloudflare is the easiest: two fields, a free tier, no server to run. coturn is the strongest if your motivation is confidentiality: no third party in the path at all, no API call to obtain credentials, and the secret you store grants relay access and nothing else. It costs you a small server and a few minutes of config.
Provider · easiest
Cloudflare — easiest to set up
Cloudflare Realtime includes a TURN service with a free monthly allowance that covers normal personal use. You need a Cloudflare account; you do not need a domain on Cloudflare.
- Sign in at dash.cloudflare.com.
- In the sidebar, open Realtime, then the TURN tab.
- Click Create to make a TURN key. Give it any name, for example
relaykey. - Cloudflare shows you a Key ID and an API Token. The token is displayed once — copy it now.
- In RelayKey: Settings → Relay → Cloudflare, paste both values, and press Test.
- Key ID
- A short hex string. Not secret.
- API Token
- The secret that goes with that key. Store it in RelayKey and nowhere else you do not need it.
That is everything the app asks for. It does not need your Cloudflare account email, your global API key, your Account ID, or a zone — and it should never be given them. A TURN key can only do one thing: mint relay credentials. If it leaks, delete it in the dashboard and create another; nothing else in your Cloudflare account is exposed.
Provider · no third party
coturn — most self-contained
coturn is the standard open-source TURN server. Run it on any small VPS with a public IP (the cheapest tier is plenty for one or two people) and no third party is involved in your connections at all.
Install it from your distribution's packages (apt install coturn on Debian or
Ubuntu), then replace /etc/turnserver.conf with this — it is a complete
working config:
listening-port=3478
tls-listening-port=5349
# Your server's PUBLIC IP. On a cloud VM whose NIC holds a private
# address, set both: external-ip=PUBLIC/PRIVATE
external-ip=203.0.113.10
realm=turn.example.com
# Time-limited credentials derived from a shared secret. No user
# accounts, no password database.
use-auth-secret
static-auth-secret=CHANGE_ME_TO_A_LONG_RANDOM_STRING
# Relay only. Do not let anyone use this box to reach private
# networks or to relay onto itself.
no-multicast-peers
denied-peer-ip=10.0.0.0-10.255.255.255
denied-peer-ip=172.16.0.0-172.31.255.255
denied-peer-ip=192.168.0.0-192.168.255.255
denied-peer-ip=169.254.0.0-169.254.255.255
denied-peer-ip=127.0.0.0-127.255.255.255
# Keep the logs boring.
no-cli
simple-log
Generate the secret with openssl rand -hex 32 and paste the output after
static-auth-secret=. Then systemctl enable --now coturn.
Ports to open
- 3478/udp and 3478/tcp — TURN. UDP is what actually gets used; TCP is the fallback on networks that block UDP.
- 5349/tcp — TURN over TLS, only if you configure certificates.
- 49152–65535/udp — the relay port range. This one is easy to forget and nothing works without it.
Open them in your cloud provider's firewall and in the host firewall if it has one.
What to put in the app
- TURN URL
turn:turn.example.com:3478— your host name or IP. Useturns:turn.example.com:5349if you set up TLS.- Shared secret
- Exactly the
static-auth-secretvalue from the config.
There is no username or password to enter, and this is the interesting part: coturn needs no API call whatsoever. The app takes your shared secret and computes a time-limited username and password locally, on your device, using the same HMAC that coturn will use to check them. Nothing is transmitted to obtain a credential — not to us, not to anyone. The first packet that leaves your machine on account of the relay is the connection to your own server.
That, plus the fact that a coturn shared secret grants relay access and nothing more, is why coturn is the strongest choice if confidentiality is what brought you to this page.
Caveat — keep the secret secret
Anyone who has it can use your server as a relay, on your bandwidth bill. Rotate it by
changing static-auth-secret, restarting coturn, and pasting the new value
into the app.
Provider · pay per gigabyte
Twilio
Twilio's Network Traversal Service works well and is billed per gigabyte, with no free tier worth planning around. Use it if you already have a Twilio account.
- Sign in at console.twilio.com.
- Copy your Account SID from the account dashboard. It begins with
AC. - Go to Account → API keys & tokens and click
Create API key. Name it
relaykeyand choose the Standard key type. - Twilio shows an SID beginning with
SKand a Secret, once. Copy both before leaving the page. - In RelayKey: Settings → Relay → Twilio, paste the Account SID in the first field and the credential in the second.
Exactly what to paste in the credential box
The credential field takes one string, and the app decides what it is by looking for a colon.
Recommended — API Key SID and Secret, joined by a colon:
SK0123456789abcdef0123456789abcdef:your_api_key_secret_here
That is the SK… value, then :, then the secret, with no spaces
and no quotes. Because the string contains a colon, the app uses it as the API key pair.
Also accepted, but not recommended — your Account Auth Token on its own:
your_account_auth_token
With no colon present, the app pairs the value with your Account SID and treats it as the Auth Token.
Caveat — prefer the API key, and here is why it is not a formality
Your Account Auth Token is the master credential for your entire Twilio account: it can send SMS and place calls at your expense, read your message history, and change billing. An API key can only be used for API calls, you can create one per application, and you can delete it in the console without touching anything else — so if it ever leaks, revoking it costs you nothing but a re-paste.
This matters most in the browser client, where the value is kept in browser storage. The macOS app stores it in the system Keychain, which is meaningfully better protected. In a browser, assume the credential is only as safe as the device and the browser profile it sits in — and put something revocable there.
- Account SID
- Begins with
AC. Identifies the account; not a secret by itself. - Credential
- Either
SK…:secret(recommended) or a bare Auth Token.
Questions
Questions
Does my provider secret ever reach RelayKey's servers?
No, and that is by design rather than by promise. With Cloudflare and Twilio the app calls
rtc.live.cloudflare.com and api.twilio.com directly
from your device — in the browser client, straight from the page, which is possible
because both APIs send permissive CORS headers. Your secret goes to the provider you chose
and to nobody else. It is also why the web client's Content-Security-Policy names exactly
those two hosts and no others: the list of places the page may talk to is short, fixed and
inspectable. With coturn there is no API call at all, so there is nothing to send
anywhere.
Do both machines need this configured?
No. Either end can supply the relay; whichever side has one offers it during connection setup. In practice, configuring it on the machine you sit at is enough.
Will my sessions get slower?
Only when a relay is actually used, and then it depends on where your relay is. A direct connection is always preferred and is unaffected. A relay adds a hop, so a server near you or near the remote machine is better than one on another continent — Cloudflare and Twilio both route to a nearby edge automatically; a single coturn box does not.
How do I know it is working?
Press Test in Settings → Relay: the app requests a credential and reports
what came back. During a live session the connection details show which kind of path was
selected — host or srflx means direct, relay means
your relay is carrying the traffic.
Can I go back to the shared relay?
Yes. Clear the fields, or switch the provider back to RelayKey relay. Nothing is kept on our side either way.