Running a Self-hosted relay
A Self-hosted relay is a relay you run yourself and enroll in your
Organization. It talks to Switchboard over the public internet at
https://switchboard.mux.global, so you don’t need a private network, a VPN,
or a custom build.
The relay is moq-relay, from the open-source
moq-dev/moq project, version 0.15 or later.
The moq-relay README
covers installing it from packages or Docker, and has example configurations.
The fastest way to start is the moqdev/moq-relay Docker image, shown in
step 3.
Once it’s enrolled, your relay calls Switchboard for three things:
| What | When | Endpoint |
|---|---|---|
| Enrollment | Once, when you set it up | POST /cluster/enroll |
| Peer discovery | About once a second | GET /cluster/connect |
| Admission | For every session, and every 30 seconds while it lasts | POST /auth |
Switchboard answers Admission from the location nearest your relay, and keeps answering while the rest of Switchboard is down or being deployed. If a peer discovery poll fails, your relay keeps the peers it already has.
A Self-hosted relay carries only your Organization’s Namespaces. Whatever
token a Client brings, the relay won’t let it publish or subscribe outside
acme/, or whatever your Namespaces are.
1. Get a Relay enrollment token
Section titled “1. Get a Relay enrollment token”You need an API key for your Organization, and the Organization’s id from
GET /v1/organizations. Get the key from the dashboard at
https://app.caprid.com/app, or see Credentials.
The examples below use Organization 4, which owns the Namespace acme.
curl -X POST https://app.caprid.com/v1/organizations/4/enrollments \ -H "Authorization: Bearer $SB_API_KEY" \ -d '{"url": "https://relay1.example.com:4443/", "region": "iad", "gateway": false}'The response includes the token, which is shown only this once:
{"id": "7c1e...", "token": "sbe_...", "expires_at": 1790301600, ...}The token fixes everything about the relay’s Node, and the relay can’t change any of it later:
urlis where other relays connect to it, and where Clients connect too, unless you setclient_url.regionis which of your Regions the relay joins. Relays in the same Region all connect to each other. If you leave it out, the relay joinsdefault. Region names are yours alone, so youriadhas nothing to do with anyone else’s.gatewayis whether the relay may be picked to carry its Region’s traffic to your other Regions.client_urlis optional. Set it when Clients reach the relay at a different address from the one its peers dial, for example whenurlis a private name. Whatever hands relay addresses to your Clients can read it from the Node.
The token expires after an hour if nobody uses it. To change that, set
expires_in, in seconds, up to a day. To revoke it early, call
DELETE /v1/organizations/4/enrollments/{id}.
2. Exchange it for a Node key
Section titled “2. Exchange it for a Node key”On the relay’s host, run this once:
curl -X POST https://switchboard.mux.global/cluster/enroll \ -d '{"token": "sbe_..."}' > enrollment.json
jq -r .node_key enrollment.json > /etc/moq/node.key # sbn_...jq '{cluster, auth}' enrollment.jsonThe second jq prints the settings for relay.toml:
{ "cluster": { "node": "https://relay1.example.com:4443/", "connect_api": "https://switchboard.mux.global/cluster/connect?jwt=sbn_..." }, "auth": {"url": "https://switchboard.mux.global/auth?jwt=sbn_..."}}The token works only once, and this response is the only time you see the
Node key, so keep it. If you lose the Node key, enroll the relay again as a
new Node, and delete the old one with
DELETE /v1/organizations/4/nodes?url=....
3. Configure the relay
Section titled “3. Configure the relay”Write /etc/moq/relay.toml:
[listen]# Where Clients and peers connect. The certificate has to be valid for the# host in [cluster] node.bind = "[::]:4443"tls.cert = ["/etc/moq/cert.pem"]tls.key = ["/etc/moq/key.pem"]
[cluster]# The values enrollment returned, unchanged.node = "https://relay1.example.com:4443/"connect_api = "https://switchboard.mux.global/cluster/connect?jwt=sbn_..."# The Node key, as a file. The relay presents it to the peers it connects to.token = "/etc/moq/node.key"
[auth]# Switchboard decides every session here.url = "https://switchboard.mux.global/auth?jwt=sbn_..."relay.toml contains the Node key twice, in those URLs. Protect it the same
way you protect node.key.
Don’t set [connect] tls.insecure. That setting turns off certificate checks
for the relay’s calls to Switchboard as well as to its peers, and
switchboard.mux.global has a publicly trusted certificate. Use it only if
your relays present self-signed certificates to each other.
To run the relay with Docker, put relay.toml, node.key and your
certificate in /etc/moq, then run:
docker run -d --name moq-relay --restart unless-stopped \ -p 4443:4443/udp \ -v /etc/moq:/etc/moq:ro \ moqdev/moq-relay:0.17.9 /etc/moq/relay.tomlThe image takes the path to its config file as its only argument. QUIC runs over UDP, so open UDP port 4443, or whichever port you bound, in your firewall.
4. Check that it works
Section titled “4. Check that it works”- Polling. A few seconds after the relay starts,
GET /v1/organizations/4/nodeslists the Node with"live": true. - Peers. With two or more relays in a Region, each relay’s log shows it connecting to the others.
- Admission. A Client token from
POST /v1/namespaces/acme/tokensworks through the relay. A token for another Organization’s Namespace, or no token, is refused.
Remove a relay
Section titled “Remove a relay”DELETE /v1/organizations/4/nodes?url=https://relay1.example.com:4443/
deletes the Node and its Node key. Switchboard refuses the relay on its next
poll, and its peers drop it. To bring the relay back, enroll it again.
Current limits
Section titled “Current limits”- Your Regions can’t link to Mux’s relays yet. Until they can, a Namespace’s
platform_peeringsetting has no effect. - To move a relay to another Region, or to change whether it can be a gateway, enroll it again.