Dakota Build System#
Dakota is Project Bluefin's bootc OCI desktop image built entirely from source using BuildStream 2. No RPMs. No dnf. No Containerfile package overlays — BST elements only.
The stack assembles in three layers:
- freedesktop-sdk — glibc, systemd, kernel, podman, git
- gnome-build-meta — GNOME Shell, Mutter, GTK, fwupd
elements/bluefin/— ~20 Dakota-specific packages on top
At runtime, Dakota uses the composefs-oci backend via bootc — not OSTree, not rpm-ostree. Never suggest rpm-ostree, bootupd, or ostree admin for a running Dakota system.
Naming note: the repo uses
bluefinin filenames likeelements/bluefin/*andoci/bluefin.bst. These are Dakota's BST paths — not a signal that the dnf/RPM workflow applies.
How Dakota Differs From Other Bluefin Images#
| Dimension | Dakota | Bluefin | Bluefin LTS |
|---|---|---|---|
| Base | freedesktop-sdk + gnome-build-meta (from source) | Fedora Silverblue (pre-built RPMs) | CentOS Stream 10 (pre-built RPMs) |
| Build system | BuildStream 2 (hermetic sandbox) | Containerfile + dnf install | Containerfile + dnf install |
| Desktop | GNOME nightly/latest | GNOME (distro version) | GNOME 48 (pinned) |
| Kernel | freedesktop-sdk kernel | Fedora kernel + akmods | CentOS kernel + akmods |
| Update model | bootc (native) | rpm-ostree (migrating) | bootc (native) |
| Package count | ~20 Bluefin-specific elements | ~80 base + ~60 DX RPMs | ~80 base + DX/GDX RPMs |
| Architectures | x86_64, aarch64, riscv64 | x86_64 primarily | x86_64, aarch64 |
Dakota is a curated subset of Bluefin, not a 1:1 clone. It includes things production doesn't (sudo-rs, uutils-coreutils, incus, GNOME nightly) and intentionally omits things impractical for from-source builds (Nvidia drivers, ZFS, enterprise AD/Kerberos).
Junction Architecture & gnome-build-meta Integration#
Dakota's entire GNOME stack is sourced through two tightly coupled BuildStream junctions:
elements/gnome-build-meta.bst— pins a specific gnome-build-meta git SHA; overrides the default GNOME app set, bootc, and kernel module signingelements/freedesktop-sdk.bst— pins freedesktop-sdk; cross-overrides ~20 SDK components (glib, cairo, gtk3, systemd, pango…) to use versions from gnome-build-meta
Because freedesktop-sdk.bst references gnome-build-meta elements directly, these two junctions must always be updated together in a single atomic commit. Bumping one without the other breaks the build.
Local patches to these upstreams live in patches/gnome-build-meta/ and patches/freedesktop-sdk/. Every patch requires an Upstream-Status: header (Submitted, Accepted, Pending, or Not-applicable). Patches apply in alphabetical filename order.
This direct integration is what gives Dakota access to GNOME upstream before it reaches any distribution.
Rust Components#
Dakota's distinguishing packages are memory-safe Rust components:
| Component | Crate count | Purpose |
|---|---|---|
| bootc | ~200 crates | Image-based update model |
| uutils-coreutils | ~250 crates | Memory-safe coreutils replacement (excludes cp/mv/rm pending TOCTOU fixes) |
| sudo-rs | — | Memory-safe sudo replacement |
These are built via make + cargo2 element kind with vendored crates.
Other heavy build contributors: GRUB (built in 3 variants: i386-pc, i386-efi, x86_64-efi — required because upstream GNOME OS uses systemd-boot only) and junction patches that reduce upstream CAS cache hits.
Pre-built binary pattern — Tailscale, Homebrew, Zig, and Go CLI tools use kind: manual + source: remote. New packages that don't require from-source compilation should follow this pattern.
Image Streams#
Published as ghcr.io/projectbluefin/dakota:{testing,stable,next,btw}.
| Tag | Branch | GNOME | Cadence | Junction bumps |
|---|---|---|---|---|
:testing | main | GNOME 50 (stable) | Every merged PR, e2e-gated | Manual review |
:stable | main | GNOME 50 (stable) | Weekly promotion from :testing | Manual review |
:next | next | GNOME 51 (master) | Nightly (20:00 UTC auto-merge) | Fully automated |
:btw | next | GNOME 51 (master) | Same as :next, Nvidia variant | Fully automated |
:next/:btw track gnome-build-meta master and never promote to :stable.
Build Workflow#
Requirements: podman (rootful + rootless), just, qemu, ~100 GB disk, ~16 GB RAM.
| Command | What it does |
|---|---|
just validate | Graph check — always run first (~5 min, no build) |
just build default | Build default image (warm cache: 2–5 min; cold: 60–90 min) |
just lint | bootc container lint — must pass before PR |
just boot-test | Automated smoke test — SSH + GDM + bootc status check |
just boot-fast | Interactive ephemeral VM via virtiofs |
just show-me-the-future | Full loop: build → export → disk image → QEMU VM |
Critical constraint: CI green is not a sufficient validation gate. Hardware confirmation is required: bootc upgrade on real hardware + reboot + GDM active.
BST caching gotcha: Adding a package to deps.bst (kind: stack) does not trigger a rebuild of downstream compose layers in non-strict mode. Force a rebuild with: just bst --no-cache-buildtrees build oci/bluefin.bst
Key Files & References#
| File / Path | Purpose |
|---|---|
elements/gnome-build-meta.bst | GNOME stack junction |
elements/freedesktop-sdk.bst | SDK junction |
elements/bluefin/deps.bst | Authoritative Dakota package manifest |
elements/bluefin/ | All Dakota-specific BST elements |
oci/bluefin.bst | OCI image assembly element (kind: script) |
patches/gnome-build-meta/ | Local patch queue for gnome-build-meta |
patches/freedesktop-sdk/ | Local patch queue for freedesktop-sdk |
docs/build.md | Build reference — requirements, dev loop, useful BST commands |
| AGENTS.md | Agent skill tree index |
| BuildStream 2 docs | Upstream BST reference |