Skip to main content

max / alloy_tui

7.8 KB · 100 lines History Blame Raw
1 # Image composition
2
3 How Alloy is built and delivered. bootc + Containerfile, source on `git.sr.ht`, CI on `builds.sr.ht`, container image on `quay.io`. Companion to [STACK.md]STACK.md.
4
5 ## Landscape
6
7 Silverblue and its atomic siblings don't have a mutable root filesystem. The OS is an immutable commit, a tree of files that swaps atomically at boot. Users can't `dnf install` into a running system; they either layer packages locally (rebuilding their image) or pull a pre-built image.
8
9 For a distro builder, "image composition" is the question of how you produce that immutable commit and how users receive it.
10
11 ## Options considered
12
13 ### rpm-ostree compose (traditional)
14
15 Classical Silverblue build. Treefile in YAML declares packages, kernel arguments, systemd presets. `rpm-ostree compose tree` produces an ostree commit, pushed to an ostree repository. Users pull via `rpm-ostree upgrade`.
16
17 **Cost:** you host an ostree repository (real infrastructure: nginx serving `/var/ostree` or equivalent). Legacy-shaped; Fedora itself is migrating away.
18
19 ### bootc + Containerfile (modern, where Fedora is going)
20
21 The OS *is* an OCI container image. Distributed via any OCI registry. Users pull with `bootc switch <registry-url>` and reboot. Build is `podman build` from a Containerfile, the same as building any Docker image.
22
23 **Cost:** pre-1.0, occasional breaking changes as bootc matures. Alloy accepts drift maintenance the same way it does for nushell config and userChrome.css.
24
25 ### ublue-downstream (rejected)
26
27 Universal Blue's convention is exactly the bootc + Containerfile pattern above, using `FROM ghcr.io/ublue-os/main`. Battle-tested. But being downstream of ublue means inheriting ublue's opinions and coupling to their release cadence, which [STACK.md's Base section]STACK.md#base explicitly rejects.
28
29 **The nuance:** Alloy uses the ublue-style *convention* (Containerfile, OCI registry, CI-driven build) *without* using ublue's base image. `FROM quay.io/fedora/fedora-bootc:43`, not `FROM ghcr.io/ublue-os/main`. That's what "alongside ublue, not downstream" resolves to in practice.
30
31 ### "Install Silverblue and run our script" (non-option)
32
33 Zero build infrastructure. But users get a mutated Silverblue with an Alloy veneer, not shipped as "Alloy." Manifesto commitment breaks. Rejected.
34
35 ## Pick: bootc + Containerfile
36
37 The tool choice. Rationale summarized: aligns with where Fedora is going; build tooling is `podman build`; distribution is any OCI registry (free); Containerfile is a single-file OS specification.
38
39 ## Delivery stack
40
41 ### Source: `git.sr.ht/~maxmj/alloy`
42
43 Primary remote. Alloy is source-hosted on sr.ht for the same reasons the rest of Make Creative's public work is: independence from big-tech-monopoly infrastructure at the layer where users install software. `srht` is a canonical remote for Alloy, not a backup.
44
45 ### CI: `builds.sr.ht` (disabled during local-iteration phase)
46
47 sr.ht ships Fedora build VMs with `dnf`, `podman`, `buildah`, `skopeo` preinstalled. When ready, the build file at `.builds/alloy-image.yml` triggers on every push.
48
49 **Current state:** the build file lives at `builds.disabled/alloy-image.yml`, parked outside the `.builds/` path sr.ht auto-runs, so no CI resources are consumed while the Containerfile is being iterated locally. Rename the directory back to `.builds/` and push to re-enable.
50
51 ### Registry: `quay.io` (deferred until distribution starts)
52
53 Red Hat's container registry is the intended destination once Alloy has an image worth distributing. Free for public images, ecosystem-coherent with the `quay.io/fedora/fedora-bootc:43` base.
54
55 **Current state:** no registry provisioned. `.builds/alloy-image.yml` runs a **build + lint smoke test** only, validating the Containerfile on every push, without publishing anywhere. When the image is worth distributing, the CI file grows back `sign` and `push` tasks and `quay.io/alloy/alloy` gets provisioned with a robot account.
56
57 Rejected alternatives (for when distribution starts): ghcr.io (source-registry ecosystem mismatch), Docker Hub (pull rate limits, no advantage), self-hosted (real infra commitment, not worth v0 operational load; revisit v2+).
58
59 ### Signing: cosign (deferred alongside distribution)
60
61 Once a registry is publishing images, cosign signs them as a CI task. Private key stored as an sr.ht secret; public key published in the Alloy repo. Users verify via `bootc switch --signature-source=<url>`. Nothing to set up until distribution starts.
62
63 ## Layer structure
64
65 The Containerfile at the repo root (see `Containerfile`) sketches:
66
67 1. **Base:** `FROM quay.io/fedora/fedora-bootc:43`.
68 2. **Third-party repos:** Tailscale, any COPRs Alloy depends on for packages not in Fedora main.
69 3. **Package additions:** the full Alloy stack from [STACK.md]STACK.md: compositor, bar, launcher, notifications, terminal, editor, shell, viewers, utilities, continuity daemons, fonts, themes.
70 4. **Package removals:** stock Silverblue desktop pieces Alloy replaces (gnome-shell, gdm; the latter gated on the greeter pick).
71 5. **Config tree:** the tree at `etc/skel/.config/*` and `etc/skel/.mozilla/*` (new-user defaults, including the Firefox first-launch profile seed), `etc/*` (system-wide, including `etc/firefox/policies/policies.json`), and `usr/lib64/firefox/*` (Firefox autoconfig + `mozilla.cfg` default prefs) in the repo maps 1:1 into the image.
72 6. **Systemd presets:** which services are enabled by default (syncthing off by default, gammastep off until enrolled, alloy-hinged conditionally on FW12, etc.).
73 7. **Branding:** os-release, plymouth splash.
74 8. **Validation:** `bootc container lint` runs at build.
75
76 The base browser (Firefox) ships as an RPM baked into the image: one code path, no first-boot delay, and enterprise policies (`/etc/firefox/policies/policies.json`) take effect immediately. The `flatpak` client is included so users can pull ungoogled-chromium and other Flathub-only apps on demand post-install; no Flatpaks are provisioned at build or first-boot time.
77
78 ## Update cadence
79
80 The sr.ht build triggers on:
81
82 - **Push to `main`**: Alloy commits.
83 - **Weekly cron**: picks up upstream Fedora base image updates. sr.ht doesn't have webhook receivers for external triggers, so cron is the pragmatic answer.
84
85 Users receive updates via `bootc upgrade`: no push notifications, no forced restart. Alloy's update UX is the standard bootc UX.
86
87 ## Fedora version tracking
88
89 Pinned explicitly, currently `:43`. Bumps to `:44` and beyond are a deliberate act: Alloy tests the new base, updates the Containerfile, ships. Not automatic. This is the "correctness over deadline" pattern applied to base tracking.
90
91 Note that `build/alloy-0.0.yaml` remains bootc-image-builder's fedora-42 package set, because bib ships no fedora-43 definition. That is deliberate and documented in the file's own header; it is not drift.
92
93 ## Open questions
94
95 - [ ] Verify which Alloy packages are in Fedora main vs. need COPRs. Candidates that may need COPRs: `satty`, `wl-screenrec` (depending on Fedora version). Audit at v0 packaging time.
96 - [ ] `bootc-image-builder` for ISO generation. First-time-user path is `bootc install` from a live environment; the ISO is what makes that a smooth experience. Verify the ISO builder handles Alloy's specific package set.
97 - [x] **Containerfile stage policy: multi-stage only where a non-Fedora Rust binary needs to ship.** Currently that's one stage (`rust-build` for wl-screenrec); everything else comes from RPM in the runtime stage. Do not add stages preemptively.
98 - [x] sr.ht account: **`~maxmj`** for v0. LLC-owned `~makecreative` remains the long-term target; migration if/when the project grows.
99 - [x] **Publish `:latest`, `:<fedora-version>`, and `:<fedora-version>-YYYYMMDD` tags.** Currently `:latest`, `:43`, `:43-YYYYMMDD`. `:latest` for casual users, the bare version for version-pinned users, the dated tag for reproducibility. Wired up when distribution starts.
100