0006 — Snapshot naming convention, autosnapshot tool, and TZ surfacing
Status: accepted (2026-06-22) — ratified by maintainer; proposed 2026-06-04
Context
keyboot’s pre-boot rollback UI (ADR 0007) needs snapshots that it can (a) read unambiguously during recovery, (b) sort chronologically for retention, (c) group into a consistent point-in-time across the recursive dataset set, and (d) show to a human. A cross-distro userland tool (Debian/Alpine/Gentoo) creates them; the name is an interface contract between that tool and keyboot.
Decision
Name: <dataset>@<YYYY-MM-DD-HHMM>Z-<LABEL> — UTC, with an explicit Z,
24-hour. LABEL ∈ {FREQUENT, HOURLY, DAILY, WEEKLY, MONTHLY} (the
zfs-auto-snapshot model). Example:
rpool/ROOT/gentoo@2026-06-04-1600Z-DAILY.
- UTC, not local. Local time is non-monotonic across DST (the fall-back
hour repeats), which breaks lexical-sort retention and “keep newest N”, and is
ambiguous exactly when you’re recovering. UTC names sort
lexically == chronologically, making retention a trivial correct
sort | head -n -N | xargs zfs destroy. TheZremoves the “is 1600 UTC?” ambiguity at a glance.
Recursive + lockstep. Snapshots are taken zfs snapshot -r over the BE
subtree so every dataset shares the name atomically (same txg) — a
point-in-time is always complete. Retention/purge is recursive on matching
names so no per-child snapshot is orphaned (which would leave a rollback with a
hole). Per-LABEL retention counts (--keep=N), cron- or timer-driven.
The tool. A cross-distro POSIX-sh utility ships snap/list/purge verbs, driven
by cron (Alpine busybox-crond / Gentoo cronie / Debian) or systemd timers where
present. Installed by the install-os plugins (or a keyboot package). It is the
blessed snapshot path. The zfs binary is not shimmed to force naming
(that would break zfs send/sanoid/replication, ADR 0004); at most a warn-only
hint on non-conforming manual snaps.
TZ surfacing (UTC on disk, local at display). Names stay UTC (source of truth, always shown); keyboot additionally renders operator-local time. Chain:
- The BE carries a configured timezone (zone name, e.g.
America/Chicago). → Requirement:install-ossets/captures a TZ on the BE. install-osrecords the zone into keyboot’s/etc/keyboot/host.confon the ESP (timezone=America/Chicago).- keyboot bundles tzdata (zoneinfo) in its initramfs.
- The menu renders
2026-06-04 16:00Z (11:00 America/Chicago).
DST-correct local display needs the zone name + tzdata, not a fixed offset (a fixed offset is wrong half the year — the very confusion we’re removing).
Contract. The naming scheme is a versioned interface between the snapshotter and keyboot; changing it requires a superseding ADR.
Alternatives considered
- Local-time names: friendlier in isolation, but DST-ambiguous + non-monotonic → breaks retention and recovery reading. Rejected; local is a display-time convenience only.
- Fixed UTC-offset display (no tzdata): avoids bundling zoneinfo but is wrong across DST. Rejected; bundle tzdata.
- Shim
zfs snapshotto enforce the convention: breaks replication / sanoid /zfs send/ our own tool. Rejected (warn-only at most).
Consequences
- keyboot’s initramfs grows by tzdata (small, version-matched to the zoneinfo release).
host.confgains atimezone=field;install-osmust write it; the BE must have a timezone set (a new install step / profile field).- Non-conforming snapshots (replication, manual) still display by UTC mtime fallback; only conforming names group into the DAILY/WEEKLY point-in-time tiers in the menu.
- The recursive-set naming is what ADR 0007’s clone/rollback verbs key off — this ADR is load-bearing for those.