193 lines
6.1 KiB
Markdown
193 lines
6.1 KiB
Markdown
# Phase 19.2: explicit installed-system generation layout on FreeBSD
|
|
|
|
Date: 2026-04-04
|
|
|
|
## Goal
|
|
|
|
Phase 19.2 is about making Fruix's installed-system generation model more explicit.
|
|
|
|
The target here is not yet a full Guix-equivalent in-place `switch-generation` workflow.
|
|
|
|
The immediate goal is to stop relying mainly on harness knowledge and implicit symlink expectations by recording installed deployment state more explicitly on disk.
|
|
|
|
## Decision
|
|
|
|
Fruix now follows this design direction:
|
|
|
|
- keep Guix-like **semantics**
|
|
- do not mirror Guix's installed-system/profile layout **mechanically 1:1**
|
|
|
|
What Fruix preserves from Guix:
|
|
|
|
- immutable closure identity
|
|
- rollback-friendly deployment semantics
|
|
- explicit current deployment pointer
|
|
- GC-root-style retention links
|
|
- `/run/current-system` as the active runtime boundary
|
|
|
|
What Fruix intentionally changes:
|
|
|
|
- installed-system generation state is represented as a small metadata-bearing directory
|
|
- the generation model is recorded under a Fruix-native path
|
|
- deployment metadata and provenance are easier to inspect directly without reconstructing intent from symlink layout alone
|
|
|
|
## Implemented layout
|
|
|
|
Installed systems now record an explicit generation root under:
|
|
|
|
- `/var/lib/fruix/system`
|
|
|
|
Current validated initial layout:
|
|
|
|
```text
|
|
/var/lib/fruix/system/
|
|
current -> generations/1
|
|
current-generation
|
|
generations/
|
|
1/
|
|
closure -> /frx/store/...-fruix-system-...
|
|
metadata.scm
|
|
provenance.scm
|
|
install.scm
|
|
```
|
|
|
|
Installed systems now also create explicit retention roots under:
|
|
|
|
- `/frx/var/fruix/gcroots`
|
|
|
|
Current validated initial layout:
|
|
|
|
```text
|
|
/frx/var/fruix/gcroots/
|
|
current-system -> /frx/store/...-fruix-system-...
|
|
system-1 -> /frx/store/...-fruix-system-...
|
|
```
|
|
|
|
Important compatibility point:
|
|
|
|
- `/run/current-system` still points directly at the active closure in `/frx/store`
|
|
|
|
That means the new explicit generation model strengthens deployment metadata without changing the already-validated runtime contract used by activation, rc.d integration, and service startup.
|
|
|
|
## Code changes
|
|
|
|
### `modules/fruix/system/freebsd/media.scm`
|
|
|
|
Added explicit generation-layout helpers:
|
|
|
|
- generation metadata object writer
|
|
- generation provenance object writer
|
|
- generation layout population for staged rootfs trees
|
|
|
|
The system rootfs staging path now creates explicit generation state during rootfs population.
|
|
|
|
That affects:
|
|
|
|
- direct rootfs materialization
|
|
- direct image materialization
|
|
- direct installation targets
|
|
- target rootfs payloads staged inside installer images
|
|
- target rootfs payloads staged inside installer ISOs
|
|
|
|
The direct install path now also refreshes the generation layout after writing:
|
|
|
|
- `/var/lib/fruix/install.scm`
|
|
|
|
so the generation directory carries the same install metadata.
|
|
|
|
### Installer runtime path
|
|
|
|
The generated installer runtime script now also copies install metadata into:
|
|
|
|
- `/var/lib/fruix/system/generations/1/install.scm`
|
|
|
|
on the installed target.
|
|
|
|
This keeps direct-install and installer-mediated installs aligned.
|
|
|
|
## New validation harness
|
|
|
|
Added:
|
|
|
|
- `tests/system/run-phase19-generation-layout-qemu.sh`
|
|
|
|
This harness builds on the already-passing direct install validation from Phase 18.1 and then verifies the new explicit generation layout on the installed target image.
|
|
|
|
Passing validation:
|
|
|
|
- `PASS phase19-generation-layout-qemu`
|
|
|
|
Validated result summary:
|
|
|
|
```text
|
|
closure_path=/frx/store/882fb4a9fbb05f08e77de29f70ca50f3c01dd29141e72688d32770a3172747e7-fruix-system-fruix-freebsd
|
|
current_generation=1
|
|
current_link=generations/1
|
|
generation_closure=/frx/store/882fb4a9fbb05f08e77de29f70ca50f3c01dd29141e72688d32770a3172747e7-fruix-system-fruix-freebsd
|
|
gcroot_current=/frx/store/882fb4a9fbb05f08e77de29f70ca50f3c01dd29141e72688d32770a3172747e7-fruix-system-fruix-freebsd
|
|
gcroot_generation=/frx/store/882fb4a9fbb05f08e77de29f70ca50f3c01dd29141e72688d32770a3172747e7-fruix-system-fruix-freebsd
|
|
run_current_system_target=/frx/store/882fb4a9fbb05f08e77de29f70ca50f3c01dd29141e72688d32770a3172747e7-fruix-system-fruix-freebsd
|
|
generation_layout=explicit
|
|
generation_layout_validation=ok
|
|
```
|
|
|
|
The harness verified all of the following:
|
|
|
|
1. the installed target contains:
|
|
- `/var/lib/fruix/system`
|
|
2. the current generation pointer exists and resolves to:
|
|
- `generations/1`
|
|
3. the generation directory contains:
|
|
- `closure`
|
|
- `metadata.scm`
|
|
- `provenance.scm`
|
|
- `install.scm`
|
|
4. the generation closure link points at the installed closure in `/frx/store`
|
|
5. the generation metadata records:
|
|
- closure path
|
|
- install metadata path
|
|
6. the generation install metadata records:
|
|
- closure path
|
|
- materialized source provenance
|
|
7. explicit retention roots exist under:
|
|
- `/frx/var/fruix/gcroots/current-system`
|
|
- `/frx/var/fruix/gcroots/system-1`
|
|
8. those GC-root-style links point at the same active closure
|
|
9. `/run/current-system` still points directly at the active closure path
|
|
10. existing install boot validation remains intact
|
|
|
|
## Relationship to Guix
|
|
|
|
Fruix now has an explicit installed-system generation model, but it is still intentionally not a byte-for-byte clone of Guix's on-disk conventions.
|
|
|
|
The design choice is:
|
|
|
|
- preserve Guix's deployment semantics
|
|
- use a Fruix-native metadata-oriented representation where that improves clarity for operators and debugging
|
|
|
|
That decision is documented separately in:
|
|
|
|
- `docs/GUIX_DIFFERENCES.md`
|
|
|
|
## Current limitations
|
|
|
|
This phase does **not** yet add:
|
|
|
|
- multi-generation switching in place
|
|
- a `switch`/`reconfigure` command
|
|
- an operator-facing rollback command that flips from current to a previous installed generation without redeploy
|
|
- explicit `rollback` link management beyond the initial current-generation layout
|
|
|
|
Those belong to later Phase 19 work.
|
|
|
|
## Conclusion
|
|
|
|
Phase 19.2 is complete.
|
|
|
|
Fruix now has a clearer, explicit installed-system generation and retention-root model on FreeBSD:
|
|
|
|
- generation metadata is recorded under `/var/lib/fruix/system`
|
|
- retention links are recorded under `/frx/var/fruix/gcroots`
|
|
- `/run/current-system` remains stable as the runtime boundary
|
|
- and the model is documented in Fruix-native terms for Guix-familiar operators
|