# Fruix differences for Guix sysadmins Date: 2026-04-04 This document is aimed at operators who already know Guix well and want a quick map of where Fruix behaves similarly and where it intentionally differs. The short version is: - Fruix is strongly **Guix-inspired** - it tries to preserve the important semantic properties - but it does **not** copy Guix mechanically where FreeBSD or Fruix-specific concerns make a different representation clearer ## Big picture Fruix keeps the core Guix ideas you would expect: - declarative inputs - content-addressed store paths - immutable build outputs - rollback-friendly deployment identity - provenance tied to the deployed closure rather than mutable in-place state But Fruix differs in at least four major ways today: 1. it targets **FreeBSD**, not GNU/Linux 2. its system frontend is currently smaller: - `fruix system build|rootfs|image|install|installer|installer-iso` 3. it treats **FreeBSD source provenance** as an explicit deployment concern 4. its installed-system generation model is still earlier-stage than Guix's mature system-generation workflow ## Similarities to Guix If you know Guix System, these Fruix properties should feel familiar. ### Immutable deployment identity A deployed Fruix system is identified primarily by its closure path in `/frx/store`, not by mutable files under `/etc` or `/usr/local`. ### `/run/current-system` Fruix keeps the Guix-like runtime convention: - `/run/current-system` That path remains the active runtime boundary used by activation and service wiring. ### Rollback-friendly semantics Fruix avoids in-place mutation of an older deployed closure. The validated rollback story today is: - keep the earlier declaration - rebuild or rematerialize it - boot or redeploy that earlier closure again That is Guix-like in spirit even though Fruix does not yet expose the same installed-system rollback command surface. ### Generation-style metadata and roots Fruix now records explicit installed-system generation state under: - `/var/lib/fruix/system` and explicit retention roots under: - `/frx/var/fruix/gcroots` This preserves the basic Guix idea that deployment state and reachability should be represented explicitly rather than inferred from whatever happens to be on disk. ## Important differences from Guix ## 1. Fruix does not mirror Guix's on-disk generation layout 1:1 This is intentional. Guix heavily reuses its profile-generation model and represents a lot of meaning through symlink structure such as profile links and system generation links. Fruix keeps the **semantics** but uses a more explicit metadata-oriented layout for installed systems. Current Fruix layout: ```text /var/lib/fruix/system/ current -> generations/1 current-generation generations/ 1/ closure -> /frx/store/...-fruix-system-... metadata.scm provenance.scm install.scm ``` Why Fruix does this: - it makes deployment state easier to inspect directly - it gives FreeBSD-specific install and provenance details a clearer home - it keeps room for richer operator tooling later without losing the Guix properties So the rule of thumb is: - **same semantics as Guix where practical** - **not necessarily the same directory names or symlink vocabulary** ## 2. Fruix currently keeps `/run/current-system` simple Even though Fruix now records explicit generation metadata under `/var/lib/fruix/system`, it still keeps: - `/run/current-system -> /frx/store/...` rather than making `/run/current-system` point through a generation directory first. This was chosen to preserve compatibility with the already-validated activation and runtime model while adding explicit generation metadata separately. ## 3. Fruix treats source provenance more explicitly Guix sysadmins are used to derivation/store provenance. Fruix adds an extra emphasis because its current FreeBSD story depends on explicit source selection and materialization. Fruix routinely records: - declared FreeBSD source object metadata - materialized source store paths - source materialization metadata files - closure-level store layout metadata - install metadata on the target system This is more prominent in Fruix than most Guix system docs because FreeBSD base/source identity has been an active design concern for this project. ## 4. Fruix has installer-media workflows as first-class system actions Guix has installation media and image workflows, but Fruix's current system frontend makes these especially explicit because they are still part of the active architectural bring-up story. Current Fruix actions include: - `fruix system install` - `fruix system installer` - `fruix system installer-iso` That is a little more deployment-medium-oriented than the mental model many Guix users start with. ## 5. Device naming is more environment-sensitive than Guix users may expect Because Fruix is on FreeBSD, the install target device naming is not the same as on Linux. Validated examples: - installer disk-image path under QEMU: - `/dev/vtbd1` - installer ISO path under QEMU: - `/dev/vtbd0` - installer ISO path under XCP-ng: - `/dev/ada0` So compared with Guix-on-Linux intuition, Fruix operators should be more explicit about target-device selection during installation and installer-media validation. ## 6. Fruix does not yet have Guix-equivalent installed-system generation commands This is the biggest current operational gap. Fruix does **not** yet provide a mature equivalent of the familiar Guix System operator flow around in-place generation switching and rollback commands. Today, Fruix rollback is mostly: - declaration-driven - rebuild/redeploy based rather than: - switch current system generation in place through a dedicated command So if you come from Guix, assume that Fruix currently has: - strong closure/store semantics - explicit install artifacts - explicit generation metadata roots - but a less mature installed-system generation UX ## Where Fruix is intentionally trying to improve on Guix's representation Fruix is not trying to improve on Guix's core semantics. Guix already got those right. Where Fruix is intentionally experimenting is mostly the **representation layer**: - make generation state more legible to operators - make provenance more visible without needing to reconstruct it mentally from symlink layout alone - separate: - runtime entry point (`/run/current-system`) - installed deployment state (`/var/lib/fruix/system`) - retention roots (`/frx/var/fruix/gcroots`) That is why Fruix currently prefers a small per-generation metadata directory instead of only a bare generation link. ## Practical operator advice for Guix users If you are already comfortable with Guix, the safest Fruix mental model today is: 1. think in terms of immutable closures and declarations first 2. use `fruix system build` as the canonical starting point 3. treat image/install/installer/installer-iso as deployment materializers built from the same declaration 4. identify a deployment by: - closure path - source provenance metadata - install metadata 5. think of rollback today as: - “redeploy the earlier declaration again” rather than: - “switch to an already-managed previous generation in place” ## Status summary Today Fruix is closest to Guix in: - store and closure semantics - declarative deployment identity - rollback-friendly immutability - `/run/current-system` runtime model It differs most from Guix in: - FreeBSD platform details - source-provenance emphasis - installer-medium-oriented workflows - generation-layout representation - and the still-maturing installed-system generation command surface