Files
hq/04-ISSUES/169-a-machine-shares-its-files-and-the-mesh-does-not-know/00-report.md
T
jschoubben a0a930b1cd Issue 169: file sharing is a core seat, one per protocol
The operator's call: a node-scoped system seat family (node-nfs-share,
node-smb-share, …) defined by the control plane, one per protocol as
package registries are (ADR 0109), so several modules occupy it and a
machine may hold both.
2026-09-30 13:50:31 +02:00

4.2 KiB

status, opened, located-in, fixed-by, amended-design
status opened located-in fixed-by amended-design
open 2026-09-30
mesh-catalog (no module shares a path over the network)
hq 02-DECISIONS (a file-share seat, per ADR 0126, is a module's own to define)

169 — A machine shares its files, and the mesh does not know

What was observed

ace serves the operator's media library to the home network with two host services no module declares and HAL never managed either:

/etc/exports:   /storage/media  192.168.1.0/24(rw,sync,root_squash,…)     nfs-server active, :2049
/etc/samba/smb.conf: [media] path = /storage/media/  valid users = media   smb active, :139/:445

Two LAN clients were connected at survey (2026-09-30). The library itself is operator data (ADR 0051: ~40 TB on ZFS, the mesh owns nothing about it — issue 153 is about modules reaching it in place).

Under the mesh as it stands, this arrangement has no expression and one failure mode:

  • Nothing declares the listens. At converge ace the filter is the sum of what modules listen on (ADR 0045); 2049 and 445 are nobody's, so the shares close — silently, for the two clients that mount them.
  • Nothing owns the configuration. /etc/exports and smb.conf are hand-written files on one machine; a second machine sharing a directory would be written by hand again.
  • Nothing can consume it. A module on another node that wanted the library (a player, an indexer, a backup) has no requires to state and no binding to read; it would mount by a hand-typed host and path.
  • The clients are LAN devices, so this also meets issue 154 (no reach for the machine's own network).

The proposal (the operator's, 2026-09-30)

File sharing is a core seat — a role each machine has, defined by the control plane — and, as with package registries (ADR 0109), one seat per protocol, so several modules occupy the family:

seat scope delivers held by
node-nfs-share node nfs-share an nfs module
node-smb-share node smb-share a samba module
… (node-webdav-share) node … whatever comes next

Named for their scope (ADR 0121), one holder per node (ADR 0110), each carrying its protocol (ADR 0129). A machine may hold both — nfs and samba on ace — and one module may hold several (0109: "gitea may hold several seats at once"). Adding a protocol is adding a seat and a provision, not widening one.

The holder module:

  • declares the exported paths as accesses (ADR 0051: it owns nothing about them — never creates, chowns or removes), and which paths as the assignment's settings (ADR 0046/0112);
  • writes the share configuration (/etc/exports, smb.conf) as mesh-managed files and drives the units, like dnsmasq/sshd do for theirs;
  • declares its endpoints (nfs 2049/tcp; smb 445/tcp, …) so the reach — internal, or the LAN once 154 has an answer — is the assignment's, and converge keeps them open;
  • provides the seat's provision, serving the export path(s), so a consumer on another node requires nfs-share (or smb-share) and reads ${bound:nfs-share:at} and the path from its binding instead of a hand-typed mount — a pair credential where the protocol has one (a Samba user), none for sec=sys NFS.

What it would settle: ace's library becomes reachable from the mesh by declaration, the two host services get an owner, converge stops being a trap for them, and a media module on another machine (or a backup on novox) can mount the library the way it binds a database today.

Open questions for the decision

  • Whether an NFS export over the overlay is an internal reach of the same endpoint or a second export line — NFS authorises by client address, so the mesh range and the LAN range are two entries in one file.
  • How a consumer's binding expresses a path to mount (today bindings carry at, port, as and whatever the provider serves), and whether one share can serve several paths.
  • Whether the seat should exist before its first module (a system seat is a decision, ADR 0110) — the decision that adds the two seats can be the one that accepts this proposal.