Commit graph

22 commits

Author SHA1 Message Date
s8n-ru
702702650a fix(bluebuild): move brand-leak check recipe RUN -> CI smoke-test
Some checks failed
Build veilor-os Installer ISO / Build installer ISO (push) Failing after 28s
Build veilor-os OCI (BlueBuild) / Build + push OCI (push) Failing after 3h10m14s
- 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>
2026-05-08 00:52:09 +01:00
claude-veilor-bot
8ffd6fb48d ci(bluebuild): bump timeout 60 → 360 min (first-time pulls slow)
Some checks failed
Build veilor-os OCI (BlueBuild) / Build + push OCI (push) Failing after 3h11m53s
166 ran 6hr through STEPS 10-14 (cosign keys cp, stage-bins cp,
nushell pull, pre_build.sh) — fuse-overlayfs with 130+ layers makes
each cp/RUN take ~40min on first build. Subsequent builds will be
faster (cached layers).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-07 08:11:06 +01:00
obsidian-ai
a06f54dd79 ci(bluebuild): --security-opt label=disable + seccomp=unconfined for files module
BlueBuild's files module fails with 'chmod: Operation not permitted' on
its own bind-mounted /tmp/modules/files/files.sh when run under podman.
Disable SELinux relabeling + seccomp filter on the bluebuild CLI
container so its nested buildah can chmod inside layer mounts.
2026-05-06 21:08:59 +01:00
obsidian-ai
e6aa2d14a8 ci(bluebuild): symlink cosign.{pub,key} to repo root for stage-keys COPY 2026-05-06 18:12:29 +01:00
obsidian-ai
266090ea0d ci(bluebuild): swap 'file' cmd for 'head' (file not in veilor-build:43) 2026-05-06 18:06:58 +01:00
obsidian-ai
b4c0feb30d ci(bluebuild): -vv + diagnostic ls before bluebuild invocation 2026-05-06 18:02:02 +01:00
obsidian-ai
c152953089 ci(bluebuild): add cosign keypair signing infra
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.
2026-05-06 17:48:58 +01:00
obsidian-ai
2c197796e3 ci(bluebuild): locate podman auth.json + copy to stable bind path
podman login writes to $XDG_RUNTIME_DIR/containers/auth.json by
default; that path varies and was missing. Probe known locations,
copy into /root/.config/containers/auth.json so the bind into the
bluebuild container has a stable source.
2026-05-06 17:21:21 +01:00
obsidian-ai
237968bfac bluebuild: switch base to ghcr.io/secureblue/kinoite-main-hardened
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.
2026-05-06 17:15:54 +01:00
obsidian-ai
f50f427ff8 ci(bluebuild): login to GHCR with PAT, share auth.json into bluebuild
GHCR rate-limited anonymous pulls (403 on bearer token). Login with
the GHCR_PULL_TOKEN secret (s8n-ru read-only PAT), then bind-mount
podman's auth.json into the bluebuild CLI container so its inner
buildah sees the same login.
2026-05-06 17:12:16 +01:00
obsidian-ai
ded80c6e15 ci(bluebuild): pre-pull secureblue base + share podman storage
GHCR rejected skopeo's anonymous manifest call from inside the
bluebuild CLI container. Pre-pull the secureblue base on the host
podman (which handles the anonymous token dance), then bind-mount
/var/lib/containers/storage into the bluebuild container so its
buildah sees the cached base layer. Drop deprecated --inspect-driver
flag while we are touching the invocation.
2026-05-06 17:09:10 +01:00
obsidian-ai
48ccabe914 ci(bluebuild): bluebuild bin lives at /usr/bin not /usr/local/bin 2026-05-06 17:06:33 +01:00
obsidian-ai
756b03aa5c ci(bluebuild): override CLI container entrypoint to bluebuild binary
Container's default entrypoint is dumb-init, which interpreted 'build'
as a command to exec rather than as a bluebuild subcommand. Pin
--entrypoint /usr/local/bin/bluebuild and pass 'build ...' as args.
2026-05-06 17:03:53 +01:00
obsidian-ai
1e70cc5461 ci(bluebuild): use ghcr.io/blue-build/cli container instead of action
The blue-build/github-action requires docker buildx which podman
doesn't ship. Symlinking podman as docker isn't enough — the action
calls 'docker buildx inspect' / 'docker buildx rm' which podman
doesn't implement. Pull the official BlueBuild CLI container and run
it with --build-driver buildah; works against podman storage with no
docker dependency.
2026-05-06 17:01:22 +01:00
obsidian-ai
9ee2cec20e ci(bluebuild): symlink podman -> docker (action needs docker CLI) 2026-05-06 16:58:50 +01:00
obsidian-ai
8926894ceb ci(bluebuild): chown /etc/sudo* to root before sudo (userns=host fix) 2026-05-06 16:56:36 +01:00
obsidian-ai
6d8164c199 ci(bluebuild): use blue-build/github-action composite (no CLI binary release)
BlueBuild CLI does not ship pre-built binaries on GitHub Releases
(latest tag v0.9.35 has no assets — install path is cargo or their
container image). Drop the curl-tarball install step and use the
official composite action @ pinned SHA — it runs podman + buildah
inside, works on Forgejo runner identically to GH-hosted because
it's bash, not node-bound.
2026-05-06 16:54:04 +01:00
obsidian-ai
bbdafbce94 ci(bluebuild): slim dnf list + install cosign from upstream binary
dnf5 in Fedora 43 strict-fails when 'already installed' packages
appear in -y install. Drop git/curl/tar/sudo (shipped in
veilor-build:43 image already) and use --skip-unavailable. cosign
isn't packaged in F43 — pull v2.4.1 static binary from upstream.
2026-05-06 16:51:17 +01:00
obsidian-ai
61fec5e1a9 ci(bluebuild): port build to Forgejo runner (nullstone label)
A1 inline (agent failed on worktree base mismatch). Adapt
build-bluebuild.yml to run on the Forgejo self-hosted runner using
the same lessons from build-iso.yml debug:

