End-to-End Encryption with Pairing Keys
Messages between your machines (a2a, notify, hub and agent traffic) are end-to-end encrypted by default. A pairing key adds the missing piece: proof that the other end is one of your machines, so even a relay that swapped keys in the middle could not read them.
Why a pairing key
Each end makes a fresh key pair and the two ends agree on a session key, so the relay only ever carries ciphertext. The public keys are not signed, though: a relay that replaced them with its own could sit in the middle. With a pairing key, a random secret that only your machines hold, each end proves it holds the same secret before any message is sent, and the secret is mixed into the session key. The relay never sees the file. Your API key cannot do this job: the relay sees it on every request.
Prerequisites
- Two machines (here: your laptop and
work-laptop) with thenfltrCLI. - Each with its own API key of your account, saved with
nfltr config add-api-key(one key runs one connection at a time). opensslon the machine that makes the key.
1. Make the key
Use random bytes, at least 32. Not a passphrase: a guessable key can be tested offline.
$ openssl rand -hex 32 > pairing.key && chmod 600 pairing.key
2. Put the same file on every machine
Copy it yourself, over a channel you trust (scp, a password manager). Never send it through nfltr.
$ scp pairing.key work-laptop:pairing.key
3. Use it on both ends
On work-laptop, listen with the key:
$ nfltr a2a listen --name work-laptop --e2ee-key-file pairing.key
Listening as work-laptop for incoming A2A calls... (Ctrl+C to stop)
On your laptop, send with the same key. The listener echoes the message back:
$ nfltr a2a send work-laptop "hello, paired" --e2ee-key-file pairing.key
Connected as you.laptop, sending to work-laptop...
hello, paired
Instead of the flag you can set NFLTR_A2A_E2EE_KEY_FILE, for example in your shell profile:
$ NFLTR_A2A_E2EE_KEY_FILE=pairing.key nfltr a2a send work-laptop "hello again"
hello again
4. How to verify
A reply is the proof: an end with a pairing key refuses any peer that cannot prove the same key, before a message is sent. There is no silent fallback to unpaired encryption. Check it once by sending with a different key; it must fail:
$ openssl rand -hex 32 > wrong.key
$ nfltr a2a send work-laptop "hi" --e2ee-key-file wrong.key
Error: rpc error: code = FailedPrecondition desc = rpcclient: peer's A2A E2EE key failed pairing-key verification (a different key, or a relay in the middle); set the same --e2ee-key-file / NFLTR_A2A_E2EE_KEY_FILE on both ends
5. Nodes and hubs
Orchestration uses the same file. Give it to every node, and to the hub:
$ nfltr node join --max-agents 1 --e2ee-key-file pairing.key
node node-laptop joining nfltr.xyz: machine=laptop max_agents=1 harnesses=claude-code
level=INFO msg="node joined the relay" node_id=node-laptop
Commands that talk to the node need the key too, or the node refuses them:
$ nfltr orch nodes list --e2ee-key-file pairing.key
node-laptop machine=laptop agents=0/1 free=1 harnesses=claude-code
$ nfltr orch --e2ee-key-file pairing.key "<goal>"
$ claude mcp add nfltr -- nfltr mcp --toolset hub --a2a-e2ee-key-file /path/to/pairing.key
A node passes the file to the agents it launches, so they can talk to the hub; their model CLI does not get it. With a key, workers also refuse work that the relay itself sends (a task posted to the relay's task API); agents a hub spawns are not affected. More in Join machines as nodes.
6. Clean up
Stop the node and the listener with Ctrl+C. To rotate the key, replace the file on every machine and restart the listeners, nodes and hub.
# Ctrl+C in the nfltr node join terminal
# Ctrl+C in the nfltr a2a listen terminal on work-laptop
If it goes wrong
| You see | Meaning and fix |
|---|---|
peer's A2A E2EE key failed pairing-key verification (a different key, or a relay in the middle) | Both ends have a pairing key, but not the same one, or something in between swapped keys. Copy the same file to both ends again. |
peer did not authenticate its A2A E2EE key with the pairing key (no pairing key there, or an older nfltr) | Only this end has a key. Give the other end the file too (--e2ee-key-file or NFLTR_A2A_E2EE_KEY_FILE), and update it if it runs an older nfltr (nfltr update). |
A2A E2EE pairing key file short.key holds 3 bytes; want at least 32 bytes of random secret (e.g. openssl rand -hex 32) | The file is too short to be safe. Make a new one with openssl rand -hex 32. |
nfltr orch nodes list shows a node with status unavailable: … peer authenticates A2A E2EE with a pairing key this end does not have | The node has a pairing key and this end has none, or another one. Run nfltr orch nodes list --e2ee-key-file pairing.key with the node's key file. |
Error: rpc error: code = NotFound desc = target agent not connected | Nothing listens under that name. Start nfltr a2a listen --name work-laptop there first. |
What a pairing key does not do: it proves the peer is one of your machines, not which one. Anyone who has the file can take part as any of them, so treat it like a private key.
Next
- End-to-end encryption: what each track protects
- Send files and messages between machines