← flue.sh

Remote access

How a machine becomes reachable from anywhere, on infrastructure you own, in one command.

The daemon never listens on the network

It listens on loopback and nothing else. Reaching a machine from somewhere else is one opt-in command, and what that command deploys belongs to you.

There is no hosted service to sign in to and no port to forward. Both ends dial out to a small Worker running in your own Cloudflare account, and the Worker connects them.

The protocol in one picture

│  daemon       on your machine
│               dials out, never listens
│     │
│     │  wss /daemon/<id>
│     ▼
│  Worker       in your Cloudflare account
│               one Durable Object per machine, one for the directory
│               forwards frames, holds no key
│     ▲
│     │  wss /client/<id>
│     │
│  browser      any device you paired
│               pins the daemon key
│
└─ Noise IK, end to end: browser initiator, daemon responder
   frame: [4B channel][payload]   inside: [1B kind][wire protocol bytes]

The Worker sits inside the encrypted run rather than at the end of it. It moves opaque frames between two sockets. The Noise channel runs between your browser and your daemon, with the daemon’s key pinned when the browser paired.

Setting it up

Run this once, on one machine. It checks the token, deploys the Worker and the web app, and joins this machine to it.

$ flue relay setup  ✓ token verified  ✓ account: Personal (a1b2c3…)  ✓ worker deployed: flue-relay  ✓ web app uploaded (128 files)  ✓ reachable at https://flue-relay.you.workers.dev  ✓ secret set  ✓ fleet key minted (stays on your machines; Cloudflare never sees it)  ✓ this machine joined as laptop (laptop-9f3a-3f9a12cd)

Every other machine runs the flue relay join line that setup prints. No token, nothing to deploy, and one relay fronts every machine you own. Each browser pairs once, from a QR code, and that pairing covers the whole fleet: the machine that runs it signs a certificate every other machine accepts, so a phone paired with your laptop can reach the Pi as well.

The full order to do things in is in the setup guide.

The API token stays on the machine that used it

It goes into one file only you can read. It is kept so that updating the relay never asks for it again, and you can delete it whenever you want it forgotten.

What it costs

A Worker, one Durable Object per machine, and one more holding the fleet directory. Cloudflare’s free plan is enough for personal use. The caps, the counters and how to read them are in the operator runbook.

What the relay can and cannot see

  • Cannot see: What is in any session. Keystrokes, output and scrollback are Noise ciphertext, and the relay holds no key for it.
  • Cannot see: Your daemon's private key, or any device's.
  • Can see: Who connected, when, and how much traffic moved each way. Enough to analyse a session, never to read one.
  • Can see: The pairing exchange. It crosses a cleartext control channel carrying a single-use token that lives two minutes.
  • Can see: The fleet directory. It holds each machine's id, name and daemon public key, and the whole revocation history. Reading it needs no credential, so anyone who learns the relay's address can read it, not only the operator.

There is one more thing worth knowing, and it is not about the cryptography. The web app is served by the relay origin, so you are trusting that origin to serve the published code. The FAQ says exactly what that means, because it is the honest limit of every end-to-end encrypted web app.

Prefer the direct path when you have one

Pairing through a relay is a trust decision about that relay. Pair over the daemon’s own address when the browser can already reach the machine, on the same network or over something like Tailscale. A phone that is not on the network has no such path, and there the relay is the only way to pair at all.

Other pages