Run #4255 reached deeper into 1100_sanity-tests, finished its apt-get
phase, and then died at the supply-chain verification step:
/workspace/.../help-steps/git_sanity_test: line 184: sq-git: command not found
ERROR: sq-git verification failed: main repo
INFO: If this is intentional, configure your own sq-git policy file.
See 'buildconfig.d/30_signing_key.conf'.
derivative-maker uses sq-git (sequoia-git) to authenticate the commit
chain against an OpenPGP policy file before building. The policy file
itself ships in the upstream repo (./openpgp-policy.toml) and the
trust-root defaults are correctly configured by help-steps/variables
(line 232 + 290) for non-redistributable builds — i.e. the verification
machinery is fully wired and just needs the binary.
Aligns with the upstream container's package list at
linux/build/derivative-maker/docker/derivative-maker-docker-setup.
Changes:
- Dockerfile.builder: add sq, sqv, sqop, sequoia-git,
sequoia-chameleon-gnupg, gpg-agent. All available in trixie main.
- build.sh: BUILDER_IMAGE digest re-pinned to sha256:c1490bab…5c97
(rebuilt on 10.0.0.51, sq-git binary verified present at /usr/bin/sq-git).
No reproducibility implications — image rebuilds against the same
pinned snapshot timestamp.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Run #4254 finally got past every harness issue and into derivative-
maker's actual sanity-tests, where it died with:
You are attempting to build on an unsupported operating system or version.
detected operating system codename: 'bookworm'
expected operating system codename: 'trixie'
The pinned derivative-maker tag (18.1.7.4-developers-only) requires
Debian 13 (trixie) as the build host. Upstream's own
linux/build/derivative-maker/docker/Dockerfile uses
`FROM debian:trixie-slim`. We picked bookworm originally and the tag
mismatch wasn't caught until the build actually ran.
Changes:
- Dockerfile.builder: FROM debian:bookworm-slim →
debian:trixie-slim @ sha256:cedb1ef4…2c5a (resolved 2026-05-07 on
the runner host). sources.list suite names follow:
`bookworm` → `trixie`, `bookworm-security` → `trixie-security`.
snapshot.debian.org pin (20260415T000000Z) is unchanged — snapshots
are date-keyed, so the same timestamp resolves trixie's dists/.
- silvermetal-base.conf: DERIVATIVE_DIST `bookworm` → `trixie` for
consistency (the value isn't passed to derivative-maker — there's
no --dist option — but it's referenced by the build.sh prologue
and we shouldn't have a stale codename floating around).
- build.sh: BUILDER_IMAGE digest re-pinned to sha256:7d893178…1890
(rebuilt natively on 10.0.0.51 against the new base, pushed).
The reproducibility guarantee is unchanged in shape — same snapshot
timestamp, same source-date-epoch derivation, just a different stable
host OS.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Run #4251 advanced past checkout and into derivative-maker, then died
immediately:
ERROR: This must NOT be run as root (sudo)!
ERROR: Exiting ./derivative-maker with non-zero exit code 1.
Errors Detected: 0. Execution Time: 00:00:00.
Kicksecure's derivative-maker explicitly refuses to run as root — it
expects a regular user with passwordless sudo and uses sudo internally
for the privileged operations (debootstrap, mksquashfs, chroot mounts).
Our minimal debian-slim builder image had a `builder` user (uid 1000)
but no sudo, no sudoers entry, and the container ran as root.
Aligns with the upstream Kicksecure container pattern at
linux/build/derivative-maker/docker/derivative-maker-docker-setup
(uses USER=user with `${USER} ALL=(ALL) NOPASSWD:ALL`).
Changes:
- Dockerfile.builder: install `sudo` (and `fakeroot` while we're here —
upstream sanity-tests pulls this in via apt at build time, but having
it baked avoids a snapshot.debian.org round-trip every run); add
passwordless sudoers entry for builder; correct the misleading
comment that claimed root was needed.
- New scripts/build-inner.sh: the inner derivative-maker invocation
pulled out of build.sh's heredoc. Once we needed to drop privileges
via runuser, the nested-heredoc / nested-quoting situation became
unmaintainable; a regular script with normal quoting is far cleaner.
- build.sh: inner heredoc now just chowns the workspace to builder and
runuser's into build-inner.sh. ${REPO_ROOT} and ${BUILD_DIR} continue
to be forwarded into the container via -e.
- build.sh: BUILDER_IMAGE digest re-pinned to sha256:f8f0db37…1bedc
(rebuilt and pushed natively on 10.0.0.51 — never on the WSL/aarch64
dev box, see reference_silvermetal_runner.md memory).
Verified: bash -n on both scripts; image builds and pushes cleanly.
Pushing this commit triggers a fresh CI run that will exercise it.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
build.sh ran fine locally but failed in Gitea Actions on the first
reproducibility-gated run (#4250) with:
bash: line 3: /work/linux/build/config/silvermetal-base.conf:
No such file or directory
Root cause: classic Docker-out-of-Docker confusion. build.sh runs
inside the act_runner job container, which talks to the host's docker
daemon via the mounted /var/run/docker.sock. The "-v ${REPO_ROOT}:/work"
flag was being interpreted by the host daemon against the host
filesystem, where /workspace/SilverLABS/SilverMetal does not exist;
docker silently auto-created an empty dir there and mounted that as
/work, so the config source target was missing.
Fix: detect GITHUB_ACTIONS and use --volumes-from "$(hostname)" in CI
to inherit the parent job container's /workspace mount intact. Locally
we keep a bind mount, but use the same path inside and outside
(${REPO_ROOT}:${REPO_ROOT}) so the inner heredoc is identical in both
modes. Inner script now references "${REPO_ROOT}/..." and
"${BUILD_DIR}/..." instead of the synthetic /work and /out paths.
No reproducibility implications — bind topology doesn't affect bytes
inside the ISO.
Verified locally: bash -n passes; structural change only, behaviour
preserved for the non-CI path.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two corrections to f9e606d:
1. Registry hostname: docker-registry:5000 isn't DNS-resolvable on the
SLAB docker host (verified). The fleet-wide convention is the canonical
docker-registry.silverlabs.uk URL, registered as an insecure-registry
in /etc/docker/daemon.json on every docker host.
2. Architecture: the original push from WSL2-on-aarch64 produced an arm64
image that won't run on the amd64 runner. Rebuilt natively on the docker
host. New manifest digest (amd64-only):
sha256:9e7161f9f180483f434074d7f32c27c907955232bd0c44efe6dc0ee1d9e56ae0
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Image built from Dockerfile.builder@36f7672 was pushed to both
docker-registry:5000 (internal) and docker-registry.silverlabs.uk
(external) under tags m1.1-bootstrap + latest. Both URLs serve the
same registry, so the manifest digest is identical:
sha256:cedef039425e0b0f5901c1023eda820c7aa38ab4b81c2bb1e12d64cadb3d6c85
Default points at the internal hostname for CI; external dev overrides
via BUILDER_IMAGE env var.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Vendors Kicksecure derivative-maker as a pinned submodule (18.1.7.4),
adds the wrapper + verify + diagnose scripts, the pinned builder image,
and the reproducibility-gated Gitea Actions workflow. Base flavour only —
no hardening overlay (that's M1.2).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>