Files
fruix/docs/PLAN_3.md

14 KiB

Fruix on FreeBSD, Path C: Short Hardening Pass, Then Native FreeBSD Base Builds

This document extends docs/PLAN_2.md after the completion of Phases 1 through 10 and the post-Phase-10 Shepherd/PID-1 and runtime-prefix cleanup work.

The project has already crossed the main feasibility threshold:

  • Fruix can build declarative FreeBSD system artifacts
  • those artifacts boot on the real XCP-ng VM
  • the guest reaches DHCP and SSH
  • both freebsd-init+rc.d-shepherd and shepherd-pid1 have been validated
  • the guest no longer depends on /tmp/*-validate-install runtime-compatibility shims

The next architectural question is about the FreeBSD base itself.

Today, Fruix still assembles the kernel, bootloader, libraries, rc assets, and userland largely by copying curated artifacts from the build host into /frx/store. That was the right bootstrap move, but it is now the largest remaining non-native part of the system.

Long-term, the desired direction is clear:

  • build FreeBSD kernel/world as Fruix-managed artifacts
  • keep them in /frx/store
  • make system upgrades a declarative rebuild/redeploy story instead of a host-copy refresh

However, this plan does not recommend jumping directly into full self-hosted FreeBSD base builds inside the guest. Instead, it takes a narrower and safer sequence:

  1. do a short hardening pass on the current working system
  2. then begin Option B immediately as the next major architecture phase
  3. start Option B on the builder side from /usr/src, not with guest self-hosting

This keeps momentum while avoiding two failure modes:

  • over-polishing the current host-copy pipeline as if it were the end state
  • mixing base-system build mechanics, runtime polish, boot debugging, and self-hosting into one oversized step

Throughout this plan, the canonical Fruix roots remain:

  • /frx/store
  • /frx/var
  • /frx/etc

The user-facing system remains Fruix, with CLI fruix, while internal upstream-derived names continue to be renamed selectively rather than mechanically.


Current State at the Start of Plan 3

Fruix on FreeBSD already has:

  • a functioning content-addressed store and derivation path
  • daemon-mediated builds with FreeBSD-aware isolation prototypes
  • real package outputs in /frx/store
  • a declarative FreeBSD operating-system model
  • rootfs and image generation driven by fruix system ...
  • real XCP-ng validation using the approved VM/VDI path
  • a working FreeBSD guest with DHCP, SSH, activation, Shepherd, and ready markers
  • validated shepherd-pid1 boot on both local QEMU/TCG and the real XCP-ng VM
  • removal of the guest runtime's dependence on /tmp compatibility-prefix symlinks

The main remaining architectural compromise is that the FreeBSD base layer is still defined mostly as a set of curated host copies:

  • kernel from /boot/kernel
  • bootloader and boot assets from /boot
  • userland/runtime pieces from /bin, /sbin, /usr/bin, /usr/sbin, /lib, /usr/lib, and /etc
  • headers from /usr/src

That means Fruix can currently rebuild and redeploy a working system, but it does not yet have a truly native upgrade story for the FreeBSD base itself.


Guiding Decision for the Next Milestone

The next milestone should be:

  • just enough hardening to make the current system a reliable platform for deeper work,
  • followed immediately by the first host-built FreeBSD base artifacts in /frx/store.

This means the next work should optimize for:

  • debuggability
  • provenance
  • repeatable deployment/validation
  • clean separation between host-staged base artifacts and Fruix-built artifacts
  • incremental replacement of the copy-based base layer

It should not optimize for:

  • turning the current host-copy path into a heavily polished long-term abstraction
  • immediate self-hosted buildworld/buildkernel inside the Fruix guest
  • solving every usability concern before starting native base work

Phase 12: Short Hardening Pass on the Existing Working Pipeline

The purpose of this phase is not to beautify the bootstrap path. It is to make the existing validated system reliable enough that FreeBSD base-build work can proceed without avoidable confusion.

Intermediate Goal 12.1: Improve Deployment Provenance and Failure Diagnosis

Verification Goal 12.1: Make the current pipeline record exactly what FreeBSD base inputs and deployment artifacts were used for each generated system/image.

This should include at least:

  • host freebsd-version / uname provenance
  • /usr/src revision or identifying metadata when available
  • the exact staged base-package store paths used in the system closure
  • image metadata that clearly distinguishes:
    • host-copied FreeBSD base artifacts
    • Fruix-built Guile/Shepherd/system artifacts
  • better collection of boot/runtime logs where possible from the existing QEMU and XCP-ng harnesses

Success Criteria: a generated Fruix system/image can be traced back to its host-side FreeBSD base inputs and runtime validation logs without ad hoc investigation.

Intermediate Goal 12.2: Tighten Basic Runtime Completeness and Operator Diagnostics

Verification Goal 12.2: Close the most important remaining “prototype rough edges” in the current guest so it remains a dependable validation target while Option B begins.

This should focus on small, high-value improvements such as:

  • clearer boot/service logs
  • fewer known noisy runtime warnings where reasonably fixable
  • more explicit validation of essential services and files
  • better failure surfacing from activation and service startup

This phase should avoid broad feature creep. The target is not a polished distribution; it is a sharper debugging and validation baseline.

Success Criteria: the current FreeBSD guest remains reproducibly bootable and easier to debug, with fewer ambiguous failures during rebuild/redeploy cycles.

Intermediate Goal 12.3: Make the Host-Staged FreeBSD Base Boundary Explicit

Verification Goal 12.3: Refine the current package/model layer so the “host-staged FreeBSD base” is treated as an explicit transitional boundary rather than an implicit permanent design.

This should include:

  • clearer grouping or manifesting of host-staged base packages
  • documentation of which components are currently copied from the host
  • explicit notes on which ones are planned to be replaced first by native base builds

Success Criteria: the repo documents and code clearly separate transitional host-copy FreeBSD base handling from genuine Fruix-built artifacts.


Phase 13: Option B Begins — Host-Built FreeBSD Kernel and World Artifacts in /frx/store

This is the real architectural pivot.

The goal is not yet to self-host FreeBSD base builds inside a Fruix guest. The goal is to teach Fruix to produce FreeBSD base artifacts as build outputs under /frx/store, using the builder host and /usr/src as the source of truth.

Intermediate Goal 13.1: Model FreeBSD World and Kernel as Fruix Build Artifacts

Verification Goal 13.1: Introduce Fruix build descriptions for the FreeBSD base that can represent at least:

  • a freebsd-world artifact
  • a freebsd-kernel artifact
  • required boot assets associated with the selected kernel/world build

The first version may still be specialized and FreeBSD-specific rather than fully generalized.

This step should determine and document:

  • how /usr/src is treated as an input
  • what build parameters affect output identity
  • how kernel/world configuration is hashed into the output model
  • how these outputs are split or grouped in /frx/store

Success Criteria: Fruix can describe native FreeBSD world/kernel build outputs as real store artifacts rather than only host-copy packages.

Intermediate Goal 13.2: Build and Stage Minimal FreeBSD World/Kernel Outputs From /usr/src

Verification Goal 13.2: Produce the first concrete world/kernel build outputs from /usr/src and stage them into /frx/store.

The first target should be intentionally narrow:

  • build a kernel matching the validated VM target
  • build a minimal world sufficient for the current Fruix guest to boot
  • stage install trees under content-addressed store paths

This phase should prefer correctness and repeatability over completeness. A minimal successful output split is acceptable if it is documented.

Success Criteria: /frx/store contains native Fruix-managed FreeBSD world/kernel outputs built from /usr/src, and their contents can be inspected as build results rather than copied host snapshots.

Intermediate Goal 13.3: Boot a Fruix System Using Store-Built FreeBSD Base Artifacts

Verification Goal 13.3: Wire the operating-system/image pipeline so a generated system can boot using the newly built world/kernel outputs instead of the corresponding host-copy packages.

This should preserve the existing validation strategy:

  • local QEMU/TCG + UEFI where useful
  • real XCP-ng validation on the approved VM and existing VDI

The first boot target may still leave some secondary base components on the older copy path if necessary, as long as the transition boundary is explicit.

Success Criteria: a Fruix system/image boots successfully using native store-built FreeBSD base artifacts for at least the kernel and core world runtime.


Phase 14: Incrementally Replace the Host-Copy FreeBSD Base Layer

Once a minimal native world/kernel path works, the rest of the host-copy base layer should be retired incrementally rather than in one giant switch.

Intermediate Goal 14.1: Replace Kernel and Boot Assets First

Verification Goal 14.1: Move the system closure and image generator to prefer native store-built kernel and boot assets over host-copied /boot/... material.

This should include:

  • kernel
  • loader/boot assets as appropriate
  • any required linker or boot metadata

Success Criteria: the image no longer relies on host-copied kernel/boot components for the validated boot path.

Intermediate Goal 14.2: Replace the Core Runtime World Slice

Verification Goal 14.2: Move the essential userland/runtime components to the native world outputs, including the files required for:

  • boot
  • activation
  • networking
  • SSH
  • service startup
  • basic operator access

Success Criteria: the booted Fruix system reaches ready state using a native store-built core FreeBSD runtime rather than a hand-curated host copy set.

Intermediate Goal 14.3: Revisit Headers, Toolchain, and Development Splits

Verification Goal 14.3: Define cleaner boundaries between:

  • runtime world outputs
  • development headers
  • toolchain artifacts
  • optional build/developer profiles

This step should reduce accidental coupling between “what the guest needs to boot” and “what the host needs to build software”.

Success Criteria: Fruix has a clearer and more maintainable model for FreeBSD runtime vs. development artifacts in /frx/store.


Phase 15: Establish a Real Fruix Upgrade Story for the FreeBSD Base

After native base artifacts exist and are used by the system closure, Fruix can move from “rebuild from current host copies” toward a more honest upgrade story.

Intermediate Goal 15.1: Make the FreeBSD Base Version a Declarative Input

Verification Goal 15.1: Define how a Fruix system declares which FreeBSD base/kernel source version it targets.

This may initially remain tied to locally available /usr/src, but it should move the model toward a declarative notion of:

  • target FreeBSD branch/release
  • kernel configuration
  • world configuration
  • boot/runtime variant

Success Criteria: FreeBSD base versioning becomes an explicit part of the Fruix system model rather than an implicit property of the builder host.

Intermediate Goal 15.2: Support Rebuild/Redeploy/Rollback Across Base Versions

Verification Goal 15.2: Demonstrate that at least two distinct FreeBSD base builds can coexist in /frx/store and that the generated system can switch between them through the normal rebuild/redeploy flow.

This should preserve the Guix-inspired strengths:

  • content-addressed outputs
  • side-by-side versions
  • rollback-friendly system closures

Success Criteria: Fruix can rebuild and redeploy a system against a newer FreeBSD base without mutating the old one in place.

Intermediate Goal 15.3: Decide When to Pursue Self-Hosted Base Builds

Verification Goal 15.3: Reassess whether the next step should be:

  • building FreeBSD base artifacts inside a Fruix-managed environment, or
  • continuing to use the host builder while improving reproducibility and source acquisition

This decision should be made only after native world/kernel artifacts are already working in /frx/store.

Success Criteria: the project has a documented, evidence-based decision on whether and when to pursue self-hosted FreeBSD base builds.


Strategic Notes

Why this order?

This sequence is intended to preserve momentum and architectural clarity.

The short hardening pass prevents the next phase from being undermined by avoidable debugging ambiguity. But the hardening phase is intentionally short so the project does not over-invest in the transitional host-copy design.

Then Option B begins immediately in a way that is ambitious but still controlled:

  • build FreeBSD base artifacts on the host
  • store them in /frx/store
  • boot from them
  • replace the host-copy model incrementally

What this plan does not require yet

This plan does not require, in its first native-base stages:

  • guest self-hosting
  • in-place freebsd-update integration
  • complete replacement of every base file in one step
  • abandoning the validated XCP-ng/QEMU test harnesses
  • immediate adoption of shepherd-pid1 as the only supported boot path

What success will mean

Success under this plan means the project moves from:

  • “Fruix assembles a FreeBSD system by copying a curated slice of the host”

into:

  • “Fruix builds and stores FreeBSD base artifacts itself, then assembles and deploys systems from those declared outputs.”

That is the real bridge from the current prototype to a more genuinely native Fruix system on FreeBSD.