7.5 KiB
Fruix FreeBSD Progress Summary
What we have achieved so far
Fruix now has a working end-to-end prototype of a Guix-inspired system on FreeBSD, while preserving the Fruix product boundary (fruix, /frx) and the core model: declarative builds, content-addressed store paths, daemon-mediated privilege separation, garbage-collection roots, derivations, and reproducible system artifacts.
Completed milestones include:
- Core runtime/build foundation: validated Guile on FreeBSD, diagnosed the packaged-Guile subprocess crash, and established a working local Guile path with the upstream FreeBSD fix.
- Store and daemon path: built the first Fruix daemon/store workflow on FreeBSD, including jail/build-user isolation, store population under
/frx/store, derivation generation, and minimal RPC integration. - Real package builds: adapted enough of the GNU build/package path to build real package outputs into
/frx/storeand install a minimal profile. - System model: introduced a declarative FreeBSD
operating-systemmodel, reproducible system closures, rootfs generation, and raw image generation as first-class system artifacts. - Bootable VM images: built FreeBSD images that boot reproducibly and stage the full
/frx/storeinto the guest image. - Real VM validation on XCP-ng: proved the system boots on the real target VM, gets DHCP, starts SSH, and exposes a usable guest for validation.
- User-facing CLI: added
bin/fruixwithfruix system build|rootfs|image, making system artifact generation a real Fruix workflow instead of a phase-specific prototype. - Boot architecture progress: validated both boot modes on the real XCP-ng VM:
freebsd-init+rc.d-shepherdshepherd-pid1
- Native runtime cleanup: removed the guest runtime’s dependence on
/tmp/*-validate-installcompatibility-prefix symlinks for Guile, guile-extra, and Shepherd. The guest now boots and runs Guile/Shepherd from the store-backed runtime layout without those temporary aliases. - Native FreeBSD base artifacts: replaced the validated host-copy boot/runtime path with native
/usr/src-built artifacts in/frx/storefor:freebsd-native-kernelfreebsd-native-bootloaderfreebsd-native-runtime
- Declarative FreeBSD base model: the FreeBSD base is now an explicit system input via
freebsd-base, not just an ambient property of the builder host. - Declarative FreeBSD source model and materialization: Fruix can now describe FreeBSD sources explicitly via
freebsd-sourceand materialize them from:- local source trees
https://git.FreeBSD.org/src.git- official
src.txzarchives such ashttps://download.freebsd.org/releases/amd64/15.0-RELEASE/src.txzinto/frx/store, with cache-backed provenance under/frx/var/cache/fruix/freebsd-source.
- Source-driven native base builds: native FreeBSD kernel/bootloader/runtime artifacts now consume those materialized source snapshots rather than ambient
/usr/src, and their build metadata records both the declared source and the effective materialized source identity. - Side-by-side source revisions: Fruix can now keep distinct FreeBSD source identities side by side in
/frx/storeand produce distinct native base outputs from them, even when the visible base version label is held constant. - Source-driven boot validation: Fruix can now also boot systems built from distinct declared FreeBSD source revisions while preserving those source identities in image/build metadata.
- Explicit source policy: the repo now records how FreeBSD source objects are fetched, cached, identified, invalidated, and consumed by native base builds in
docs/freebsd-source-policy.md. - Minimal installation workflow: Fruix now has a non-interactive
fruix system installpath that can partition, format, populate, and boot a target image or disk from a declarative system closure. - Minimal installer environment: Fruix can now also build and boot a dedicated installer image that carries a selected target closure, installs it onto a second disk from inside the guest, and leaves the installed target bootable.
- Base upgrade story: Fruix can now keep distinct declared base versions side by side in
/frx/storeand roll forward / back between them through the normal system deployment flow.
Major pain points now behind us
- Guile subprocess instability on FreeBSD: root-caused and bypassed with the validated local Guile build.
- “Prototype only” store/build flow: replaced with real derivations, store outputs, and system artifacts under
/frx/store. - Non-booting early images: fixed rootfs/image composition, GPT sizing issues for XCP-ng, and early rc/fstab problems.
- No practical VM validation path: when local bhyve proved impossible under Xen, validation successfully pivoted to the real XCP-ng VM and existing VDI.
- Guest runtime crashes from locale/prefix issues: fixed enough locale/runtime staging and later removed dependence on guest-side compatibility-prefix shims.
- Shepherd only as a bridged service: Fruix has now proven Shepherd can run as PID 1 on FreeBSD, not just behind FreeBSD
init+rc.d.
Major pain points still ahead
- True store-native runtime artifacts: some historical build/install prefixes are still embedded in binaries and metadata. They are no longer required at runtime, but the local Guile/guile-extra/Shepherd build/install flow should still be moved to a genuinely store-native prefix from the start.
- Installer media beyond disk images: Fruix now has both a host-driven install path and a bootable installer environment, but it still lacks a UEFI installer ISO and a more polished operator-facing installation medium.
- Boot-path simplification: Fruix now supports both the legacy
freebsd-init+rc.d-shepherdpath and the more Guix-likeshepherd-pid1path. We still need to decide whether Shepherd PID 1 becomes the preferred/default architecture. - Reduce transitional FreeBSD glue: more of the current bootstrap/activation/runtime setup should become cleaner and less prototype-specific over time.
- Tooling and platform constraints: local bhyve remains blocked by missing nested virtualization under Xen, and XO permissions still prevent creating/importing new VDIs; current validation must keep reusing the approved VM/VDI path.
- Remaining ecosystem gaps: some deeper Guix-like features are still immature on FreeBSD, especially around native package-management ergonomics and fully polished runtime/deployment behavior.
Bottom line
Fruix has crossed the most important threshold: it is no longer just a collection of isolated FreeBSD experiments. It can now build declarative FreeBSD system artifacts, boot them on the real target VM, reach the network, serve SSH, run Shepherd as PID 1, operate from /frx without depending on temporary runtime-prefix shims, build native FreeBSD base artifacts into /frx/store, roll forward / back between declared base versions, materialize declared FreeBSD source inputs into /frx/store, drive native base builds from those materialized source snapshots, boot systems from distinct source revisions, explain the source provenance/invalidation rules explicitly, install a declarative system onto a target image through a repeatable Fruix workflow, and boot a dedicated Fruix-managed installer environment that performs that installation from inside the guest. The biggest remaining work is no longer “can this build/install at all?” but “how does this become a fuller installer/deployment/generation/installer-media story?”