#+TITLE: ZFS pre-pacman snapshot installer step (durable retention) #+DATE: 2026-06-29 #+SOURCE: handoff from the home project, 2026-06-29 * Problem A pacman =PreTransaction= hook snapshots =zroot/ROOT/default@pre-pacman_= before every transaction, but nothing prunes them. Sanoid doesn't manage them (they aren't =autosnap_= names), so they accumulated to 53 on velox between April and the 2026-06-29 health check. Unbounded, they fill the pool over time. * What's actually on velox vs. archsetup The live =/usr/local/bin/zfs-pre-snapshot= is *not* authored by archsetup — =git grep= for its content (=MIN_INTERVAL=, the pre-pacman =LOCKFILE= logic) finds nothing tracked. The =PreTransaction= hooks in the archsetup monolith (~lines 910, 1907, 1942) are the live-update guard, a different hook. The script appears hand-placed on velox. The 2026-01-17 security doc line "ZFS pre-pacman snapshots (already in install-archzfs)" is therefore *out of date* — archsetup does not install this. Incorporating the fix is a NET-NEW installer step, not a patch to an existing one. Correct that stale doc line as part of the work. velox was patched live (pruned to 10, script replaced with the self-pruning version below); live backup at =/usr/local/bin/zfs-pre-snapshot.bak-2026-06-29=. * Proposed installer step In the archzfs / ZFS-on-root install path, gated to ZFS-root installs (velox is the only ZFS daily driver; ratio is btrfs), install: 1. =/etc/pacman.d/hooks/zfs-snapshot.hook= — the =PreTransaction= hook that runs the script. *Not included in the handoff* — source it from velox (=/etc/pacman.d/hooks/zfs-snapshot.hook=) or write it. 2. =/usr/local/bin/zfs-pre-snapshot= — the =KEEP=10= self-pruning version below. Tests live in archsetup, so this wants an archsetup session and a ZFS-root VM test (=make test FS_PROFILE=zfs=), not a cross-project edit from home. * The script (KEEP=10 self-pruning version) #+begin_src bash #!/bin/bash POOL="zroot" DATASET="$POOL/ROOT/default" LOCKFILE="/tmp/.zfs-pre-snapshot.lock" MIN_INTERVAL=60 KEEP=10 # how many pre-pacman snapshots to retain (rollback safety for recent transactions) # Skip if a snapshot was created within the last 60 seconds if [ -f "$LOCKFILE" ]; then last=$(stat -c %Y "$LOCKFILE" 2>/dev/null || echo 0) now=$(date +%s) if (( now - last < MIN_INTERVAL )); then exit 0 fi fi TIMESTAMP=$(date +%Y-%m-%d_%H-%M-%S) SNAPSHOT_NAME="pre-pacman_$TIMESTAMP" if zfs snapshot "$DATASET@$SNAPSHOT_NAME"; then echo "Created snapshot: $DATASET@$SNAPSHOT_NAME" touch "$LOCKFILE" # Retention: keep only the most recent $KEEP pre-pacman snapshots, destroy older ones. # Sanoid does not manage these (they aren't autosnap_), so prune them here at creation time. zfs list -H -o name -t snapshot -s creation "$DATASET" 2>/dev/null \ | grep '@pre-pacman_' \ | head -n -"$KEEP" \ | while read -r old; do zfs destroy "$old" && echo "Pruned old snapshot: $old" done else echo "Warning: Failed to create snapshot" >&2 fi #+end_src * Open items before implementation - Source or write =/etc/pacman.d/hooks/zfs-snapshot.hook= (the trigger). - Decide the exact insertion point in the ZFS-root install path. - Add a ZFS-root VM test asserting the hook + script land and the script self-prunes past =KEEP=. - Correct the stale 2026-01-17 security-doc line.