Add Fruix bootable installer environment
This commit is contained in:
191
docs/reports/phase18-installer-environment-freebsd.md
Normal file
191
docs/reports/phase18-installer-environment-freebsd.md
Normal file
@@ -0,0 +1,191 @@
|
||||
# Phase 18.2: minimal Fruix-managed installer environment on FreeBSD
|
||||
|
||||
Date: 2026-04-04
|
||||
|
||||
## Goal
|
||||
|
||||
Phase 18.2 builds on the Phase 18.1 host-driven install primitive.
|
||||
|
||||
The goal here is not a polished live installer. The goal is a small Fruix-managed environment that can:
|
||||
|
||||
- boot as its own Fruix system,
|
||||
- carry a selected target Fruix system closure and rootfs payload,
|
||||
- install that target system onto a second disk from inside the booted environment,
|
||||
- and leave the installed target bootable.
|
||||
|
||||
## Implementation
|
||||
|
||||
### New installer-environment API
|
||||
|
||||
Added in `modules/fruix/system/freebsd.scm`:
|
||||
|
||||
- `installer-operating-system`
|
||||
- `operating-system-installer-image-spec`
|
||||
- `materialize-installer-image`
|
||||
|
||||
The installer environment is derived from the selected target operating system, but with installer-specific behavior:
|
||||
|
||||
- host name defaults to:
|
||||
- `<target-host-name>-installer`
|
||||
- init mode is kept on the currently most stable installer path:
|
||||
- `freebsd-init+rc.d-shepherd`
|
||||
- the installer image root label is distinct:
|
||||
- `fruix-installer-root`
|
||||
- `sshd` is enabled for operator/debug access
|
||||
- installer accounts needed for SSH/DHCP are ensured if absent:
|
||||
- `sshd`
|
||||
- `_dhcp`
|
||||
|
||||
### Bootable installer image contents
|
||||
|
||||
`materialize-installer-image` now produces a bootable image that contains:
|
||||
|
||||
- the installer system closure and its runtime store closure
|
||||
- the selected target system closure
|
||||
- the selected target system's referenced store items
|
||||
- a prebuilt target rootfs tree staged under:
|
||||
- `/var/lib/fruix/installer/target-rootfs`
|
||||
- installer plan/state files under:
|
||||
- `/var/lib/fruix/installer`
|
||||
- installer helper scripts:
|
||||
- `/usr/local/libexec/fruix-installer-run`
|
||||
- `/usr/local/etc/rc.d/fruix-installer`
|
||||
|
||||
The booted installer environment runs a background rc.d job that:
|
||||
|
||||
- partitions the selected target disk
|
||||
- creates EFI + UFS filesystems
|
||||
- copies the staged target rootfs onto the target
|
||||
- copies only the target system's required store items into the target `/frx/store`
|
||||
- installs the target's `loader.efi`
|
||||
- writes `/var/lib/fruix/install.scm` on the target
|
||||
- records installer state in:
|
||||
- `/var/lib/fruix/installer/state`
|
||||
- logs to:
|
||||
- `/var/log/fruix-installer.log`
|
||||
|
||||
### New CLI action
|
||||
|
||||
Added in `scripts/fruix.scm`:
|
||||
|
||||
- `fruix system installer`
|
||||
|
||||
Added option:
|
||||
|
||||
- `--install-target-device DEVICE`
|
||||
|
||||
This action materializes a bootable installer image in `/frx/store` and emits metadata for:
|
||||
|
||||
- installer image paths
|
||||
- installer closure path
|
||||
- target closure path
|
||||
- target install device
|
||||
- installer state/log paths
|
||||
- declared/materialized FreeBSD source metadata
|
||||
- target/native/runtime store metadata
|
||||
|
||||
### FreeBSD virtio target-device detail
|
||||
|
||||
A practical detail surfaced during validation:
|
||||
|
||||
- the correct FreeBSD virtio block device node for the second QEMU disk is:
|
||||
- `/dev/vtbd1`
|
||||
|
||||
The earlier Linux-flavored guess:
|
||||
|
||||
- `/dev/vtblk1`
|
||||
|
||||
was wrong for the actual FreeBSD device node namespace in this environment.
|
||||
|
||||
The installer defaults were updated accordingly.
|
||||
|
||||
### Small image-builder correctness fix
|
||||
|
||||
While doing this work I also fixed `materialize-bhyve-image` so its generated UFS filesystem label respects the requested:
|
||||
|
||||
- `root-partition-label`
|
||||
|
||||
instead of always hardcoding:
|
||||
|
||||
- `fruix-root`
|
||||
|
||||
This matters for the installer image because it needs a distinct root label while the target disk still uses the normal target label.
|
||||
|
||||
## Validation
|
||||
|
||||
Added validation artifacts:
|
||||
|
||||
- `tests/system/phase18-installer-target-operating-system.scm.in`
|
||||
- `tests/system/run-phase18-installer-environment.sh`
|
||||
|
||||
Passing validations:
|
||||
|
||||
- `PASS phase18-installer-environment`
|
||||
- regression re-check:
|
||||
- `PASS phase18-system-install`
|
||||
- regression re-check:
|
||||
- `PASS phase17-source-revisions-qemu`
|
||||
|
||||
Validated installer-environment result:
|
||||
|
||||
```text
|
||||
installer_image_store_path=/frx/store/fb038dbf5dac2ad1bb767a264d3a268915f489b936dc5dd32425645102d3da48-fruix-installer-image-fruix-freebsd-installer
|
||||
installer_disk_image=/frx/store/fb038dbf5dac2ad1bb767a264d3a268915f489b936dc5dd32425645102d3da48-fruix-installer-image-fruix-freebsd-installer/disk.img
|
||||
installer_disk_capacity=16g
|
||||
installer_root_size=14g
|
||||
target_disk_capacity=12g
|
||||
install_target_device=/dev/vtbd1
|
||||
installer_closure_path=/frx/store/ea821f20b579684877fdc86a2a1e80485cf2b12d9d32f74f42e368d738c2ad4d-fruix-system-fruix-freebsd-installer
|
||||
target_closure_path=/frx/store/7ee225db532b6973e385f8507d2d61aec3cd3aeb0864f983c2ae4b6e149ef3b0-fruix-system-fruix-freebsd
|
||||
freebsd_source_kind=git
|
||||
freebsd_source_ref=stable/15
|
||||
freebsd_source_commit=332708a606f6bf0841c1d4a74c0d067f5640fe89
|
||||
materialized_source_store=/frx/store/7563df2714ae7fa9bd40b83c74512ffe2cb2ad91b297915591b55c76edbb2fcb-freebsd-source-stable15-installer-target-source
|
||||
installer_state=done
|
||||
installer_sshd_status=running
|
||||
target_esp_fstype=msdosfs
|
||||
target_root_fstype=ufs
|
||||
target_shepherd_status=running
|
||||
target_sshd_status=running
|
||||
installer_environment_boot=ok
|
||||
installer_environment_install=ok
|
||||
installed_target_boot=ok
|
||||
```
|
||||
|
||||
The harness verified all of the following:
|
||||
|
||||
1. `fruix system installer` produces a bootable installer image in `/frx/store`
|
||||
2. validation boots a workdir copy of that installer disk image so the store artifact itself is not mutated during the boot/install run
|
||||
3. the installer environment boots successfully under QEMU/UEFI/TCG
|
||||
4. the installer environment becomes reachable over SSH
|
||||
5. `/run/current-system` inside the installer environment points at the installer closure
|
||||
6. the installer rc.d job reaches:
|
||||
- `state=done`
|
||||
7. the installer log records:
|
||||
- `fruix-installer:done`
|
||||
8. the target raw disk is transformed into a valid GPT-installed Fruix target with:
|
||||
- EFI filesystem: `msdosfs`
|
||||
- root filesystem: `ufs`
|
||||
- `EFI/BOOT/BOOTX64.EFI` present
|
||||
- `/var/lib/fruix/install.scm` present
|
||||
9. the installed target then boots successfully as its own Fruix system under QEMU/UEFI/TCG
|
||||
10. after target boot:
|
||||
- `/run/current-system` points at the target closure
|
||||
- `/usr/local/etc/rc.d/fruix-shepherd onestatus` reports running
|
||||
- `sshd` is running
|
||||
- activation completed successfully
|
||||
|
||||
## Result
|
||||
|
||||
Phase 18.2 is complete.
|
||||
|
||||
Fruix now has a real installer substrate on FreeBSD:
|
||||
|
||||
- a bootable Fruix-managed installer image
|
||||
- a target closure bundled inside that installer environment
|
||||
- in-guest non-interactive installation onto a second disk
|
||||
- validated boot of the installed result
|
||||
|
||||
The next step is Phase 18.3:
|
||||
|
||||
- produce a bootable installer ISO for UEFI systems, rather than only a disk-image-style installer environment.
|
||||
Reference in New Issue
Block a user