diff --git a/.gitea/workflows/build-kernel.yml b/.gitea/workflows/build-kernel.yml index 8b4978b..7add102 100644 --- a/.gitea/workflows/build-kernel.yml +++ b/.gitea/workflows/build-kernel.yml @@ -27,8 +27,14 @@ jobs: # Don't cancel the other versions if one fails to build. fail-fast: false matrix: - kernel_version: - - "1:6.12.93-1+rpt1" + # Each raspberrypi archive suite only carries its own latest kernel, so + # the Debian base suite is paired with the kernel version it can install: + # bookworm -> 6.12.x, trixie -> 6.18.x. + include: + - kernel_version: "1:6.12.93-1+rpt1" + suite: bookworm + - kernel_version: "1:6.18.34-1+rpt1" + suite: trixie steps: - name: Checkout uses: actions/checkout@v4 @@ -38,6 +44,7 @@ jobs: env: HEADERS_PKG: ${{ env.HEADERS_PKG }} KERNEL_VERSION: ${{ matrix.kernel_version }} + DEBIAN_SUITE: ${{ matrix.suite }} run: | set -eux # arm64 emulation for the builder image (no-op if already registered). @@ -46,6 +53,7 @@ jobs: fi # Builder image: toolchain + matching raspberrypi kernel headers. docker build --platform linux/arm64 \ + --build-arg DEBIAN_SUITE="$DEBIAN_SUITE" \ --build-arg HEADERS_PKG="$HEADERS_PKG" \ --build-arg KERNEL_VERSION="$KERNEL_VERSION" \ -t iec-kbuild . diff --git a/docs/kernel-notes.md b/docs/kernel-notes.md index 7f324b7..fae5df7 100644 --- a/docs/kernel-notes.md +++ b/docs/kernel-notes.md @@ -168,14 +168,27 @@ Configurable via env vars (kernel version is configurable as requested): | Var | Default | Purpose | |-----|---------|---------| +| `SUITE` | `bookworm` | Debian/RPi OS suite; **must match the kernel** — `bookworm` ⇒ 6.12.x, `trixie` ⇒ 6.18.x | | `HEADERS_PKG` | `linux-headers-rpi-v8` | headers package; use `-v7`/`-v6` for 32-bit, or `raspberrypi-kernel-headers` | | `KERNEL_VERSION` | *(latest)* | exact version pin, e.g. `1:6.6.51-1+rpt3` | | `IMAGE` | `iec-kbuild` | builder image tag | ```bash -KERNEL_VERSION=1:6.6.51-1+rpt3 ./build-in-docker.sh +SUITE=trixie KERNEL_VERSION=1:6.18.34-1+rpt1 ./build-in-docker.sh ``` +**`SUITE` must match `KERNEL_VERSION`.** Each raspberrypi archive suite carries +only its own latest kernel, so a trixie-era version against a `bookworm` base +fails with `Version '…' was not found`. Find the Pi's suite with +`. /etc/os-release; echo "$VERSION_CODENAME"` (or `lsb_release -cs`). + +**trixie SHA1 caveat.** On trixie, apt verifies signatures with Sequoia (`sqv`), +whose crypto policy rejects SHA1 since 2026-02-01. The raspberrypi archive key's +binding self-signature is SHA1, so trixie's apt rejects the repo as *"not +signed"* (`Policy rejected … SHA1 is not considered secure …`). The Dockerfile +works around this by marking the raspberrypi repo `trusted=yes` **only when +`DEBIAN_SUITE=trixie`**; bookworm (gpgv) keeps full signature verification. + **Find the exact values for *your* Pi** — run this on the Pi (e.g. over SSH); it prints the two lines ready to copy into the `build-in-docker.sh` invocation: @@ -183,19 +196,21 @@ prints the two lines ready to copy into the `build-in-docker.sh` invocation: pkg="linux-headers-$(uname -r | sed 's/.*+rpt-//')"; echo "HEADERS_PKG=$pkg KERNEL_VERSION=$(dpkg-query -W -f='${Version}' "$pkg")" ``` -On the project's Pi Zero 2 W (`chris@10.1.0.41`, kernel `6.12.93+rpt-rpi-v8`) -this currently prints: +On the Pi at `chris@10.1.0.41` (a Pi 3B+, kernel `6.12.93+rpt-rpi-v8`; same +arm64/`-v8` headers as the Zero 2 W) this currently prints: ```bash HEADERS_PKG=linux-headers-rpi-v8 KERNEL_VERSION=1:6.12.93-1+rpt1 ``` -**vermagic caveat:** the raspberrypi apt archive normally serves only the -*latest* kernel in its pool, so pinning `KERNEL_VERSION` to an old release may -not be downloadable. The reliable strategy is to keep the Pi current -(`sudo apt full-upgrade`) and build with the default (latest) — then the Pi and -the container agree. If you must target an older/specific kernel, copy the Pi's -`/lib/modules/$(uname -r)/build` tree into the container instead of using apt. +**vermagic caveat:** each raspberrypi apt archive **suite** normally serves only +the *latest* kernel in its pool (`bookworm` ⇒ 6.12.x, `trixie` ⇒ 6.18.x), so the +container's `SUITE` must match the Pi's release, and pinning `KERNEL_VERSION` to +an old release within a suite may not be downloadable. The reliable strategy is +to keep the Pi current (`sudo apt full-upgrade`) and build with the matching +`SUITE` + default (latest) version — then the Pi and the container agree. If you +must target an older/specific kernel, copy the Pi's `/lib/modules/$(uname +-r)/build` tree into the container instead of using apt. `uname -r` is **not** used inside the container (it reports the host kernel under emulation); the entrypoint derives `KDIR` from the installed headers under diff --git a/kernel/Dockerfile b/kernel/Dockerfile index 7531691..b8b592e 100644 --- a/kernel/Dockerfile +++ b/kernel/Dockerfile @@ -9,18 +9,38 @@ # docker run --privileged --rm tonistiigi/binfmt --install arm64 # # Kernel version is configurable via build args: +# --build-arg DEBIAN_SUITE=trixie # Debian/RPi OS suite (see notes) # --build-arg HEADERS_PKG=linux-headers-rpi-v8 # 64-bit Pi Zero 2 W (default) # --build-arg KERNEL_VERSION=1:6.6.51-1+rpt3 # optional exact pin (see notes) # +# DEBIAN_SUITE must match the kernel you target: each raspberrypi archive suite +# only carries its own latest kernel (bookworm -> 6.12.x, trixie -> 6.18.x), so +# pinning a trixie-era KERNEL_VERSION against a bookworm base will fail with +# "Version ... was not found". Keep this in sync with the Pi's release. +# # Build context is this kernel/ directory. -FROM --platform=linux/arm64 debian:bookworm +ARG DEBIAN_SUITE=bookworm +FROM --platform=linux/arm64 debian:${DEBIAN_SUITE} + +# Re-declare after FROM so it is in scope for the RUN below (ARGs before FROM +# are only visible to the FROM line itself). +ARG DEBIAN_SUITE=bookworm # The raspberrypi kernel/headers live in the raspberrypi.com archive, not Debian. +# +# On trixie, apt verifies signatures with Sequoia (sqv), whose crypto policy +# rejects SHA1 since 2026-02-01. The raspberrypi archive key's binding +# self-signature is SHA1, so trixie's apt refuses the repo as "not signed" +# (bookworm's gpgv doesn't enforce this). We mark the repo trusted=yes *only on +# trixie* to bypass that check; bookworm keeps full signature verification. The +# key is still fetched over HTTPS and pinned via signed-by where it is honoured. RUN apt-get update \ && apt-get install -y --no-install-recommends ca-certificates curl gnupg \ && curl -fsSL https://archive.raspberrypi.com/debian/raspberrypi.gpg.key \ | gpg --dearmor -o /usr/share/keyrings/raspberrypi-archive-keyring.gpg \ - && echo "deb [signed-by=/usr/share/keyrings/raspberrypi-archive-keyring.gpg] http://archive.raspberrypi.com/debian/ bookworm main" \ + && opts="signed-by=/usr/share/keyrings/raspberrypi-archive-keyring.gpg" \ + && if [ "$DEBIAN_SUITE" = "trixie" ]; then opts="$opts trusted=yes"; fi \ + && echo "deb [$opts] http://archive.raspberrypi.com/debian/ ${DEBIAN_SUITE} main" \ > /etc/apt/sources.list.d/raspi.list \ && rm -rf /var/lib/apt/lists/* diff --git a/kernel/build-in-docker.sh b/kernel/build-in-docker.sh index a905d3d..30c8966 100755 --- a/kernel/build-in-docker.sh +++ b/kernel/build-in-docker.sh @@ -9,19 +9,22 @@ # ./build-in-docker.sh clean # clean build artifacts # # Configurable via environment variables: +# SUITE Debian/RPi OS suite (default: bookworm; use trixie for 6.18.x) # HEADERS_PKG headers package (default: linux-headers-rpi-v8, 64-bit Zero 2 W) # e.g. linux-headers-rpi-v7 / -v6 for 32-bit, raspberrypi-kernel-headers # KERNEL_VERSION exact version to pin, e.g. 1:6.6.51-1+rpt3 (default: latest in repo) # IMAGE builder image tag (default: iec-kbuild) # -# NOTE: the raspberrypi apt archive generally serves only the *latest* kernel in -# its pool, so pinning KERNEL_VERSION to an old release may fail to download. The +# NOTE: each raspberrypi apt archive suite serves only the *latest* kernel in its +# pool (bookworm -> 6.12.x, trixie -> 6.18.x), so SUITE must match the kernel you +# target and pinning KERNEL_VERSION to an old release may fail to download. The # reliable match strategy is to keep the Pi current (`sudo apt full-upgrade`) and -# build with the default (latest). See docs/kernel-notes.md. +# build with the matching SUITE + default (latest) version. See docs/kernel-notes.md. set -euo pipefail cd "$(dirname "$0")" IMAGE="${IMAGE:-iec-kbuild}" +SUITE="${SUITE:-bookworm}" HEADERS_PKG="${HEADERS_PKG:-linux-headers-rpi-v8}" KERNEL_VERSION="${KERNEL_VERSION:-}" @@ -32,8 +35,9 @@ if [ ! -e /proc/sys/fs/binfmt_misc/qemu-aarch64 ]; then fi # 2. Build the builder image (installs toolchain + matching kernel headers). -echo "==> building image '$IMAGE' (HEADERS_PKG=$HEADERS_PKG KERNEL_VERSION=${KERNEL_VERSION:-latest})" +echo "==> building image '$IMAGE' (SUITE=$SUITE HEADERS_PKG=$HEADERS_PKG KERNEL_VERSION=${KERNEL_VERSION:-latest})" docker build --platform linux/arm64 \ + --build-arg DEBIAN_SUITE="$SUITE" \ --build-arg HEADERS_PKG="$HEADERS_PKG" \ --build-arg KERNEL_VERSION="$KERNEL_VERSION" \ -t "$IMAGE" .