Three independent hardenings, addressing a review finding that the
kernel and image build pipelines were relying on HTTPS alone for
artifact integrity.
scripts/make-generic-kernel.sh
- Fetch the detached PGP signature (linux-<ver>.tar.sign) alongside
the tarball and verify it with gpg before extraction. An isolated
$GNUPGHOME under the tempdir keeps the kernel signers out of the
invoking user's keyring.
- Import the three kernel.org release signing keys (Greg KH / Linus /
Sasha Levin) from keyserver.ubuntu.com, falling back to
keys.openpgp.org. Ubuntu comes first because keys.openpgp.org strips
unverified UIDs on upload, leaving gpg with UID-less keys it
refuses to trust.
- Require VALIDSIG (cryptographic proof) rather than GOODSIG
(printed even for expired keys) before proceeding. Verified
end-to-end against a clean tarball (accepts) and a byte-flipped
tampered copy (rejects with BADSIG).
- gpg + gpgv + xz added to the required-tools check.
images/golden/Dockerfile
- Pin Docker's apt signing key by fingerprint. After downloading
/etc/apt/keyrings/docker.asc we gpg --show-keys --with-colons it,
extract the fpr, and compare against the expected
9DC858229FC7DD38854AE2D88D81803C0EBFCD88. A tampered or swapped key
aborts the build before any apt repo metadata is fetched.
- Replace `curl https://mise.run | sh` with a pinned GitHub release
binary (mise v2026.4.18, linux-x64) verified against its published
sha256. Refuses to build on unknown architectures rather than
silently installing a binary we have no hash for.
- Add gnupg to the ESSENTIAL apt-get install so the fingerprint check
has gpg available.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The golden-image Dockerfile + catalog pipeline replaces the entire
manual rootfs-build stack. With that shipped, the per-distro shell
flows are dead code.
Removed:
- scripts/customize.sh, scripts/interactive.sh, scripts/verify.sh
- scripts/make-rootfs{,-void,-alpine}.sh
- scripts/register-{void,alpine}-image.sh
- scripts/make-{void,alpine}-kernel.sh
- internal/imagepreset/ (only consumer was `banger internal packages`,
which fed customize.sh)
- examples/{void,alpine}.config.toml
- Makefile targets: rootfs, rootfs-void, rootfs-alpine, void-kernel,
alpine-kernel, void-register, alpine-register, void-vm, alpine-vm,
verify-void, verify-alpine, plus the ALPINE_RELEASE / *_IMAGE_NAME
/ *_VM_NAME variables
The void-6.12 kernel catalog entry is also gone — golden image pairs
with generic-6.12 and nothing else in the catalog depended on it.
Consolidated: imagemgr now holds the small DebianBasePackages list +
package-hash helper inline, so the `image build --from-image` flow
(still supported) no longer pulls from a separate imagepreset package.
Net: 3,815 lines deleted, 59 added. No runtime functionality removed
beyond the `banger internal packages` subcommand (hidden, used only
by the deleted customize.sh).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three fixes discovered during end-to-end boot testing on Firecracker:
- Install udev + dbus alongside systemd. Both are Recommends of the
systemd package, skipped by --no-install-recommends. Without udev,
systemd never activates device units (dev-vdb.device stays inactive
even after the kernel enumerates /dev/vdb) and the work-disk mount
hangs forever. dbus is required by a growing set of services
(logind, systemd-resolved shim, etc.).
- Ship /usr/lib/tmpfiles.d/sshd.conf creating /run/sshd. Debian's
openssh-server package doesn't ship one, and ssh.service's own
RuntimeDirectory=sshd fires too late for the ExecStartPre config
check, which blows up with 'Missing privilege separation directory'.
The tmpfiles entry runs in systemd-tmpfiles-setup.service well
before ssh.service starts.
- Rewrite the ssh.service drop-in to reset the main unit's
ExecStartPre list. Debian ships `sshd -t` as ExecStartPre #1; that
fails without host keys and terminates the service before our
`ssh-keygen -A` fires. Reset + re-add in the correct order: mkdir,
keygen, then the test.
StandardOutput/Error=journal+console on ssh.service so future sshd
failures surface in the firecracker console log too, not only in the
(unreachable) guest journal.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Debian bookworm with two clearly-labeled sections:
- ESSENTIAL: systemd, openssh-server, ca-certificates, curl, iproute2.
- OPINION: git, jq, ripgrep, fd, build-essential, shellcheck, mise,
Docker CE (+ Compose v2 + buildx), tmux, htop, and friends.
Per-VM identity stripped at build time: /etc/machine-id cleared,
SSH host keys removed with a ssh.service drop-in that runs
`ssh-keygen -A` on first start so each VM gets a unique set.
The script is a parameterized wrapper around `docker build`; it also
supports `--push` to an OCI registry, which will be removed once the
bundle pipeline is in place.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>