# mounts The shares and the occasional sources a machine mounts, and what it mounts and shares, read as tools (novox/hq ADR 0263, to-be design 52 "Shares and mounts", from research 038). It holds the node seat `node-mounts`, one holder per machine. A machine mounts only what its assignment names (ADR 0263 rule 5): nothing by default, and "every machine" is the same setting given once at the mesh-wide layer. A share of another machine comes from the provision `nfs-share`, which `nfs-server` provides on the machine that shares. ## What it owns - The packages `nfs-utils` and `cifs-utils`. - `/etc/mesh-mounts/mounts.conf`, placed by the mesh from the assignment: the settings `shares` and `sources`, the binding of `nfs-share` (`from`, the sharing machine, and `at`, where it is reached on the private network), the operator account, and where the module's secret is. - One `.mount` and one `.automount` unit per share or source, in `/etc/systemd/system`, named as `systemd-escape --path` names the mount point and opened by the marker `# Written by the mesh (module mounts, novox/hq ADR 0263).` A unit file without that marker is not the module's: it is never written over, stopped or removed, and the share whose mount point it holds is said as not set up. - The SMB logins, one file per source in the module's state directory, readable by root only. - `/var/lib/mesh-mounts/from-bus` (the bundle's: what the sharing machine exports) and `/run/mesh-mounts` (the processes': what was applied and what was found). What it never does: chown or chmod a mount point (it makes one that is missing, and nothing else), touch a mounted filesystem to look at it, or remove a pair because the sharing machine did not answer. A pair is removed only when the settings stop naming its mount point. The files a share serves are the operator's (ADR 0051): the module mounts them and owns nothing in them. ## The unit pair Only the automount is enabled (under `remote-fs.target`; a disk's under `local-fs.target`). The mount is never enabled: it is made at the first use of its mount point and released after ten idle minutes (`TimeoutIdleSec=600`). So nothing mounts at boot and nothing can fail a boot, and a mount point is always an autofs mount, so nothing writes into the empty directory under it. | kind | What | Options | TimeoutSec | |---|---|---|---| | a node's share, read-write | `:`, `Type=nfs4` | `vers=4.2,hard,timeo=150,retrans=3,_netdev` | 30 | | a node's share, read-only | `:`, `Type=nfs4` | `ro,vers=4.2,soft,timeo=150,retrans=3,_netdev` | 30 | | an SMB source | `///`, `Type=cifs` | `credentials=,iocharset=utf8,_netdev,nofail,uid=…,gid=…` | 10 | | a disk | `/dev/disk/by-uuid/`; the mount `BindsTo=` the disk's device | `nofail` | 10 | A share is read-only when the setting says `:ro` or the sharing machine exports it read-only. A read-write share is mounted hard, so a write is never dropped while the server is away. ## Settings Both are preferences whose default, `none`, mounts nothing (ADR 0262 allows no empty default). - `shares`: space-separated `name=mountpoint`, each optionally `:ro`. The name is the share's on the sharing machine; its path there comes from that machine over the bus, never from this setting. For example `library=/srv/library downloads=/srv/downloads:ro`. - `sources`: space-separated occasional sources, each optionally `:ro`: `name=smb:///@` or `name=disk:@`. For example `games=smb://192.0.2.76/Share@/mnt/games`. A mount point is an absolute, plainly written path, not a directory of the system's own (`/etc`, `/usr`, `/run`, …). An entry that cannot be read is said, and only that entry is left out. ## The secret `smb-credentials` is the module's own secret, issued by an outside party (the device's owner), so the mesh never makes one in its place. The operator gives it with `secret accept mounts smb-credentials --from `; the file holds one section per SMB source: ``` [games] username=… password=… domain=… (optional) ``` A source whose section is missing is not mounted, and is said with that remedy. No tool answers a password: the options, fstab lines and mountinfo the tools read are redacted. ## The processes and the bus - `apply` (root, judged by its unit) writes and removes the unit pairs and the logins, makes a missing mount point, reloads the service manager when anything changed and arms every automount, every 30 s. - `watch` (root, judged by `mounts_health`) tries each source without touching its mount point — TCP 2049 for a node's share, 445 for an SMB source, the device for a disk — and says each one's state. - The bundle (the operator account) reads what the sharing machine exports from `nfs-server`'s state `exports`, keyed by that machine, and leaves it for `apply`; a failed read keeps the last answer. It puts what `watch` found in the module's state `shares`, keyed by this machine. No module reads another's files (ADR 0260). The states: `armed` (the automount waits), `mounted`, `absent` (an occasional source that is not there — a state, not a fault), `unreachable` (should be there and is not), `failed` (tried and refused, or not set up; `why` says which). ## Health Unhealthy when a share that should always be there has been unreachable or failed for five minutes ("The share library of is not reachable from this machine since 19:21."), when an automount is not armed, when something the settings name cannot be set up (a missing login, a unit file that is not the module's), or when `watch` has not looked for two minutes. An occasional source that is absent is healthy, and said as not present since when. ## Taking over a hand-written line The operator's own fstab lines for a share are taken over only through `adopt`, on their word, and only once the module's own pair for the same mount point is written and its automount armed: the replacement works first, then the line goes. Without `confirm` it is a dry run. With it (and `why`), the line is commented out as `# adopted by the mesh (module mounts) on : `, the file as it was is kept as `/etc/fstab.mesh-adopted-` readable by root only, and the service manager reloads. The module never takes a line over on its own. ## What it reads - `/etc/fstab`, every line but swap. A credential in the options (`password=`, `pass=`, `passwd=`) is answered as `(redacted)`; a `credentials=` file is named and never opened. - The service manager's mount and automount units, with `systemctl list-units` and `systemctl show`: state, result, timeout, and whether each was generated from fstab or comes from a unit file. The kernel's own filesystems (proc, tmpfs, mqueue and the like) are left out. - `/proc/self/mountinfo`, for what is mounted now. A mount point is never opened or statted, so a network filesystem whose server is away cannot hang a call. - `/etc/exports`, `/etc/exports.d/*.exports` and the kernel's live export table `/var/lib/nfs/etab`. - The ZFS `sharenfs` and `sharesmb` properties, where `zfs` is installed. - The share sections of `/etc/samba/smb.conf`: path, valid users, read only or writable, force user and the like. The `[global]` section and every other setting are left out, so no password or password backend is answered. A file that cannot be read, and a command that does not answer, is said under `notes`, never answered as empty. ## Tools What only root may do (`mount`, `unmount`, `adopt`) goes through `sudo -n`, as the packet filter's and the service manager's tools do; a refusal by sudo is said as one. | tool | | answers | |---|---|---| | `mounts_list` | r | every mount point, its fstab line, its mount and automount units and whether it is mounted now; network filesystems marked; a network mount without automount or nofail said. Narrowed with `network` and `match` | | `mounts_exports` | r | the NFS exports declared and live, the ZFS share properties, the Samba shares, and whether nfs-server and smb are active; an export declared and not live, or live and declared nowhere, said | | `mounts_health` | r | the health check: healthy or not, with why, one sentence per finding | | `node-mounts.list` | r | the machine's mount points, and every share and source the module is asked to mount with its state, since when and why | | `node-mounts.test` | r | whether one share's or source's server answers now, tried without touching its mount point | | `node-mounts.mount` | a | mount one share or source now | | `node-mounts.unmount` | a | release one now; its automount stays armed | | `node-mounts.adopt` | a | take over one hand-written fstab line, as above |