fix(linux/build): add systemctl no-op shim for the build container (M1.1)
Some checks failed
Build SilverMetal Linux ISO (reproducibility-gated) / build-and-verify (push) Failing after 2m20s

Run #4257 cleared sanity-tests entirely (sq-git verification of every
submodule signature: ; tag/uncommitted relaxation: ) and reached
1200_prepare-build-machine, where it died:

    + sudo systemctl daemon-reload
    sudo: systemctl: command not found
    ERROR detected in script!: ././build-steps.d/1200_prepare-build-machine

derivative-maker assumes systemd is PID 1 on the build host. Upstream's
own container (linux/build/derivative-maker/docker/) runs
systemd-as-init via an entrypoint that masks irrelevant units and
declares its own. We don't want that surgery for M1.1 — it pulls in
cgroup mounts, --cgroupns=host, and a much bigger debugging surface.

Shim approach instead: install /usr/local/bin/systemctl that logs the
attempt to stderr and exits 0. /usr/local/bin precedes /usr/bin in
both default $PATH and sudo's secure_path, so it satisfies any
systemctl call regardless of whether the real binary later gets pulled
in by a package install. Standard pattern for systemd-aware Debian
build scripts in transient containers.

Risk if it doesn't suffice: the shim makes daemon-reload / restart /
mask calls succeed, but doesn't actually run any service. If a later
build step depends on (say) approx actually being up to serve cached
debs, we'll see the next failure and decide whether to escalate to
real systemd-in-container or skip the relevant build step.

Changes:
- Dockerfile.builder: add the shim with a brief log line to stderr;
  comment block documents the trade-off.
- build.sh: BUILDER_IMAGE digest re-pinned to sha256:70f160ab…5460
  (built natively on 10.0.0.51, shim verified working with
  `docker run … systemctl daemon-reload` returning 0).

Verified: shim emits "systemctl-shim: daemon-reload" to stderr and
exits 0.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-07 11:45:13 +01:00
parent 8a3cd0ba22
commit 7058fb775c
2 changed files with 20 additions and 1 deletions

View File

@@ -78,6 +78,25 @@ RUN set -eux; \
apt-get clean; \
rm -rf /var/lib/apt/lists/*
# systemctl no-op shim.
# derivative-maker's build steps call `sudo systemctl daemon-reload` /
# `systemctl restart approx` / etc. as part of host-machine preparation,
# assuming systemd is PID 1 on the build host. Upstream's own container
# image runs systemd-in-container; we don't, so any real systemctl call
# would fail. The shim returns success for every invocation and logs
# what was attempted, which is the standard pattern for running
# systemd-aware build scripts in transient containers without actual
# systemd. /usr/local/bin precedes /usr/bin in both default $PATH and
# sudo's secure_path, so this masks any real systemctl that might land
# later via package install.
RUN printf '%s\n' '#!/bin/sh' \
'# systemctl no-op shim for systemd-less build containers.' \
'# Logs the attempt to stderr and returns success.' \
'echo "systemctl-shim: $*" >&2' \
'exit 0' \
> /usr/local/bin/systemctl \
&& chmod 0755 /usr/local/bin/systemctl
# Non-root user for derivative-maker.
# Kicksecure's derivative-maker explicitly refuses to run as root and uses
# sudo internally for its privileged operations (debootstrap, mksquashfs,

View File

@@ -32,7 +32,7 @@ cd "${REPO_ROOT}"
# outside the LAN — it's the entry that fleet-wide /etc/docker/daemon.json
# registers as an insecure-registry. The host-style "docker-registry:5000"
# is *not* DNS-resolvable; do not use it.
BUILDER_IMAGE="${BUILDER_IMAGE:-docker-registry.silverlabs.uk/silvermetal-builder@sha256:c1490bab7785e86b431cea3efaf60c4c41b566fd3de085f5f0c4a53b236e5c97}"
BUILDER_IMAGE="${BUILDER_IMAGE:-docker-registry.silverlabs.uk/silvermetal-builder@sha256:70f160ab6084c49b81262e3625425848eb678c4b13175fb1b201cfb1fa075460}"
if [[ "${BUILDER_IMAGE}" != *"@sha256:"* ]]; then
echo "build.sh: BUILDER_IMAGE must be pinned by digest, got: ${BUILDER_IMAGE}" >&2