- runs-on: nullstone (resolves to veilor-build:43, fedora43+nodejs)
- BlueBuild CLI installed in-job from upstream release tarball v0.9.10
- podman/buildah/skopeo/cosign installed via dnf
- bluebuild build with podman driver + skopeo inspect + cosign signing
- Push primary to Forgejo registry git.s8n.ru/veilor-org/veilor-os
- GHCR push gated to github.server_url == 'https://github.com' only
- SBOM + attest-build-provenance gated GH-only (Forgejo has no Fulcio)
- All third-party actions remain pinned to node20-shipping versions

Secrets needed in Forgejo repo settings:
- FORGEJO_REGISTRY_TOKEN: PAT with package:write on veilor-org
- FORGEJO_REGISTRY_USER: 's8n-ru' (or org member with write scope)
2026-05-06 16:44:52 +01:00
obsidian-ai
e50c9a3b43 ci(bluebuild): pin actions to node20-safe tags
forgejo-runner v6.4.0 javascript runtime is node20. Pin every
javascript action used in the spike branch's workflows to the last
release that ships node20.

- actions/checkout v4 -> v4.1.7 (3 files)
- softprops/action-gh-release v2 -> v2.0.4 (build-iso)
- anchore/sbom-action v0 -> v0.17.2
- actions/attest-build-provenance v2 -> v2.2.3
- blue-build/github-action@v1 unchanged (TODO: SHA pin)

This is the spike-branch counterpart of the main-branch fix in
feat/runner-fix-docker-sock-and-node20.
2026-05-06 13:54:12 +01:00
s8n
f2e36bfead ci(bluebuild): pin blue-build/github-action to commit SHA
Replace @v1 with @24d146df25adc2cf579e918efe2d9bff6adea408 (the commit
v1 currently resolves to). Tag pins on third-party actions are mutable
— a maintainer or attacker can re-point v1 at a malicious commit and
silently change what runs on every push.

