mirror of
https://github.com/oqyude/nixos.git
synced 2026-10-11 22:37:25 +03:00
CRITICAL BUG #2 in storage guard, caught by live test v8 on sapphira (2026-10-10). RequiresMountsFor=/home/ooyude/External in the unit file told systemd that the service depends on the mount. When the mount was gone and the service was started, systemd's dependency resolver AUTOMATICALLY REMOUNTED the filesystem to satisfy the dependency — THEN checked ConditionPathIsMountPoint. The condition saw the just-remounted filesystem and evaluated to true. Service started on empty external storage. Guard completely bypassed. This is a subtle interaction: - ConditionPathIsMountPoint is a TEST (true/false evaluation) - RequiresMountsFor is a DEPENDENCY (systemd must make it true) A guard should be a TEST, not a dependency that makes the test trivially pass. Remove the dependency. The condition alone is sufficient for both boot-time and runtime checks: - Boot: mount unit starts via local-fs.target, condition is true - Runtime: if mount disappears, condition becomes false on next start attempt. Without RequiresMountsFor, systemd doesn't auto-recover, so the guard fires. Ordering should be expressed via After= in the consumer's systemd.services block (not in the shared helper), e.g.: systemd.services.postgresql.after = [ "home-ooyude-External.mount" ]; Live test v8 sequence (before this fix): 1. umount /home/ooyude/External → OK, gone from /proc/mounts 2. findmnt /home/ooyude/External → exit=1, not in table 3. systemctl start postgresql → STARTED (guard bypassed) 4. journal: no ConditionPath error (service started successfully) This is the second guard bug found by live testing in this session. The first one was the '!' prefix inversion. Both were invisible to nix eval, both only visible at runtime. Lesson reinforced: guards MUST be live-tested, not just statically evaluated. Recovery: v8 test reverted state via emergency_recovery trap (remount + restart all services). System healthy at 10/10.