0005 — Dataset layout & boot-environment scope
Status: accepted (2026-06-22) — ratified by maintainer; proposed 2026-06-04
Context
/boot lives inside each BE on the encrypted pool (ADR 0003 / SPEC §3), so a BE
rolls back / clones as a unit. That raises the layout question: which datasets
travel with the BE (clone + roll back with it) and which are persistent
(survive a BE switch/rollback)? SPEC §3 locks “discover any mountable dataset; no
enforced layout” for boot-time discovery — this ADR sets the installer
default + the consistency rules, not a hard requirement keyboot enforces at
boot.
Two correctness constraints drive it:
/usr↔ package DB lockstep./var/lib/{dpkg,rpm,portage}records what is installed; if it can roll back independently of/usr, a rolled-back system has a package DB that disagrees with its binaries. So the package DB must move with the BE.zfs rollbackis per-dataset (ADR 0007): there is no atomic roll-back-these-five-datasets, so the fewer datasets that must move together, the simpler and safer rollback is.
Decision
BE root dataset = rpool/ROOT/<be>, and it INCLUDES /var (so the package
DB rolls back in lockstep with /usr). Only binary-independent leaves are
split out.
Two dataset classes, distinguished purely by where the dataset lives:
- BE-scoped — children of
rpool/ROOT/<be>(e.g.rpool/ROOT/<be>/home): cloned and rolled back with the BE. This is the default for/home. - Persistent — outside
rpool/ROOT(e.g.rpool/data/home,rpool/var/log,rpool/data/...): survive BE switch/rollback. For state that must not revert, and for datasets that want their ownrecordsize/props.
Installer default profile (extends the SPEC §13 interactive sketch; today
install-os creates only rpool/ROOT/<distro>):
rpool/ROOT/<be>— root incl./usr,/etc,/var(+ package DB)rpool/ROOT/<be>/home—/home, BE-scoped by defaultrpool/var/log— persistent,sync=always,exec=off- (opt)
rpool/data/home— persistent/home(the opt-out) - (opt)
rpool/var/lib/docker,rpool/data/...— persistent, tuned per use
recordsize and other props are set per dataset where it pays (e.g. a DB
dataset at 16K vs the 128K default) — the reason to split a leaf at all.
The /var line: stays in the BE — package DB, and anything whose state must
match the binaries. Split out only genuinely-independent leaves: /var/log,
/var/cache, /var/lib/<db>, /var/lib/docker.
Refinement (2026-06-05, GL#17): parameterize; defer the default profile
The profile above is the recommended reference, not what the installer bakes
in. Per operator decision, the layout is parameterized and the installer
default stays minimal (rpool/ROOT/<distro> only, as today). Operators /
Ansible spell out the leaves they want:
install-os --dataset '<ds>[:<mnt>][:<props>]'(repeatable). The{BE}token expands to the BE dataset, so--dataset '{BE}/home:/home'is BE-scoped and--dataset 'rpool/var/log:/var/log:exec=off'is persistent. Props (incl.recordsize,compression, user props likecom.sun:auto-snapshot=false) are passed through. Datasets are created after the BE is mounted,canmount=onso they auto-mount on first boot.- Swap is a separate param (
--swap, follow-up: per-distro fstab + the zvol-deadlock caveat).
This avoids the installer making fleet policy decisions; an opinionated default
profile (turning the table above into a one-flag preset) is deferred to a
later pass. So /home placement is no longer a baked default — it’s whichever
--dataset form the operator passes (the two-homes rule, expressed explicitly).
Alternatives considered
/varfully separate / persistent: breaks the/usr↔package-DB lockstep. Rejected — split only binary-independent leaves./homealways persistent (outside the BE) by default: safest against data loss, but a BE rollback then can’t give a consistent point-in-time (home stays current). Made the opt-out (rpool/data/home), not the default. The BE-scoped default is safe because the default rollback verb is non-destructive clone-and-boot (ADR 0007) — current home is never destroyed.- Flat single dataset (no splits): no sub-system rollback, no per-dataset tuning. Rejected.
Consequences
- A BE-scoped
/homeforks per BE (an upgrade clone gets a CoW copy; work in the new BE isn’t in the old). Acceptable given clone-and-boot rollback + frequent snapshots (ADR 0006/0007); workstation operators who dislike it flip torpool/data/home. install-osmust grow a dataset profile (it currently creates onlyrpool/ROOT/<distro>). The profile is operator-overridable.- The “what stays in
/varvs splits out” rule is documented so rollbacks stay internally consistent. - Boot-time discovery stays layout-agnostic (SPEC §3); this ADR governs the installer + the consistency rules only.