1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
#+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_<ts>=
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.
|