4.7 KiB
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-specinstall-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_msdosnewfs
- mounts them
- stages the declarative Fruix rootfs
- copies the closure and referenced
/frx/storeitems into the installed root - installs
loader.efitoEFI/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:
targettarget_kindtarget_deviceesp_deviceroot_deviceinstall_metadata_pathdisk_capacityroot_size- declared/materialized FreeBSD source metadata
- closure/native/runtime store metadata
Validation harnesses
Added:
tests/system/phase18-install-operating-system.scm.intests/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:
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
msdosfsfilesystem - the installed root partition is
ufs EFI/BOOT/BOOTX64.EFIexists on the target/run/current-systempoints at the installed closure in/frx/store- the installed closure exists under the target's
/frx/store /var/lib/fruix/install.scmexists 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:
sshdis running/usr/local/etc/rc.d/fruix-shepherd onestatusreports 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_64under TCG, higher SMP did not help this validation path and in practice regressed boot responsiveness - the harnesses therefore keep
QEMU_SMPconfigurable but retain a conservative default of2for 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.