Your own relay server#
Your devices reach your session host in one of two ways. When they can see each other on the network, for example at home on the same Wi-Fi, they connect directly. When they cannot, because the server sits behind a router or your phone is on mobile data, they meet at a relay: a small server on the internet that passes their packets on.
tablet ──────────── direct, when possible ─────────── session host
│ │
└──────────────► relay.mightypainting.dev ◄─────────────┘
(forwards encrypted packets)
mpmux uses the relay relay.mightypainting.dev unless you set up your own.
That relay works and costs you nothing, so most people never need this page.
Do I need my own?#
The relay cannot read your terminal. Everything between your devices and the host is end-to-end encrypted, and the relay only forwards the encrypted packets. It holds no keys and no passwords.
What a relay does see is that your devices talk to each other, when, and how much. Run your own relay if:
- you want that information to stay on a server you control,
- you want the relay close to you (a server in your country or your company's network), for lower latency,
- you do not want to depend on someone else's server being up.
What you need#
- A small server with a public IP address: any cloud VM or a machine at home that the internet can reach. It needs little: a relay for a few devices runs on the smallest VM.
- A domain name pointing at it, for example
relay.example.com. - Ports 80 and 443 open (80 is only for getting the HTTPS certificate).
- About 15 minutes.
The steps below are for Ubuntu or Debian. They are the setup that runs
relay.mightypainting.dev.
Step 1: install the relay#
The relay is the iroh-relay program from the Iroh project. Install Rust
(https://rustup.rs), then build and install it:
cargo install iroh-relay --version 1.1.0 --features server --locked
sudo install -m755 ~/.cargo/bin/iroh-relay /usr/local/bin/iroh-relay
sudo useradd --system --no-create-home --shell /usr/sbin/nologin iroh-relay
Version 1.1.0 is the one mpmux 0.1.8 is tested with.
Step 2: configure and start it#
The relay itself listens only on the server's own address; Caddy (step 3)
takes the connections from the internet and adds HTTPS. Create
/etc/iroh-relay/config.toml:
enable_relay = true
http_bind_addr = "127.0.0.1:3340"
enable_quic_addr_discovery = false
enable_metrics = true
metrics_bind_addr = "127.0.0.1:9090"
access = "everyone"
[limits]
accept_conn_limit = 20.0
accept_conn_burst = 100
[limits.client.rx]
bytes_per_second = 4194304
max_burst_bytes = 16777216
The limits keep the relay from being overrun: at most 20 new connections a second, and 4 MB/s per device. That is plenty for terminals; raise them if many people share the relay.
Then a service that starts it with the server,
/etc/systemd/system/iroh-relay.service:
[Unit]
Description=Iroh relay for mpmux
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=iroh-relay
Group=iroh-relay
Environment=RUST_LOG=info,iroh_relay=info
ExecStart=/usr/local/bin/iroh-relay --config-path /etc/iroh-relay/config.toml
Restart=on-failure
RestartSec=5s
StateDirectory=iroh-relay
NoNewPrivileges=true
PrivateTmp=true
ProtectHome=true
ProtectSystem=strict
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
[Install]
WantedBy=multi-user.target
Start it:
sudo systemctl daemon-reload
sudo systemctl enable --now iroh-relay
Step 3: HTTPS with Caddy#
Caddy gets a certificate for your domain by
itself and passes the relay's connections on. Install it
(sudo apt install caddy), then put this in /etc/caddy/Caddyfile, with
your domain in both places:
{
# Iroh 1.1 and later send no server name when they connect; this tells
# Caddy which certificate to use for them.
default_sni relay.example.com
}
relay.example.com {
@relay_websocket {
path /relay
header Upgrade websocket
}
handle @relay_websocket {
reverse_proxy 127.0.0.1:3340 {
flush_interval -1
}
}
@relay_probe path /ping /generate_204
handle @relay_probe {
reverse_proxy 127.0.0.1:3340
}
handle {
respond "Not Found" 404
}
}
Do not leave out default_sni: without it, current mpmux versions cannot
connect. If Caddy serves other websites too, keep it pointing at the relay.
sudo systemctl reload caddy
Step 4: check it#
From any computer:
curl -i https://relay.example.com/ping
It should answer HTTP/2 200. If it does not, see
when something does not work.
Step 5: switch mpmux to it#
On the machine that runs your session host, install the host with your relay
(--restart applies it to a host that already runs; it ends the host's
shells, so save your work first):
mpmux-cli service install --remote --relay-url https://relay.example.com --restart
Check that the host uses it:
journalctl --user -u mpmux-sessiond -n 20 | grep "Iroh listener"
# mpmux-sessiond: Iroh listener online as … via https://relay.example.com/
Now pair your devices again (chapter 8): a device learns which relay to use from the invite, so devices you paired before still look for the host at the old relay. New invites carry your relay; nothing needs to be set on the devices themselves.
Devices on the same network as the host keep connecting directly; the relay
is only for the rest. To send everything through your relay, add
--relay-only.
When something does not work#
| Symptom | Likely cause |
|---|---|
curl …/ping times out |
The firewall or the cloud provider blocks port 443, or the domain does not point at the server yet (dig relay.example.com). |
curl reports a certificate error |
Caddy could not get a certificate: port 80 must be open for that, and the domain must point at this server. journalctl -u caddy says why. |
curl works, but devices cannot connect |
default_sni is missing in the Caddyfile, or the devices were paired before the switch: pair them again. |
| The host's log shows no "Iroh listener online … via" your relay | The service still has the old relay: run step 5 again with --restart. |
journalctl -u iroh-relay -f on the relay server shows connections as they
come and go.
For operators#
- Monitoring: the relay publishes Prometheus metrics on
http://127.0.0.1:9090/metrics(local to the server only), andhttps://relay.example.com/generate_204answers204while Caddy and the relay are up, for an uptime check. - Short-code pairing: short codes use a separate
rendezvous service,
pair.mightypainting.dev, which only passes encrypted handshake data. Pairing by link or QR code does not use it. You can run it yourself (mpmux-cli short-code-relaybehind Caddy on/relay);mpmux-cli session create-qr-code --relaytakes its address, whilempmux-cli pair short-codealways uses the default service. - Updates: keep
iroh-relayat a version mpmux is tested with; the release notes say when that changes.