v0.16.0 takes Lagu Remote out of the house through Lagu Relay. It's the first thing Lagu runs on servers of its own, so I wanted to write up how it keeps your remote private. If you don't use Lagu Remote away from home, nothing here affects you, so feel free to skip it. https://lagu.fm/relay covers what it does; this post is the how, and what it doesn't protect. https://status.lagu.fm shows how each relay is doing.
The short version
- Lagu Relay only carries Lagu Remote's control messages: play, pause, seek, the queue, and what's playing. Your music, covers and library browsing still go straight to your own Plex server, as they do away from home today.
- Every message is sealed on one device and opened on the other. The relay passes along sealed bytes it can't read, and so does Cloudflare, which sits in front of the relays.
- The relay can see your IP address, when you connected, for how long, and how many bytes went by. It has no accounts and never talks to plex.tv.
- It's on for phones once a paired host offers it (switch in Settings › Remote), and on Apple TV, Android TV and Fire TV while Lagu Remote is on. Desktop is off until you turn it on.
- Off on a computer or TV closes every relay connection to it at once. Off on a phone keeps it to your own network. Removing a phone or resetting pairing on the host cuts that phone off at once.
It's free, there's no account, and you don't need Plex Pass. Phones paired on 0.15 pick up relay access the next time they connect at home, no re-pairing.
How it's protected
How do the two ends know they're talking to each other? And if a key leaks later, can old sessions be read?
When you pair at home (QR code or six-digit PIN), the computer or TV hands your phone its public key and saves your phone's public key in its paired-device list. On every connection, each side has to prove it holds the private key that matches what the other side saved. If your phone isn't on the list, the host closes the connection without replying. If the host's reply doesn't open on your phone, it isn't the host you paired with. Think of two people who swapped signatures in person and check them on every letter.
For old sessions: both sides make a fresh throwaway key for every connection, and it's mixed into the keys that seal the messages. Those session keys only exist for that one connection and never leave the two devices.
Could someone record a message and send it again?
After the handshake, every message carries a number that only goes up, in each direction. The receiving side only accepts a number higher than the last one it accepted, so a repeated or reshuffled message is refused. Replaying the first handshake message gets a reply, but nothing after it can be read or forged, and the host acts on nothing until a message passes the check.
Could someone get in the middle while I pair?
The QR code, the default, is the strong path. It contains a fingerprint of the host's certificate, and your phone locks onto that certificate before it sends the PIN, so the keys arrive over a connection it has already checked.
The typed PIN is the weaker one. Your phone has only an address and the PIN, so it trusts the first certificate it sees and sticks with it after that. Someone already on your home network, attacking during the roughly three minutes while you type, could in theory get in the middle. My take: a typed PIN is fine on a network you trust; use the QR on one you don't. A fix (a short code that confirms the connection) is on my list, but it isn't in v0.16.0.
The PIN is random, lasts three minutes, works once, and wrong guesses get slowed down, so there's room for about 33 guesses at most against a million codes. Over the relay you can only pair by QR, after turning on "Pair over Lagu Relay" on the host (off by default). That adds a single-use key to the code that lasts ten minutes. A typed PIN never pairs over the relay.
Has anyone checked this?
No outside security firm has audited Lagu or the relay yet. I reviewed the design and code in several passes with tooling before release. A security review of Lagu Remote in August found no critical or high issues and three hardening items, the typed PIN one included. The relay got three review passes in October, and the bugs they found were fixed before release. Desktop, Apple TV, iPhone and Android are all tested against the same set of known messages, so each one seals and opens them the same way. If you have the background and want to poke at it, I'd welcome it 🙂
What it doesn't protect
- The connection between your phone and your Plex server. The relay does nothing for it; it works the same as before.
- Your IP address and timing. The relay and Cloudflare both see those, as with any connection. It's a relay, not an anonymity service.
- Typed PIN pairing at home, and no outside audit yet (both above).
What the relay keeps
The list of connected hosts, with the host's random relay id and your phone's key id, lives in memory and is gone when you disconnect. Device ids and message contents are never stored. Connection logs hold your IP only as a one-way hash whose key changes every midnight UTC and is never saved, and they're deleted after 7 days. Counters (connections, bytes, errors, response times) are kept for 13 months, with no ids or addresses.
How long it'll be around
There are 17 relays today: Montréal, Jacksonville, Kansas City, Hillsboro, Bogotá, Santiago, São Paulo, London, Frankfurt, Warsaw, Timișoara, Johannesburg, Dubai, Mumbai, Singapore, Tokyo and Sydney. Your computer or TV picks whichever answers fastest and moves to another within about 15 seconds if that one dies. Your phone follows within about a minute.
The whole fleet of small servers costs about $125–130 a year, cheap enough to run on Lagu's own sales. A heads up: a relay nobody uses will likely be dropped, and the fleet will follow where people are. If none of them are near you, status.lagu.fm can send in the ping your browser measures to each one, and that counts toward where the next one goes.
For the curious
- X25519 to agree keys, ChaCha20-Poly1305 to seal each message, HKDF-SHA256 to derive.
- The handshake is Noise IK shaped: phone to host, host to phone, then data, with the ephemeral-ephemeral exchange mixed into the session keys.
- The message counter is 64-bit and doubles as the nonce, authenticated with the frame type as associated data. A failed message doesn't advance it; gaps are allowed since the relay may drop an over-budget frame.
- A host proves itself to the relay by signing a fresh random nonce with an Ed25519 key (separate from its TLS identity, regenerated by Reset pairing). Its relay id is the hash of that public key.
- A phone needs a host-signed ticket (90 days at most), handed out only at home over the LAN and checked by the relay against the live host. A stolen ticket without the phone's private key can't finish the handshake; at worst it holds one of the host's 4 relay slots until the host drops it (no data within 10 seconds).
- Per connection: 2 KiB/s sustained with a 64 KiB burst, 16 KiB max message, 10 minute idle close, and per-IP caps on connections and failures. Cloudflare's rate rule is the outer limit.
As always, if you have questions or something here doesn't add up, reply here or open a new thread and I'll answer as best I can.