Files
fruix/docs/reports/phase13-native-base-boot-freebsd.md

5.2 KiB

Phase 13.3: booted Fruix using native store-built FreeBSD base artifacts

Date: 2026-04-03

Goal

Phase 13.3 was the first end-to-end boot validation of the new native FreeBSD base path.

The target was a Fruix system/image that boots using:

  • native /usr/src-built kernel output in /frx/store
  • native /usr/src-built world output in /frx/store
  • host-staged bootloader only, as the remaining explicit transitional boundary

Validation still followed the established strategy:

  • local QEMU/UEFI/TCG
  • real XCP-ng on the approved VM/VDI path

Issues found and fixed

1. The old fixed 256 MiB root filesystem image was too small

The first native-base image attempt failed during makefs with:

size of .../image-rootfs is larger than the maxsize of 268435456

That was expected once the image started carrying a native world instead of the earlier curated host-copy runtime slice.

To fix this cleanly, Fruix image generation gained an explicit root filesystem size parameter:

  • scripts/fruix.scm now accepts:
    • --root-size SIZE
  • image metadata now emits:
    • root_size=...
  • tests/system/run-phase8-system-image.sh now accepts:
    • ROOT_SIZE and records the reported root size in metadata

For the native-base boot validation, the working values were:

  • local QEMU:
    • ROOT_SIZE=6g
    • DISK_CAPACITY=8g
  • real XCP-ng:
    • ROOT_SIZE=6g
    • disk capacity kept matched to the fixed 30 GiB VDI as before

2. materialize-bhyve-image needed to propagate native-base metadata

After adding the new native_base_* metadata path, the first native image run hit a Scheme error because materialize-bhyve-image still returned:

  • host-base-stores
  • fruix-runtime-stores

but not:

  • native-base-stores

That was corrected so image-generation results now carry the native-base store set too.

Harness updates

Reused/extended existing Phase 11 boot harnesses

  • tests/system/run-phase11-shepherd-pid1-qemu.sh
    • now accepts OS_TEMPLATE like the XCP-ng PID1 harness already did
  • tests/system/run-phase8-system-image.sh
    • now records:
      • native_base_store_count
      • native_base_stores
      • root_size

Added native-base boot wrappers

New wrappers:

  • tests/system/run-phase13-native-base-qemu.sh
  • tests/system/run-phase13-native-base-xcpng.sh

These wrappers reuse the already-validated PID1 boot path but require the image metadata to confirm that the booted system really uses the intended Phase-13 base split:

  • native_base_store_count=2
  • native kernel present
  • native world present
  • host_base_store_count=1
  • host base reduced to bootloader only

Validation

Local QEMU / UEFI / TCG

Passing run:

  • PASS phase13-native-base-qemu
  • workdir: /tmp/phase13-3-qemu3-1775174863

Key metadata:

disk_capacity=8g
root_size=6g
native_base_store_count=2
host_base_store_count=1
shepherd_pid=1
sshd_status=running
native_base_boot=ok

The wrapped underlying Phase 11 PID1 harness also confirmed the full guest runtime path:

  • ready marker present
  • /run/current-system correct
  • Shepherd socket present
  • Shepherd PID is 1
  • sshd running
  • activation completed successfully
  • /etc/login.conf regular + databases present

Real XCP-ng VM

Passing run:

  • PASS phase13-native-base-xcpng
  • workdir: /tmp/phase13-3-xcpng-1775175086

Key metadata:

vm_id=90490f2e-e8fc-4b7a-388e-5c26f0157289
vdi_id=0f1f90d3-48ca-4fa2-91d8-fc6339b95743
guest_ip=192.168.213.62
root_size=6g
native_base_store_count=2
host_base_store_count=1
shepherd_pid=1
sshd_status=running
compat_prefix_shims=absent
guile_module_smoke=ok
native_base_boot=ok

The dynamic VHD upload remained workable even with the larger native-world image payload, though naturally much larger than the earlier minimal image path:

  • upload size: 4740784128 bytes (~4.42 GiB)

What booted

The validated native-base system closure used:

  • native kernel store:
    • /frx/store/93f35ddcb9a03f63f83c9e8ae29788685d339789da664f881822b4a1914f5ff6-freebsd-native-kernel-15.0-STABLE
  • native world store:
    • /frx/store/3f6f7f8c06ed8dad4cae21a1e8ac8ba4823bdb7cf54328c9bbcccaeb858beb77-freebsd-native-world-15.0-STABLE
  • remaining host base store:
    • /frx/store/8ffcfe0356fea815726b610514a1280a11266851c2acb870047d559795569f0e-freebsd-bootloader-15.0-STABLE

That means Phase 13 has now crossed its main success boundary:

  • the kernel is native
  • the core world runtime is native
  • the system actually boots from those outputs

Assessment

Phase 13 is complete.

Fruix has now moved from:

  • building a FreeBSD system from curated host copies

into:

  • building kernel/world artifacts from /usr/src into /frx/store, then booting a declarative Fruix system from those outputs.

The remaining major transitional boundary is now much narrower and explicit:

  • host-staged bootloader/boot assets remain
  • native kernel + native core world runtime are already in place

That is a real architectural shift, not just more documentation.

Proceed to Phase 14:

  1. replace the remaining host-copy boot assets first
  2. then keep reducing the older host-staged FreeBSD base slice around the now-working native world/kernel path
  3. revisit cleaner runtime vs. development splits once the boot asset transition is done