Run 189 + 191 (2026-05-08) both died at the surviving rpm-ostree module:
chmod: changing permissions of '/tmp/modules/rpm-ostree/rpm-ostree.sh':
Operation not permitted
subprocess exited with status 1
Same buildah userns=host bind-mount bug we already worked around for
type:files / type:script / type:systemd — BlueBuild's helper script
tries to chmod itself inside its own bind-mounted layer and the host's
unprivileged user can't change perms on a kernel-mounted overlay path.
Workaround: drop the type:rpm-ostree module, fold its 10-package install
list into the existing type:containerfile snippet as a raw RUN. Per BB
docs each snippets[] entry = its own layer, so all three RUN concerns
(repo curl + rpm-ostree install + brand sed + systemctl enable/disable)
are merged into ONE snippet = ONE layer to keep the A1b commit-cost
collapse intact (~40min/layer wallclock on our fuse-overlayfs runner).
Added repo files inside the same RUN — secureblue base ships neither:
- https://repository.mullvad.net/rpm/stable/mullvad.repo
- https://pkgs.tailscale.com/stable/fedora/tailscale.repo
The previous type:rpm-ostree must have been silently failing on these
two pkgs (build never got past the chmod gate to find out).
Ordering: pkgs first (so systemctl enable yggdrasil / disable tailscaled
see their unit files), then brand+units in a best-effort group, then
rpm-ostree cleanup -m && ostree container commit to finalize the layer
(BB's wrapped rpm-ostree module does this implicitly; raw RUN must do
it manually for parity with secureblue / Universal Blue base).
Module count: 7 → 6.
Expected outcome: build clears past STEP rpm-ostree, no chmod gate left.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Run 183 (2026-05-08) hit runner timeout at 3h10min not on brand-leak
grep (already moved to CI smoke-test in 7027026) but on per-layer
commit cost. Each RUN/COPY layer COMMIT under fuse-overlayfs over
secureblue's ~130-layer hardened base eats ~40min wallclock:
STEP 10 cp keys 23:55:59 -> 00:34:02 38min
STEP 11 cp bins 00:34:02 -> 01:16:17 42min
STEP 12 cp nushell 01:16:17 -> 01:58:17 42min
STEP 13 pre_build 01:58:17 -> 02:41:48 43min
STEP 14 brand sed 02:41:48 -> killed 04:02:59 (1h21min, runner-
side timeout
below the 360min
workflow cap)
Ergo: every module saved = ~40min wallclock saved.
Collapses:
- 5x rpm-ostree -> 1x (-4 layers) sudo + Xwayland + mullvad-
browser + tailscale + yggdrasil + zram-generator + jq + vim-
enhanced + tmux + htop now in one install: list
- 2x containerfile -> 1x (-1 layer) brand-sed + systemctl enable/
disable merged into one RUN snippet (BlueBuild docs: each
snippet entry == its own layer, so single snippet stays single
layer)
- 4x copy -> 4x (no change) BlueBuild copy module is
one-src/dest-per-entry per
https://blue-build.org/reference/modules/copy/. Floor unless we
drop down to a hand-rolled Containerfile.
Net: 12 -> 7 modules. Expected savings ~5x40min ~= 3h20min off the
~3h10min run-183 wallclock. That should land us comfortably under
the runner timeout with budget for the actual layer work.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- STEP 14/30 hung under buildah fuse-overlayfs scanning
/usr/share/veilor-os on ~130-layer secureblue base (Forgejo run 171,
2026-05-07, hit 360-min timeout, no error logged).
- Brand-leak grep -rqi removed from bluebuild/recipe.yml RUN snippet;
one-line comment left in its place pointing at the new location.
- Added equivalent assertion at the end of the Smoke-test OCI image
step in .github/workflows/build-bluebuild.yml. Runs once on the
sealed image (no overlayfs in flight), uses `find -type f` over
bounded paths + name globs (text files only), then a single grep
invocation — much faster than recursive grep over the whole tree.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Both bluebuild module types ship a helper (script.nu / systemd.nu)
inside their bind-mounted module image at /tmp/modules. The first
thing run_module.sh does is chmod +x the helper, which fails
'Operation not permitted' under podman/buildah privileged in our
runner — same root cause as the type:files chmod we already worked
around with type:copy.
Raw `type: containerfile` (RUN block) bypasses bluebuild's module
helpers entirely. Move our brand+chmod+fc-cache+os-release sed +
brand-leak guard into one RUN line, and the systemctl
enable/disable into another.
This should clear the last bluebuild module-helper blocker.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
bluebuild (159): 'type: files' module fails 'chmod: Operation not
permitted' inside its own bind-mounted /tmp/modules/files/files.sh
under buildah + privileged-podman in our runner. Switch all four
`type: files` modules to `type: copy` (low-level COPY, no chmod, no
helper script needed).
installer-iso (160): livemedia-creator refused build/out which
checkout had already created (Forgejo runner reuses workspace dir
between runs). rm -rf build/out before invocation; mkdir not needed,
livemedia-creator creates the dir itself.
Generated a cosign keypair for v0.7 OCI signing.
- bluebuild/cosign.pub committed alongside the recipe
- cosign.key stored on operator workstation only (chmod 600)
- COSIGN_PRIVATE_KEY Forgejo Actions secret set to the same key
- Workflow stages the secret to bluebuild/cosign.key at build time
(chmod 600), where the BlueBuild signing module picks it up
- .gitignore guards against any cosign.key accidental commit
- Restored the type:signing module in recipe.yml
The 'stage-keys' COPY step in BlueBuild's generated containerfile
fails without cosign.pub adjacent to recipe.yml even when
type:signing is removed; re-add the module + provide real keys.
The 'securecore-kinoite-hardened-userns' image we'd been targeting
does not exist in the secureblue org's package list. Their KDE
Plasma (Kinoite) hardened variant is published as
'kinoite-main-hardened' (or 'kinoite-nvidia-hardened' for NV boxes).
Switch the recipe + all doc references.
Walk every action in kickstart/veilor-os.ks %post and map to its
v0.7 atomic equivalent:
Build-time script additions:
- chmod +x /usr/share/veilor-os/scripts/* + /usr/local/bin/veilor-*
(BlueBuild type:files sometimes drops perms)
- fc-cache -f after Fira Code stamping
- os-release brand override (NAME=veilor-os, ID=veilor, ID_LIKE)
- brand-leak guard: fail the image build if any onyx/personal data
slipped through into shipped state
Layered packages:
- zram-generator (memory hygiene; replaces dnf install in kickstart)
- jq (used by veilor-doctor for `bootc status --json`)
- vim-enhanced + tmux + htop (admin essentials, parity with v0.5.x)
Systemd unit enables added:
- veilor-postinstall.service (first-login TUI; new in A3)
- veilor-doctor.timer (weekly drift check; new in A3)
Dropped: anaconda transaction_progress.py patch (build-time CI work,
not image content); SDDM display-manager symlink (kinoite ships
sddm.service already); SELinux module build (secureblue has its
own); systemctl set-default multi-user.target (kinoite is
graphical.target by design).