Build both RPi 5 and RPi 4/CM4 from single tag

- Make TALOS_VERSION overridable (?=) and extract from git tag
- Workflow builds Pi5 then Pi4 (clean re-checkout for different kernel config)
- Separate installer images: <tag>-rpi5 and <tag>-rpi4
- Separate metal images: metal-arm64-rpi5.raw.zst and metal-arm64-rpi4.raw.zst
- Release includes both platforms with updated notes
- README updated for dual-platform support
This commit is contained in:
Stephen Wheet
2026-03-10 21:20:47 -07:00
parent 3319e2db58
commit c62a8373a2
3 changed files with 149 additions and 62 deletions
+111 -44
View File
@@ -4,7 +4,6 @@ on:
- 'v*.*.*'
env:
RPI_MODEL: rpi5
REGISTRY: ghcr.io
REGISTRY_USERNAME: ${{ github.repository_owner }}
# Extensions to bake into the installer image.
@@ -36,6 +35,16 @@ jobs:
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
- name: Extract Talos version from tag
id: talos-version
run: |
# Tag format: v1.11.6-rpi5, v1.11.5-cm5, etc.
# Extract the upstream Talos version (vMAJOR.MINOR.PATCH) from the tag.
TAG="${{ github.ref_name }}"
TALOS_VERSION=$(echo "$TAG" | grep -oE '^v[0-9]+\.[0-9]+\.[0-9]+')
echo "TALOS_VERSION=${TALOS_VERSION}" >> $GITHUB_ENV
echo "Resolved TALOS_VERSION=${TALOS_VERSION} from tag ${TAG}"
- name: Resolve extension image digests
run: |
EXTENSIONS=""
@@ -46,84 +55,142 @@ jobs:
done < <(env | grep '^EXTENSION_')
echo "EXTENSIONS=${EXTENSIONS# }" >> $GITHUB_ENV
- name: Prepare (checkouts & patches)
run: make RPI_MODEL=${{ env.RPI_MODEL }} checkouts patches-pi5
# ──────────────────────────────────────────────
# Raspberry Pi 5
# ──────────────────────────────────────────────
- name: Kernel
run: make RPI_MODEL=${{ env.RPI_MODEL }} REGISTRY=${{ env.REGISTRY }} REGISTRY_USERNAME=${{ env.REGISTRY_USERNAME }} kernel
- name: "Pi5 — Prepare (checkouts & patches)"
run: make TALOS_VERSION=${{ env.TALOS_VERSION }} checkouts patches-pi5
- name: Kernel initramfs
run: make RPI_MODEL=${{ env.RPI_MODEL }} REGISTRY=${{ env.REGISTRY }} REGISTRY_USERNAME=${{ env.REGISTRY_USERNAME }} kern_initramfs
- name: "Pi5 — Kernel"
run: make TALOS_VERSION=${{ env.TALOS_VERSION }} REGISTRY=${{ env.REGISTRY }} REGISTRY_USERNAME=${{ env.REGISTRY_USERNAME }} kernel
- name: Installer base
run: make RPI_MODEL=${{ env.RPI_MODEL }} REGISTRY=${{ env.REGISTRY }} REGISTRY_USERNAME=${{ env.REGISTRY_USERNAME }} installer-base
- name: "Pi5 — Kernel initramfs"
run: make TALOS_VERSION=${{ env.TALOS_VERSION }} REGISTRY=${{ env.REGISTRY }} REGISTRY_USERNAME=${{ env.REGISTRY_USERNAME }} kern_initramfs
- name: Imager
run: make RPI_MODEL=${{ env.RPI_MODEL }} REGISTRY=${{ env.REGISTRY }} REGISTRY_USERNAME=${{ env.REGISTRY_USERNAME }} imager
- name: "Pi5 — Installer base"
run: make TALOS_VERSION=${{ env.TALOS_VERSION }} REGISTRY=${{ env.REGISTRY }} REGISTRY_USERNAME=${{ env.REGISTRY_USERNAME }} installer-base
- name: Overlay
run: make RPI_MODEL=${{ env.RPI_MODEL }} REGISTRY=${{ env.REGISTRY }} REGISTRY_USERNAME=${{ env.REGISTRY_USERNAME }} overlay
- name: "Pi5 — Imager"
run: make TALOS_VERSION=${{ env.TALOS_VERSION }} REGISTRY=${{ env.REGISTRY }} REGISTRY_USERNAME=${{ env.REGISTRY_USERNAME }} imager
- name: Build installer image (with extensions)
- name: "Pi5 — Overlay"
run: make TALOS_VERSION=${{ env.TALOS_VERSION }} REGISTRY=${{ env.REGISTRY }} REGISTRY_USERNAME=${{ env.REGISTRY_USERNAME }} overlay
- name: "Pi5 — Build installer image (with extensions)"
run: |
make RPI_MODEL=${{ env.RPI_MODEL }} \
make TALOS_VERSION=${{ env.TALOS_VERSION }} \
REGISTRY=${{ env.REGISTRY }} \
REGISTRY_USERNAME=${{ env.REGISTRY_USERNAME }} \
ASSET_TYPE=installer \
EXTENSIONS="${{ env.EXTENSIONS }}" \
installer-pi5
# Push the installer OCI tarball so it can be used for upgrades
crane push \
./checkouts/talos/_out/installer-arm64.tar \
${{ env.REGISTRY }}/${{ env.REGISTRY_USERNAME }}/installer:$(cd checkouts/talos && git describe --tag --always --dirty --match v[0-9]*)
${{ env.REGISTRY }}/${{ env.REGISTRY_USERNAME }}/installer:${{ github.ref_name }}-rpi5
- name: Build metal disk image (for fresh installs)
- name: "Pi5 — Build metal disk image"
run: |
make RPI_MODEL=${{ env.RPI_MODEL }} \
make TALOS_VERSION=${{ env.TALOS_VERSION }} \
REGISTRY=${{ env.REGISTRY }} \
REGISTRY_USERNAME=${{ env.REGISTRY_USERNAME }} \
ASSET_TYPE=metal \
EXTENSIONS="${{ env.EXTENSIONS }}" \
installer-pi5
mv ./checkouts/talos/_out/metal-arm64.raw.zst ./metal-arm64-rpi5.raw.zst
- name: Release (tag installer image with git tag)
if: startsWith(github.ref, 'refs/tags/v')
run: make RPI_MODEL=${{ env.RPI_MODEL }} REGISTRY=${{ env.REGISTRY }} REGISTRY_USERNAME=${{ env.REGISTRY_USERNAME }} release
# ──────────────────────────────────────────────
# Raspberry Pi 4 / CM4
# ──────────────────────────────────────────────
- name: "Pi4 — Prepare (clean, re-checkout & patches)"
run: make TALOS_VERSION=${{ env.TALOS_VERSION }} checkouts-clean checkouts patches-pi4
- name: "Pi4 — Kernel"
run: make TALOS_VERSION=${{ env.TALOS_VERSION }} REGISTRY=${{ env.REGISTRY }} REGISTRY_USERNAME=${{ env.REGISTRY_USERNAME }} kernel
- name: "Pi4 — Kernel initramfs"
run: make TALOS_VERSION=${{ env.TALOS_VERSION }} REGISTRY=${{ env.REGISTRY }} REGISTRY_USERNAME=${{ env.REGISTRY_USERNAME }} kern_initramfs
- name: "Pi4 — Installer base"
run: make TALOS_VERSION=${{ env.TALOS_VERSION }} REGISTRY=${{ env.REGISTRY }} REGISTRY_USERNAME=${{ env.REGISTRY_USERNAME }} installer-base
- name: "Pi4 — Imager"
run: make TALOS_VERSION=${{ env.TALOS_VERSION }} REGISTRY=${{ env.REGISTRY }} REGISTRY_USERNAME=${{ env.REGISTRY_USERNAME }} imager
- name: "Pi4 — Build installer image (with extensions)"
run: |
make TALOS_VERSION=${{ env.TALOS_VERSION }} \
REGISTRY=${{ env.REGISTRY }} \
REGISTRY_USERNAME=${{ env.REGISTRY_USERNAME }} \
ASSET_TYPE=installer \
EXTENSIONS="${{ env.EXTENSIONS }}" \
installer-pi4
crane push \
./checkouts/talos/_out/installer-arm64.tar \
${{ env.REGISTRY }}/${{ env.REGISTRY_USERNAME }}/installer:${{ github.ref_name }}-rpi4
- name: "Pi4 — Build metal disk image"
run: |
make TALOS_VERSION=${{ env.TALOS_VERSION }} \
REGISTRY=${{ env.REGISTRY }} \
REGISTRY_USERNAME=${{ env.REGISTRY_USERNAME }} \
ASSET_TYPE=metal \
EXTENSIONS="${{ env.EXTENSIONS }}" \
installer-pi4
mv ./checkouts/talos/_out/metal-arm64.raw.zst ./metal-arm64-rpi4.raw.zst
# ──────────────────────────────────────────────
# Release
# ──────────────────────────────────────────────
- name: Create GitHub Release
if: startsWith(github.ref, 'refs/tags/v')
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
INSTALLER_PI5="${{ env.REGISTRY }}/${{ env.REGISTRY_USERNAME }}/installer:${{ github.ref_name }}-rpi5"
INSTALLER_PI4="${{ env.REGISTRY }}/${{ env.REGISTRY_USERNAME }}/installer:${{ github.ref_name }}-rpi4"
NOTES=$(cat <<EOF
> ⚠️ Experimental build, use at your own risk.
This is a patched version of Talos tailored for the Raspberry Pi 5, including NVMe, NIC and USB support.
Patched Talos Linux for **Raspberry Pi 5** and **Raspberry Pi 4 / CM4**, including NVMe, NIC and USB support.
### Extensions included
- \`iscsi-tools\` ${{ env.EXTENSION_ISCSI_IMAGE }}
- \`util-linux-tools\` ${{ env.EXTENSION_UTIL_LINUX_IMAGE }}
### What's available
- 📦 **Raw disk image** (\`metal-arm64.raw.zst\`) for fresh installs
- ⚙️ **Installer image** (\`${{ env.REGISTRY }}/${{ env.REGISTRY_USERNAME }}/installer:${{ github.ref_name }}\`) for upgrades
### Install
- **Fresh install**
- Download the raw disk image from this release
- Flash with \`dd\` or your favorite tool
- **Upgrade existing node**
\`\`\`bash
talosctl upgrade --nodes <NODE_IP> --image ${{ env.REGISTRY }}/${{ env.REGISTRY_USERNAME }}/installer:${{ github.ref_name }}
\`\`\`
### Artifacts
| Platform | Disk image | Installer image |
|----------|-----------|----------------|
| **RPi 5 / CM5** | \`metal-arm64-rpi5.raw.zst\` | \`${INSTALLER_PI5}\` |
| **RPi 4 / CM4** | \`metal-arm64-rpi4.raw.zst\` | \`${INSTALLER_PI4}\` |
### Fresh install
Download the disk image for your board and flash it:
\`\`\`bash
unzstd metal-arm64-rpi5.raw.zst # or metal-arm64-rpi4.raw.zst
dd if=metal-arm64-rpi5.raw of=<disk> bs=4M status=progress
\`\`\`
### Upgrade
\`\`\`bash
# Raspberry Pi 5
talosctl upgrade --nodes <NODE_IP> --image ${INSTALLER_PI5}
# Raspberry Pi 4 / CM4
talosctl upgrade --nodes <NODE_IP> --image ${INSTALLER_PI4}
\`\`\`
EOF
)
gh release create \
${{ github.ref_name }} \
./checkouts/talos/_out/metal-arm64.raw.zst \
metal-arm64-rpi5.raw.zst \
metal-arm64-rpi4.raw.zst \
--title "${{ github.ref_name }}" \
--notes "$NOTES"
+1 -1
View File
@@ -1,5 +1,5 @@
PKG_VERSION = v1.11.0
TALOS_VERSION = v1.11.5
TALOS_VERSION ?= v1.11.5
SBCOVERLAY_VERSION = main
PUSH ?= true
+37 -17
View File
@@ -1,6 +1,6 @@
# Raspberry Pi 5 Talos Builder
# Raspberry Pi 5 & Pi 4 Talos Builder
This repository serves as the glue to build custom Talos images for the Raspberry Pi 5. It patches the Kernel and Talos build process to use the Linux Kernel source provided by [raspberrypi/linux](https://github.com/raspberrypi/linux).
This repository builds custom Talos Linux images for the **Raspberry Pi 5** and **Raspberry Pi 4 / CM4**. It patches the Kernel and Talos build process to use the Linux Kernel source provided by [raspberrypi/linux](https://github.com/raspberrypi/linux).
## Tested on
@@ -18,24 +18,34 @@ So far, this release has been verified on:
## How to use?
The releases on this repository align with the corresponding Talos version. There is a raw disk image (initial setup) and an installer image (upgrades) provided.
Each release contains disk images and installer images for both Raspberry Pi 5 and Raspberry Pi 4 / CM4 platforms.
### Examples
Initial:
```bash
unzstd metal-arm64-rpi.raw.zst
dd if=metal-arm64-rpi.raw of=<disk> bs=4M status=progress
sync
# Raspberry Pi 5 / CM5
unzstd metal-arm64-rpi5.raw.zst
dd if=metal-arm64-rpi5.raw of=<disk> bs=4M status=progress
# Raspberry Pi 4 / CM4
unzstd metal-arm64-rpi4.raw.zst
dd if=metal-arm64-rpi4.raw of=<disk> bs=4M status=progress
```
Upgrade:
```bash
# Raspberry Pi 5 / CM5
talosctl upgrade \
--nodes <node IP> \
--image ghcr.io/talos-rpi5/installer:<version>
--image ghcr.io/talos-rpi5/installer:<version>-rpi5
# Raspberry Pi 4 / CM4
talosctl upgrade \
--nodes <node IP> \
--image ghcr.io/talos-rpi5/installer:<version>-rpi4
```
## Building
@@ -44,28 +54,38 @@ talosctl upgrade \
The CI workflow builds and publishes images automatically. It is triggered when you push a version tag:
- **Push a tag** matching `v*.*.*` — this triggers the full build and creates a GitHub Release:
- **Push a tag** matching `v*.*.*` — this builds both Raspberry Pi 5 and Pi 4 / CM4 images and creates a GitHub Release:
```bash
git tag v1.11.5-cm5
git push origin v1.11.5-cm5
git tag v1.11.6
git push origin v1.11.6
```
### Local build
If you'd like to make modifications, it is possible to create your own build. Bellow is an example of the standard build.
If you'd like to make modifications, it is possible to create your own build.
```bash
# Clones all dependencies and applies the necessary patches
make checkouts patches
# Full pipeline for Raspberry Pi 5
make REGISTRY=ghcr.io REGISTRY_USERNAME=<username> pi5
# Builds the Linux Kernel (can take a while)
# Full pipeline for Raspberry Pi 4 / CM4
make REGISTRY=ghcr.io REGISTRY_USERNAME=<username> pi4
```
Or step by step:
```bash
# Clone dependencies and apply patches
make checkouts patches-pi5 # or patches-pi4
# Build the Linux Kernel (can take a while)
make REGISTRY=ghcr.io REGISTRY_USERNAME=<username> kernel
# Builds the overlay (U-Boot, dtoverlays ...)
# Build the overlay (Pi5 only — Pi4 uses the stock siderolabs overlay)
make REGISTRY=ghcr.io REGISTRY_USERNAME=<username> overlay
# Final step to build the installer and disk image
make REGISTRY=ghcr.io REGISTRY_USERNAME=<username> installer
# Build the installer and disk image
make REGISTRY=ghcr.io REGISTRY_USERNAME=<username> installer-pi5 # or installer-pi4
```
### Extensions support