Docs menuTrust and grants

fabric experimental

Trust and grants

fabric's security model comes down to two ideas: mutual trust between machines, and per-peer grants that deny everything by default.

Identity

Each machine has a stable node id, a public key created the first time fabric runs. It's safe to share: it identifies the machine, it doesn't unlock it.

fabric id

Peers find each other by node id, not by address, so a laptop that moves between networks reconnects on its own.

Mutual, manual trust

To connect two machines, swap their node ids over a channel you already trust, and add each side to the other:

# on machine A
fabric add <machine-b-node-id> machine-b

# on machine B
fabric add <machine-a-node-id> machine-a

That's deliberate. There are no accounts, no pairing service and no automatic trust. Each daemon only accepts connections from node ids on its own list. Adding a machine to an existing mesh means doing this once per peer, in both directions.

Names like machine-b are local labels. Each machine can call a peer whatever it likes; trust always follows the node id.

Grants: deny by default

Trust gets a peer to the front door, not inside. Each peer has an allow list of the services it may reach: sync, shell, exec, send-file, or the name of something you exposed. An empty list grants nothing.

[[peers]]
id = "<node-id>"
name = "workstation"
allow = ["sync", "send-file", "pty-remote"]

You can grant services as you add a peer, with fabric add <node-id> workstation --allow sync,send-file. The allow-list is also a file you can edit by hand, so you can review it, keep it in configuration management, or provision it before fabric ever runs.

The target decides

Every check happens on the side being acted on. The far daemon checks its own grants before it opens a socket, starts a command or writes a file, and a caller can't talk its way past them.

Remote shell and exec need one more thing: an opt-in for the whole daemon on the target machine. Without it, no peer gets a shell, whatever its grants say.

Turning on shell gives every peer granted shell a real shell as the daemon's user. Keep grants tight, and only opt in where you mean it.