Trailing comment '# v1' preserves human readability for future bumps.

Refs: 9-agent CI hardening wave (agent 8), 2026-05-05.
2026-05-06 10:32:13 +01:00
veilor-org
3c247bc601 v0.7 spike: BlueBuild recipe + ostreecontainer kickstart + cosign workflow
Initial scaffold for the v0.7 hybrid path. Spike branch only — does
NOT land in main until success criteria pass (see bluebuild/README.md).

## What this commits

- bluebuild/recipe.yml — BlueBuild recipe extending
  ghcr.io/secureblue/securecore-kinoite-hardened-userns:latest with:
  * veilor branding overlay (overlay/, assets/, scripts/ at /usr/share/veilor-os)
  * sudo restored (revert secureblue's run0-only)
  * Xwayland restored (some apps still need it)
  * mullvad-browser layered alongside Trivalent (default browser kept)
  * tailscale + yggdrasil packages (mesh stack layers 1 + 2)
  * tailscaled.service pre-disabled (awaits first-boot prompt)
  * yggdrasil.service enabled (idle warm-fallback per STRATEGY.md)
  * veilor-firstboot.service + veilor-modules-lock.service enabled
  * cosign signing module configured

- bluebuild/config/just/60-veilor.just — ujust recipes:
  * install-reticulum (RetiNet AGPL fork — mesh layer 3)
  * install-reticulum-rnode (LoRa hardware)
  * install-thorium (opt-in browser with explicit CVE-lag warning)
  * veilor-mesh-join (token paste / QR for tailscale onboarding)

- bluebuild/README.md — spike doc + smoke-test commands + 5-item
  success criteria checklist

- kickstart/install-ostreecontainer.ks — install kickstart template
  for the v0.7 path. No %packages block; uses
  `ostreecontainer --url=ghcr.io/veilor-org/veilor-os:43 --transport=registry`
  to populate / from the OCI image directly during anaconda's install
  pass. No first-boot rebase, no transition window. Keeps existing
  LUKS+btrfs partitioning verbatim.

- .github/workflows/build-bluebuild.yml — GH Actions workflow:
  * Triggered on push to v0.7-bluebuild-spike, weekly cron, dispatch
  * Uses blue-build/github-action@v1 (TODO: pin to commit SHA per
    CI hardening agent 8 follow-up)
  * Builds + cosign-signs (keyless via Sigstore) + pushes to GHCR
  * Smoke-tests the OCI image (sudo, mullvad-browser, yggdrasil,
    tailscale all present)
  * Generates SBOM (SPDX) via anchore/sbom-action
  * Publishes SLSA build provenance attestation

## What this does NOT change

- main branch is untouched. v0.5.x kickstart path keeps shipping.
- kickstart/veilor-os.ks (the live-ISO ks) is untouched — the v0.7
  hybrid uses the existing live-ISO build path; only the install-time
  ks (install-ostreecontainer.ks) is new.
- overlay/, scripts/, assets/ are untouched on this branch — the
  recipe pulls them in via `type: files` modules at build time.

## Spike success criteria (reproduced from bluebuild/README.md)

- [ ] `bluebuild build recipe.yml` exits 0
- [ ] `bootc container lint` exits 0 on resulting image
- [ ] `podman run` smoke-test passes
- [ ] CI workflow builds + cosign-signs + pushes to GHCR
- [ ] Installer ISO using `ostreecontainer` against this OCI reaches
      SDDM with admin login on first boot

If all 5 land, merge v0.7-bluebuild-spike → main as v0.7.0.

## Reference

- docs/STRATEGY.md (full plan)
- docs/ROADMAP.md v0.7 (schedule)
- docs/THREAT-MODEL.md (publish before v0.7 ship)
- secureblue: https://github.com/secureblue/secureblue
- BlueBuild: https://blue-build.org
- ostreecontainer: https://docs.fedoraproject.org/en-US/bootc/anaconda-install/
2026-05-05 15:30:04 +01:00