Files
fruix/docs/PLAN_2.md

361 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Fruix on FreeBSD, Path B: Real Guix/Fruix Integration First, Then a Minimal bhyve System
This document extends `docs/PLAN.md` after the completion of Phases 1 through 4 on the current FreeBSD amd64 prototype track. The next major objective is no longer to validate isolated subsystems, but to connect them through a real Guix/Fruix execution path and ultimately boot a minimal Fruix system in bhyve.
Unlike a prototype-image-first strategy, this plan takes **Path B directly**:
- prioritize real Guix/Fruix checkout and runtime integration on FreeBSD,
- connect package lowering, derivation generation, daemon/store behavior, and system composition,
- and only then generate and boot a minimal bhyve image from that integrated path.
This is slower than assembling an image from ad hoc prototypes, but it better preserves the architectural goal: a genuine Fruix system built through Guix-style mechanisms rather than merely a FreeBSD image with Fruix-like parts.
Throughout this plan, the experimental store root remains:
- `/frx/store`
- `/frx/var`
- `/frx/etc`
rather than `/gnu/store`.
## Naming and Fork Identity Policy
This plan assumes that the project is now **Fruix** as a user-facing system, in the same way that the store root has already moved from `/gnu` to `/frx`.
The naming policy for the next phases is:
- the user-facing CLI should become `fruix`
- user-facing daemon, service, help text, generated documentation, and system identity should prefer `fruix` over `guix`
- new fork-specific modules and code should prefer `fruix` namespaces and naming
- the `/frx` path family remains the canonical store/state/config root for FreeBSD work
- internal upstream-derived module namespaces should **not** be renamed mechanically just for branding
- names containing `gnu` should be preserved where they refer to actual GNU concepts or components, such as:
- GNU packages
- GNU Shepherd
- `gnu-build-system`
This means the early integration work will often need to distinguish between:
- the **current upstream-derived internal checkout reality**, where the failing command path is still `./pre-inst-env guix ...`, and
- the **desired Fruix product boundary**, where the operator-facing command should become `fruix`.
Accordingly, the next phases should first make the current checkout runnable, then establish a controlled rename boundary for the user-facing command and related interfaces, rather than attempting a blanket internal rename of every `guix` or `gnu` identifier.
---
## Current State at the End of Phase 4
The following have already been validated on the active FreeBSD amd64 host:
- fixed local Guile path suitable for subprocess-heavy Scheme work
- FreeBSD jail-first build isolation prototype
- privilege drop and build-user isolation prototype
- `/frx/store` prototype with GC-style rooted retention
- reusable FreeBSD GNU build-system adaptation across representative packages
- prototype FreeBSD package-definition/profile layer
- Shepherd build and runtime supervision on FreeBSD
- Shepherd `rc.d` integration prototype
- Shepherd bridge layer for FreeBSD rc.d, loopback/network, tmpfs, and user/group administration
The largest remaining blocker before real system generation is still the live upstream-derived checkout/runtime path, especially:
- `./pre-inst-env guix --version`
- `Wrong type to apply: #<syntax-transformer leave-on-EPIPE>`
That blocker is the first item in the next phase because without it, system composition cannot honestly move from prototype scaffolding to real Fruix/Guix execution. Resolving it is also the prerequisite for introducing a trustworthy `fruix` user-facing command boundary on top of the current checkout.
---
## Phase 5: Real Guix Checkout and Host Runtime Unblocking on FreeBSD
### Intermediate Goal 5.1: Unblock the Uninstalled Checkout Command Path and Establish the `fruix` CLI Boundary
The immediate goal is to move from “the checkout configures and builds some generated scripts” to “the checkout actually runs on FreeBSD”.
Because the current checkout still exposes an upstream-derived `guix` command path, this step must also define how the user-facing `fruix` command is introduced without forcing a premature blanket rename of internal identifiers.
**Verification Goal 5.1:** Investigate and fix the runtime failure in the uninstalled checkout command path:
- `./pre-inst-env guix --version`
- `./pre-inst-env guix repl`
- `./pre-inst-env guix build --help`
Then, once that path works, introduce a first user-facing `fruix` command boundary for the checkout, whether by renamed frontend, generated wrapper, compatibility symlink policy, or another documented transition mechanism.
The investigation must identify whether the `leave-on-EPIPE` failure is due to:
- macro expansion / module ordering assumptions,
- Guile version or module interaction,
- FreeBSD-specific POSIX behavior,
- generated source ordering,
- or a latent upstream bug exposed by FreeBSD.
Produce:
- a dedicated reproducer harness,
- a root-cause report,
- and either:
- an in-repo patch queue for the Guix checkout, or
- a precise upstreamable fix series.
**Success Criteria:** `./pre-inst-env guix --version` succeeds on FreeBSD using the fixed local Guile stack, at least one additional non-trivial checkout subcommand works, and there is a documented first-step user-facing `fruix` frontend policy for the live checkout.
### Intermediate Goal 5.2: Validate Package Lowering and Derivation Generation
Once the checkout is runnable, the next boundary is host-side lowering rather than builder-side phase execution.
**Verification Goal 5.2:** Demonstrate that a real Guix checkout on FreeBSD can lower at least one tiny package to a derivation using the `/frx` store settings. This step should verify:
- package -> bag lowering,
- bag -> derivation lowering,
- imported module closure materialization,
- fixed-output source origin handling,
- and generation of a real derivation file targeting `/frx/store`.
The initial validation target should be intentionally small, such as a previously successful package from the build-system work (`hello`, `which`, or similar).
**Success Criteria:** a real derivation is emitted by Guix on FreeBSD, references `/frx/store`, and can be inspected as a normal derivation rather than only as a prototype metadata file.
### Intermediate Goal 5.3: Establish Store Connection and Minimal Daemon RPC Integration
At this point, the remaining gap is the connection between host-side lowering and actual store-backed builds.
**Verification Goal 5.3:** Connect the runnable checkout to a minimal FreeBSD-aware store/daemon path. This should include:
- confirming `open-connection` / store socket behavior on FreeBSD,
- minimal daemon configuration for `/frx/store`,
- validating store registration and metadata behavior,
- and ensuring that at least one real derivation can be submitted to the daemon.
This phase may still rely on prototype jail/build-user implementations while integrating them incrementally into daemon behavior.
**Success Criteria:** a real checkout command path can contact a FreeBSD-aware daemon/store path and submit at least one derivation-backed build request, with the intended user-facing interface moving toward `fruix`.
---
## Phase 6: Real FreeBSD-Backed Store Builds Through Guix/Fruix Mechanisms
### Intermediate Goal 6.1: Build a Real Package Into `/frx/store`
The builder-side phase runners proved that GNU packages can build on FreeBSD. This phase requires proving that they can do so through real lowering + store + daemon plumbing.
**Verification Goal 6.1:** Build at least one small GNU package from a real Guix package definition all the way into `/frx/store`, through the daemon path. Validate:
- store path creation,
- output registration,
- runtime execution from the store,
- and preservation of declared references.
**Success Criteria:** `fruix build`-style execution succeeds for at least one real package on FreeBSD and produces a usable output in `/frx/store`, even if the underlying checkout still retains transitional upstream-derived command plumbing.
### Intermediate Goal 6.2: Integrate FreeBSD Jail/Privilege Prototypes Into the Real Build Path
The current jail/build-user work is still prototype-scoped. It now needs to become part of the actual FreeBSD build path.
**Verification Goal 6.2:** Adapt the daemon build path so that real derivation builds use the already validated FreeBSD primitives:
- thin jails,
- explicit `nullfs` mount plans,
- dropped build users,
- `/frx/store` read semantics,
- and per-build writable scratch/output directories.
At least one real package build should be observed executing inside that integrated jail/build-user path.
**Success Criteria:** a real Guix/Fruix build runs inside a FreeBSD jail with dropped build credentials and succeeds into `/frx/store`.
### Intermediate Goal 6.3: Validate Profiles and User-Facing Package Installation
Once real builds land in the store, the next user-facing layer is profile generation.
**Verification Goal 6.3:** Demonstrate that a user profile can be produced from real store items on FreeBSD, not only from the earlier package/profile prototype layer. Validate:
- profile symlink generation,
- transaction semantics at least in a minimal form,
- PATH usability,
- and user access to built packages.
**Success Criteria:** a package built through the real FreeBSD store path can be installed into a user profile and executed through that profile.
---
## Phase 7: Declarative Fruix System Composition on FreeBSD
### Intermediate Goal 7.1: Define a Minimal Fruix Operating-System Model
The package layer alone is not enough; there must be a system-level object that describes an installable/bootable Fruix system.
**Verification Goal 7.1:** Define a minimal Fruix system model for FreeBSD, analogous in spirit to Guix Systems operating-system record, that can describe:
- kernel and boot assets,
- essential FreeBSD base packages,
- `/etc` configuration files,
- activation requirements,
- Shepherd configuration,
- file systems,
- users/groups,
- and host identity settings.
This may begin in Fruix-specific modules rather than attempting immediate full upstream Guix OS integration.
**Success Criteria:** a declarative system description can be evaluated into a coherent system closure specification rather than only a loose collection of packages.
### Intermediate Goal 7.2: Generate a Minimal System Closure and Activation Payload
The next step is to turn the system model into concrete filesystem content.
**Verification Goal 7.2:** Generate a minimal system closure for FreeBSD that includes at least:
- FreeBSD kernel and boot files,
- minimal userland,
- required `/etc` files,
- Shepherd service definitions and startup hook,
- activation scripts,
- and references into `/frx/store`.
This phase should decide and document whether the first boot target uses:
- FreeBSD init + `rc.d` to launch Shepherd, or
- Shepherd as PID 1.
For the first integrated boot target, FreeBSD init + `rc.d` is acceptable if it is generated declaratively from the system definition.
**Success Criteria:** a system closure directory tree can be generated reproducibly from a declarative Fruix system description.
### Intermediate Goal 7.3: Validate an Installable Root Filesystem Tree
Before generating a disk image, validate that the system closure can be materialized as a rootfs tree suitable for installation or image creation.
**Verification Goal 7.3:** Build a root filesystem tree that contains:
- bootable kernel/loader content,
- generated configuration,
- declared users/groups,
- Shepherd launch integration,
- and enough runtime content to reach a login prompt or equivalent ready state.
**Success Criteria:** the generated rootfs is internally coherent and passes static validation for image construction.
---
## Phase 8: FreeBSD/Fruix Image Construction for bhyve
### Intermediate Goal 8.1: Create a Reproducible Disk Image Build Path
Now that the system closure exists, produce a real boot medium from it.
**Verification Goal 8.1:** Create tooling to generate a bootable bhyve-compatible disk image from the Fruix system closure. This should include:
- partition map creation,
- filesystem creation,
- rootfs population,
- boot asset installation,
- and serial-console-friendly configuration.
The first target should prefer the simplest debuggable bhyve path, likely:
- raw disk image,
- UEFI boot,
- FreeBSD kernel/loader,
- serial console.
**Success Criteria:** a reproducible image file is generated from the declarative Fruix system description and passes boot-structure sanity checks.
### Intermediate Goal 8.2: Integrate Image Generation With the Fruix System Definition Layer
The image builder should not remain a detached shell-only utility.
**Verification Goal 8.2:** Connect image generation to the system description layer so that the image is the output of system composition, not a manual afterthought. Ideally, this begins to resemble a minimal FreeBSD analogue of `fruix system image`, even if some internal machinery still derives from upstream Guix code paths.
**Success Criteria:** a single declarative Fruix system description can drive image generation end-to-end.
---
## Phase 9: Boot a Minimal Fruix System in bhyve
### Intermediate Goal 9.1: Reach a Serial-Console Boot Milestone
The first VM target should be intentionally narrow: boot the generated image and prove it reaches a known-good ready state.
**Verification Goal 9.1:** Create a bhyve launcher/validation harness that:
- boots the generated image,
- captures serial output,
- waits for a ready marker,
- and tears down the VM cleanly.
The ready marker may initially be one of:
- a login prompt,
- a Shepherd status marker,
- or a deterministic boot-complete message.
**Success Criteria:** the Fruix image boots in bhyve and reaches a deterministic serial-console ready state.
### Intermediate Goal 9.2: Validate In-Guest Shepherd and Core Services
After basic boot, verify that the system behaves like a Fruix system and not merely a FreeBSD guest with some files copied in.
**Verification Goal 9.2:** Validate in the running bhyve guest that:
- Shepherd is active,
- the expected essential services are started,
- the generated configuration is in effect,
- and the system closure in the guest matches the declared build outputs.
**Success Criteria:** the bhyve guest boots the generated Fruix system and runs Shepherd-managed core services successfully.
### Intermediate Goal 9.3: Validate Minimal Operator Usability
The final milestone for the first bhyve system is not completeness, but minimal usefulness.
**Verification Goal 9.3:** Confirm that the guest supports a minimal operator workflow, such as:
- console login or root shell access,
- inspection of Shepherd service status,
- reading generated configuration files,
- and optionally basic networking.
**Success Criteria:** a human operator can boot the bhyve guest and verify a minimally usable Fruix environment from inside the VM.
---
## Optional Phase 10: Replace Transitional Pieces With More Native Fruix/Guix Machinery
This phase is intentionally deferred until after the first real bhyve success.
Possible follow-up work includes:
- replacing residual prototype-only composition layers with true Guix-native system-generation mechanisms,
- deeper integration of FreeBSD package definitions with real package records and lowering paths,
- improving daemon/store metadata fidelity,
- turning image generation into a true `fruix` command,
- and evaluating whether Shepherd-as-PID-1 is worth pursuing beyond the validated `rc.d` bridge path.
---
## Recommended Immediate Order of Work
If work begins on this plan now, the recommended near-term order is:
1. **Phase 5.1** — fix the `leave-on-EPIPE` checkout/runtime blocker
2. **Phase 5.2** — prove real derivation generation on FreeBSD with `/frx/store`
3. **Phase 5.3 / 6.1** — connect real builds to the daemon/store path and land one package in `/frx/store`
4. **Phase 6.2** — attach the real build path to FreeBSD jail/build-user isolation
5. **Phase 7** — define the minimal declarative Fruix system model and rootfs closure
6. **Phase 89** — generate and boot the first bhyve image
This ordering keeps the project honest: the bhyve image milestone will be the output of genuine Guix/Fruix integration work rather than a prototype assembled around unresolved core runtime issues. It also keeps the naming transition disciplined: user-facing `fruix` surfaces can be introduced deliberately on top of a working checkout instead of via a destabilizing whole-tree rename.
---
## Final Target of This Plan
The end goal of this Path B plan is:
> A minimal Fruix system for FreeBSD, generated through real Guix/Fruix-style mechanisms, exposed to operators through `fruix` user-facing interfaces, stored under `/frx`, bootable in bhyve, and capable of running Shepherd-managed core services.
This target explicitly assumes selective renaming rather than blanket renaming: Fruix at the product boundary, stable upstream-derived internal names where they continue to provide architectural or maintenance value, and preserved GNU naming where it refers to genuine GNU components.
That is the next major milestone after the completed foundational and prototype phases.