Pairing a device
Pairing is how a new phone, tablet, or browser earns the right to talk to your daemon. It happens once per device and takes a few seconds. There are two ways to do it, and both reach the same key exchange with the same protection.
What pairing is
A daemon will not talk to a device it has never met. Pairing introduces the two: the device proves it holds a fresh pairing secret, both sides run a key exchange, and the daemon hands the device a private token to use from then on. After that the device is on the allow-list and every message between them rides an encrypted session. You only do this once per device. Lose the device or finish with it, and you revoke its token without touching any other.
Option 1: scan the QR
When the daemon starts it prints a QR right in the terminal. Open your phone camera or the codeout app and point it at the QR. It carries the daemon address and a short-lived pairing secret. Your device runs the key exchange, receives its own device token, and is paired. Nothing to type. This is the fast path, and it also gives you the man-in-the-middle check for free, which the next section explains.
Option 2: type the code
No camera, a QR that will not scan, or pairing across a screen-share where a camera is useless? The daemon also prints a human-typeable pairing code. Enter it in the app along with the daemon address and you get the same result as scanning.
$ codeout codeout -> http://localhost:8400 pair a device: scan the QR, or type this code K7QM-3FBR-9TZX expires in 5:00
In the app, choose to pair manually, enter the daemon address (for example http://localhost:8400 or your tailnet address), and type the code. The app runs the same libsodium key exchange the QR triggers and stores the device token it gets back.
What the code looks like
The pairing code is twelve characters of Crockford base32, grouped as XXXX-XXXX-XXXX so it is easy to read aloud and easy to type. Crockford base32 drops the letters that get confused with digits, so there is no squinting at whether that is a zero or an O, a one or an I. Three properties matter:
Confirm the daemon fingerprint
After the key exchange, the app shows a short fingerprint of the daemon you reached, four and four like ZMYR-C1HG. The daemon prints the same fingerprint in its terminal. Glance at both and check they match.
device paired: phone-15 daemon fingerprint: ZMYR-C1HG confirm this matches what the app shows
If they match, you are talking to your daemon and nothing in between. If they do not match, something is sitting in the path pretending to be your daemon, and you stop right there.
Why this defeats a man-in-the-middle
The fingerprint is derived from the daemon's real key material, which an attacker cannot fake. A machine that relays your pairing to slip itself into the middle would have to present its own keys, so the fingerprint your app computes would not match the one your terminal prints. The mismatch is the tell. Scanning the QR gives you this protection automatically, because the QR carries the daemon's own key material and the app verifies it without you lifting a finger. The manual flow simply makes the same check visible so you can do it by eye, which is exactly what you want when you typed the address yourself and a typo could have sent you somewhere unexpected.
What happens under the hood
- The daemon offers a pairing secret.
Short-lived and single-use, encoded in the QR and printed as the typeable code.
- Your device runs a key exchange.
It presents the secret and performs a libsodium
crypto_kxexchange with the daemon. - The app shows the daemon fingerprint.
You confirm you reached the right machine and not an impostor in the path.
- The daemon issues a device token.
The device stores it; the daemon records it in its allow-list against a name you can recognise.
- Every later message rides an encrypted session.
The device authenticates with its token and the channel is end-to-end encrypted from there on.
The pairing secret, QR or typed, is single-use and expires in five minutes. A photo of an old QR or a code from last week is worthless. To add another device, generate a fresh one.
Add another device
From a device that is already paired, or from the daemon terminal, request a new pairing QR or code and use it on the new device. Each device ends up with its own token, so you can tell them apart in the device list and revoke them one at a time.
Revoke a device
Lost a phone, or done with a borrowed laptop? Revoke its token. The daemon drops it from the allow-list immediately and that device can no longer connect or decrypt anything new. Other devices are unaffected.
$ codeout devices phone-15 paired 2d ago active work-laptop paired 6h ago active $ codeout devices revoke work-laptop revoked. work-laptop can no longer connect.