Add non-interactive Fruix installation flow
This commit is contained in:
167
docs/reports/phase18-minimal-installation-flow-freebsd.md
Normal file
167
docs/reports/phase18-minimal-installation-flow-freebsd.md
Normal file
@@ -0,0 +1,167 @@
|
||||
# Phase 18.1: minimal non-interactive Fruix installation flow on FreeBSD
|
||||
|
||||
Date: 2026-04-03
|
||||
|
||||
## Goal
|
||||
|
||||
Phase 18.1 turns Fruix's existing closure/rootfs/image machinery into a real installation workflow.
|
||||
|
||||
The goal is not a polished installer yet. The goal is a repeatable, non-interactive install path that can:
|
||||
|
||||
- take a declarative Fruix system,
|
||||
- partition and format a target disk or image,
|
||||
- populate it with the selected system closure,
|
||||
- install boot assets,
|
||||
- and leave the target bootable.
|
||||
|
||||
## Implementation
|
||||
|
||||
### New install spec and installer entry point
|
||||
|
||||
Added in `modules/fruix/system/freebsd.scm`:
|
||||
|
||||
- `operating-system-install-spec`
|
||||
- `install-operating-system`
|
||||
|
||||
The installer currently supports:
|
||||
|
||||
- raw image-file targets
|
||||
- `/dev/...` block-device targets
|
||||
|
||||
For raw image-file targets, Fruix now:
|
||||
|
||||
- creates/truncates the target image
|
||||
- attaches it with `mdconfig`
|
||||
- creates a GPT layout
|
||||
- adds:
|
||||
- an EFI partition
|
||||
- a FreeBSD UFS root partition
|
||||
- formats them with:
|
||||
- `newfs_msdos`
|
||||
- `newfs`
|
||||
- mounts them
|
||||
- stages the declarative Fruix rootfs
|
||||
- copies the closure and referenced `/frx/store` items into the installed root
|
||||
- installs `loader.efi` to `EFI/BOOT/BOOTX64.EFI`
|
||||
- writes install metadata to:
|
||||
- `/var/lib/fruix/install.scm`
|
||||
|
||||
### Rootfs staging was factored for reuse
|
||||
|
||||
Added internal helper:
|
||||
|
||||
- `populate-rootfs-from-closure`
|
||||
|
||||
This lets image generation and installation reuse the same rootfs staging logic while differing in how the final target is created.
|
||||
|
||||
### New CLI action
|
||||
|
||||
Added user-facing command support in `scripts/fruix.scm`:
|
||||
|
||||
- `fruix system install`
|
||||
|
||||
New system option:
|
||||
|
||||
- `--target PATH`
|
||||
|
||||
Install metadata now emits machine-readable fields including:
|
||||
|
||||
- `target`
|
||||
- `target_kind`
|
||||
- `target_device`
|
||||
- `esp_device`
|
||||
- `root_device`
|
||||
- `install_metadata_path`
|
||||
- `disk_capacity`
|
||||
- `root_size`
|
||||
- declared/materialized FreeBSD source metadata
|
||||
- closure/native/runtime store metadata
|
||||
|
||||
### Validation harnesses
|
||||
|
||||
Added:
|
||||
|
||||
- `tests/system/phase18-install-operating-system.scm.in`
|
||||
- `tests/system/run-phase18-system-install.sh`
|
||||
|
||||
The Phase 18 install validation uses the already-validated boot mode:
|
||||
|
||||
- `freebsd-init+rc.d-shepherd`
|
||||
|
||||
This keeps the install-flow validation focused on installation mechanics rather than on the separate Shepherd-as-PID-1 boot path.
|
||||
|
||||
## Validation
|
||||
|
||||
Passing validation:
|
||||
|
||||
- `PASS phase18-system-install`
|
||||
- regression re-check:
|
||||
- `PASS phase17-source-revisions-qemu`
|
||||
|
||||
Validated install result:
|
||||
|
||||
```text
|
||||
target_image=/tmp/fruix-phase18-install.CyrgKc/installed.img
|
||||
target_kind=raw-file
|
||||
disk_capacity=12g
|
||||
root_size=10g
|
||||
closure_path=/frx/store/ee486985797103aa5d3eeeef7f2cf066bcbd6839cd81083dbe626a594e71a703-fruix-system-fruix-freebsd
|
||||
freebsd_source_kind=git
|
||||
freebsd_source_ref=stable/15
|
||||
freebsd_source_commit=332708a606f6bf0841c1d4a74c0d067f5640fe89
|
||||
materialized_source_store=/frx/store/a892afb425235de71c9da38884e2ebdba5dafd3a1993f432fe7c446f5af2151f-freebsd-source-stable15-install-source
|
||||
native_base_store_count=3
|
||||
install_metadata_path=/var/lib/fruix/install.scm
|
||||
esp_fstype=msdosfs
|
||||
root_fstype=ufs
|
||||
shepherd_status=running
|
||||
sshd_status=running
|
||||
install_flow=non_interactive
|
||||
init_mode=freebsd-init+rc.d-shepherd
|
||||
install_target_boot=ok
|
||||
```
|
||||
|
||||
The harness verified all of the following:
|
||||
|
||||
- GPT partitioning is created on the target image
|
||||
- the installed ESP is a valid `msdosfs` filesystem
|
||||
- the installed root partition is `ufs`
|
||||
- `EFI/BOOT/BOOTX64.EFI` exists on the target
|
||||
- `/run/current-system` points at the installed closure in `/frx/store`
|
||||
- the installed closure exists under the target's `/frx/store`
|
||||
- `/var/lib/fruix/install.scm` exists and records:
|
||||
- closure path
|
||||
- store items
|
||||
- install spec
|
||||
- materialized source provenance via the referenced closure/store items
|
||||
- the installed system boots under local QEMU/UEFI/TCG
|
||||
- after boot:
|
||||
- `sshd` is running
|
||||
- `/usr/local/etc/rc.d/fruix-shepherd onestatus` reports running
|
||||
- activation completed successfully
|
||||
|
||||
## QEMU SMP note
|
||||
|
||||
I tested the idea of defaulting local QEMU validation to 8 vCPUs.
|
||||
|
||||
Result:
|
||||
|
||||
- for local `qemu-system-x86_64` under **TCG**, higher SMP did not help this validation path and in practice regressed boot responsiveness
|
||||
- the harnesses therefore keep `QEMU_SMP` configurable but retain a conservative default of `2` for TCG-based local validation
|
||||
|
||||
This keeps the validated path reliable while still allowing manual override when useful.
|
||||
|
||||
## Result
|
||||
|
||||
Phase 18.1 is complete.
|
||||
|
||||
Fruix now has a real, repeatable, non-interactive installation workflow for FreeBSD systems:
|
||||
|
||||
- declarative system input
|
||||
- native/source-driven closure output
|
||||
- partition/format/install to a target image or disk
|
||||
- bootable installed result
|
||||
|
||||
The next step is Phase 18.2:
|
||||
|
||||
- a minimal Fruix-managed installer environment that can boot into an install context and run this workflow from within that environment.
|
||||
Reference in New Issue
Block a user