system: validate host-initiated native base builds
This commit is contained in:
169
docs/reports/phase20-host-initiated-native-builds-freebsd.md
Normal file
169
docs/reports/phase20-host-initiated-native-builds-freebsd.md
Normal file
@@ -0,0 +1,169 @@
|
||||
# Phase 20.2: host-initiated native base builds inside a Fruix-managed environment
|
||||
|
||||
Date: 2026-04-05
|
||||
|
||||
## Goal
|
||||
|
||||
Validate the next step after Phase 20.1:
|
||||
|
||||
- the host still orchestrates the outer loop
|
||||
- the actual FreeBSD native base build work runs inside a booted Fruix-managed system
|
||||
|
||||
This is the intermediate path between:
|
||||
|
||||
- purely host-side native base builds
|
||||
- any future claim of guest self-hosting
|
||||
|
||||
The target here was not a new self-hosted package manager story.
|
||||
|
||||
It was narrower:
|
||||
|
||||
- boot a Fruix-managed FreeBSD system on the approved real XCP-ng path
|
||||
- expose the development environment required for native base work
|
||||
- run real `buildworld` / `buildkernel` / staged install steps inside that Fruix guest
|
||||
- confirm that the resulting staged artifacts are the expected FreeBSD base slices
|
||||
|
||||
## Implementation
|
||||
|
||||
### Canonical development-path compatibility links
|
||||
|
||||
Phase 20.1 proved that Fruix could keep development content separate in:
|
||||
|
||||
- `/run/current-system/development-profile`
|
||||
- `/run/current-development`
|
||||
|
||||
Phase 20.2 exposed an additional practical requirement:
|
||||
|
||||
- FreeBSD native base builds still expect canonical system paths such as:
|
||||
- `/usr/include`
|
||||
- `/usr/share/mk`
|
||||
|
||||
For development-enabled systems, `populate-rootfs-from-closure` now also exposes:
|
||||
|
||||
- `/usr/include -> /run/current-system/development-profile/usr/include`
|
||||
- `/usr/share/mk -> /run/current-system/development-profile/usr/share/mk`
|
||||
|
||||
This keeps the development profile separate while still satisfying the buildworld/buildkernel assumptions of the native FreeBSD build system.
|
||||
|
||||
### Media builder invalidation
|
||||
|
||||
Because this changed the visible rootfs layout of booted systems, the media builder versions were bumped in `modules/fruix/system/freebsd/media.scm`:
|
||||
|
||||
- `image-builder-version`
|
||||
- `install-builder-version`
|
||||
- `installer-image-builder-version`
|
||||
- `installer-iso-builder-version`
|
||||
|
||||
That ensured booted images and future installed targets actually pick up the new compatibility links.
|
||||
|
||||
### New validation harness
|
||||
|
||||
Added:
|
||||
|
||||
- `tests/system/run-phase20-host-initiated-native-build-xcpng.sh`
|
||||
|
||||
This harness reuses the validated Phase 20.1 XCP-ng path first, then performs the 20.2-native-build step over SSH from the host.
|
||||
|
||||
The guest build flow is:
|
||||
|
||||
1. boot the development-enabled Fruix guest on XCP-ng
|
||||
2. recover the materialized source store from `/run/current-system/metadata/store-layout.scm`
|
||||
3. run real FreeBSD native build commands inside the guest:
|
||||
- `make -j8 buildworld`
|
||||
- `make -j8 buildkernel`
|
||||
- `make DESTDIR=... installworld`
|
||||
- `make DESTDIR=... distribution`
|
||||
- `make DESTDIR=... installkernel`
|
||||
4. stage narrower artifact slices from the staged output:
|
||||
- headers slice
|
||||
- bootloader slice
|
||||
- kernel stage
|
||||
|
||||
### Why `DB_FROM_SRC=yes` is used for staged install steps
|
||||
|
||||
The development-enabled Fruix guest is intentionally lean and does not carry the full ambient host account database.
|
||||
|
||||
`installworld` on modern FreeBSD checks for required users/groups unless `DB_FROM_SRC` is defined. For staged installs into `DESTDIR`, the appropriate controlled input is the source tree's own account database under `etc/`, not the minimal running guest's `/etc/master.passwd`.
|
||||
|
||||
So the validated Phase 20.2 staged install path uses:
|
||||
|
||||
- `DB_FROM_SRC=yes`
|
||||
|
||||
for:
|
||||
|
||||
- `installworld`
|
||||
- `distribution`
|
||||
- `installkernel`
|
||||
|
||||
That keeps the staged install driven by the declared source input rather than by accidental guest-local account state.
|
||||
|
||||
## Validation
|
||||
|
||||
Passing run:
|
||||
|
||||
- `PASS phase20-host-initiated-native-build-xcpng`
|
||||
- workdir: `/tmp/fruix-phase20-host-initiated-native-build-xcpng`
|
||||
|
||||
Validated on the approved real XCP-ng path:
|
||||
|
||||
- VM `90490f2e-e8fc-4b7a-388e-5c26f0157289`
|
||||
- VDI `0f1f90d3-48ca-4fa2-91d8-fc6339b95743`
|
||||
|
||||
Representative result:
|
||||
|
||||
```text
|
||||
build_jobs=8
|
||||
source_store=/frx/store/12d7704362e95afc2697db63f168b878e082b372-freebsd-source-default
|
||||
source_root=/frx/store/12d7704362e95afc2697db63f168b878e082b372-freebsd-source-default/tree
|
||||
build_root=/var/tmp/fruix-phase20-native-build
|
||||
world_stage=/var/tmp/fruix-phase20-native-build/stage-world
|
||||
kernel_stage=/var/tmp/fruix-phase20-native-build/stage-kernel
|
||||
headers_stage=/var/tmp/fruix-phase20-native-build/artifact-headers
|
||||
bootloader_stage=/var/tmp/fruix-phase20-native-build/artifact-bootloader
|
||||
build_root_size=7.6G
|
||||
world_stage_size=672M
|
||||
kernel_stage_size=739M
|
||||
headers_stage_size=32M
|
||||
bootloader_stage_size=1.3M
|
||||
sha_kernel=16950f116a52134b98e2f8e0dacc556e18fe254e4a0ac2c1741422dde281a341
|
||||
sha_loader=ea417846167ece270ada611624dca622ca38bd30125b9a125cd8ebb8b3600313
|
||||
sha_param=9eb140ca7d9666f3d484a4174c9acd94b45427db6292b4e17de19af2c6aa5219
|
||||
host_initiated_native_build=ok
|
||||
```
|
||||
|
||||
The harness verified all of the following:
|
||||
|
||||
- the guest still boots and passes the Phase 20.1 development-environment checks first
|
||||
- development-enabled systems expose canonical native-build compatibility links at:
|
||||
- `/usr/include`
|
||||
- `/usr/share/mk`
|
||||
- the guest can recover the declared materialized FreeBSD source store from system metadata
|
||||
- real FreeBSD `buildworld` succeeds inside the booted Fruix guest
|
||||
- real FreeBSD `buildkernel` succeeds inside the booted Fruix guest
|
||||
- staged `installworld`, `distribution`, and `installkernel` also succeed inside the guest
|
||||
- the staged outputs contain the expected artifact shapes:
|
||||
- `boot/kernel/kernel`
|
||||
- `usr/include/sys/param.h`
|
||||
- `usr/share/mk/bsd.prog.mk`
|
||||
- `boot/loader.efi`
|
||||
- `boot/defaults/loader.conf`
|
||||
- `boot/lua/loader.lua`
|
||||
|
||||
## Result
|
||||
|
||||
Phase 20.2 is complete.
|
||||
|
||||
Fruix now validates a real host-orchestrated path where:
|
||||
|
||||
- the host boots and reaches a Fruix-managed development-enabled guest
|
||||
- the guest uses its own Fruix-exposed development paths and declared source store
|
||||
- the native FreeBSD base build work runs inside that Fruix-managed environment
|
||||
- the host remains the outer orchestrator and result collector
|
||||
|
||||
This materially narrows the gap to any future self-hosting experiment while still avoiding the complexity jump to a full guest-driven package/deployment loop.
|
||||
|
||||
## Next step
|
||||
|
||||
Per `docs/PLAN_4.md`, the next planned step is:
|
||||
|
||||
- **Phase 20.3** — reassess and potentially prototype guest self-hosted base builds
|
||||
Reference in New Issue
Block a user