Files
felhom.eu/REPORT.md
T

3.7 KiB

felhom.eu — task reports

Overwrite this file with a summary of the most recent task only (uniform with the other repos; not cumulative). The cumulative hub history lives in hub/CHANGELOG.md; the scripts history lives in scripts/CHANGELOG.md.

SPIKE — NAS verify mechanisms + NFS squash matrix — 2026-07-11

Class: spike (findings doc is the only artifact; no production code touched). Record: documentation/audits/SPIKE-nas-verify-2026-07-11.md. Baselines (read-only): felhom-agent 300f06722b (v0.80.0, netmount.go = recipe under test), felhom-controller 3db9126121 (v0.112.0, the probe container), felhom.eu 8ca1272db6.

Verdicts (all five questions answered live, evidence in the record)

  • Q1 — in-guest automount trigger: PASS (make-or-break). A pct exec ls AND a docker bind-mount access from inside guest 9201 both wake the host systemd automount (~1 s); content correct, nfs4 propagates host→guest; idle-unmount + re-trigger proven. Q1c open item: whether a trigger installed BEFORE guest start carries through at boot needs a restart-window test (no restart permitted this spike).
  • Q2 — controller uid-1000 probe: PASS. docker exec -u 1000:1000 chain proof + setpriv --reuid 1000 mechanism proof (same syscalls as syscall.Credential); CapEff a80425fb has SETUID/SETGID; server-side files land 101000:101000.
  • Q3 — Route A: ACCEPTED-with-caveats. all_squash to an arbitrary server uid (1050) gives the guest-uid-1000 app full read/create/rename/hardlink/delete. Caveats: guest sees nobody:nogroup; chown fails immediate-clean EPERM; chmod SUCCEEDS and persists server-side. q3c pinned the June WRONG case: anonuid without all_squash never applies to non-root traffic — wire uid 101000 fails on others-perms. Consumer guidance must require the "map/squash ALL users" mode, not just an anon-uid field.
  • Q4 — error taxonomy + timing: full table in the record. Headlines: NFSv4 returns the IDENTICAL No such file or directory for nonexistent vs not-permitted exports (merge those error categories); dead server = systemd timeout at 90 s (systemd kills mount.nfs before its 2-min retry — no diagnostic string); retry=0 recommended for the PRODUCTION unit (dead-server verify 90 s→3.1 s with clean No route to host; guest on-demand access 91 s→3.8 s ENODEV; happy path untouched; autofs retries fresh per access). SMB splits cleanly: error(13)=credentials, error(2)=share name. Budget (Q4-vii): verify cannot ride the agentapi global 15 s timeout (client.go:87) — worst case is systemd's 90 s; give AddNetStorage its own longer-lived path or async status-poll, ~120 s end-to-end, agent-side systemctl start bounded at ~95 s.
  • Q5 — plain-user SMB: PASS. Stock user + rw share, zero server-side uid config, all 8 probe steps pass INCLUDING hardlink (on Debian Samba/ext4 — re-verify on a real appliance); server-side ownership = the authenticated account; guest sees forced 1000:1000/0664.

Safety rails held

Isolated scratch root /srv/nas-spike2/ on 180 (backups .bak-nasspike2); no iptables/network manipulation (unreachable case = verified-unused 192.168.0.199); no guest restart; spike mounts only under /mnt/felhom-drives/spike2-*. Teardown verified: exports back to pre-count 2, smb.conf sections 6, spike users/scratch/units/creds/mountpoints all gone, 0 spike2 mounts on host and in guest, controller 0.112.0 healthy, spike-pulled alpine image removed.

Next: the production "NAS verify-before-commit + UI redesign" TASK is written by the operator side on these findings (STOP honored — no production work started).