diff --git a/.github/workflows/builder.yaml b/.github/workflows/builder.yaml
new file mode 100644
index 0000000..1f73560
--- /dev/null
+++ b/.github/workflows/builder.yaml
@@ -0,0 +1,112 @@
+name: BerryOS Builder
+
+on:
+ workflow_call:
+ inputs:
+ build_arch:
+ type: string
+ required: true
+ default: armhf
+ os_version:
+ type: string
+ default: "nightly"
+ debian_release:
+ type: string
+ required: true
+ default: bookworm
+ workflow_dispatch:
+ inputs:
+ build_arch:
+ type: choice
+ description: "Target architecture"
+ required: true
+ default: armhf
+ options:
+ - armhf
+ - arm64
+ os_version:
+ type: string
+ description: "OS Version"
+ default: "nightly"
+ debian_release:
+ type: choice
+ description: "Base Debian release"
+ required: true
+ default: bookworm
+ options:
+ - bullseye
+ - bookworm
+
+defaults:
+ run:
+ shell: bash
+
+jobs:
+ rootfs:
+ runs-on: ubuntu-latest
+ container:
+ image: ghcr.io/0rax/berryos-builder
+ options: --privileged
+ credentials:
+ username: ${{ github.actor }}
+ password: ${{ secrets.github_token }}
+ env:
+ BUILD_DIR: ${{ github.workspace }}
+ OUTPUT_DIR: ${{ github.workspace }}/out
+ OS_VERSION: ${{ inputs.os_version }}
+ GIT_HASH: ${{ github.sha }}
+ DEBIAN_RELEASE: ${{ inputs.debian_release }}
+ BUILD_ARCH: ${{ inputs.build_arch }}
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ - name: Bootstrap rootfs
+ run: |
+ ./scripts/00-bootstrap.sh
+ - name: Upload rootfs
+ uses: actions/upload-artifact@v4
+ with:
+ name: berryos-${{ inputs.build_arch }}-rootfs
+ path: |
+ out/berryos-${{ inputs.build_arch }}-${{ inputs.debian_release }}-*-rootfs.tar.xz
+ out/berryos-${{ inputs.build_arch }}-${{ inputs.debian_release }}-*-packages.txt
+
+ image:
+ needs: rootfs
+ runs-on: ubuntu-latest
+ container:
+ image: ghcr.io/0rax/berryos-builder
+ options: --privileged
+ credentials:
+ username: ${{ github.actor }}
+ password: ${{ secrets.github_token }}
+ volumes:
+ - berryos-output:/tmp/berryos-output
+ env:
+ BUILD_DIR: ${{ github.workspace }}
+ OUTPUT_DIR: ${{ github.workspace }}/out
+ OS_VERSION: ${{ inputs.os_version }}
+ DEBIAN_RELEASE: ${{ inputs.debian_release }}
+ BUILD_ARCH: ${{ inputs.build_arch }}
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ - name: Download rootfs
+ uses: actions/download-artifact@v4
+ with:
+ name: berryos-${{ inputs.build_arch }}-rootfs
+ path: out/
+ - name: Export image
+ run: |
+ ./scripts/10-export.sh
+ - name: Generate checksum
+ run: |
+ sha256sum "out/berryos-${{ inputs.build_arch }}-${{ inputs.debian_release }}-${OS_VERSION//.}.img.xz" \
+ > "out/berryos-${{ inputs.build_arch }}-${{ inputs.debian_release }}-${OS_VERSION//.}.img.xz.sha256"
+ - name: Upload image
+ uses: actions/upload-artifact@v4
+ with:
+ name: berryos-${{ inputs.build_arch }}-image
+ path: |
+ out/berryos-${{ inputs.build_arch }}-${{ inputs.debian_release }}-*.img.xz
+ out/berryos-${{ inputs.build_arch }}-${{ inputs.debian_release }}-*.img.xz.sha256
diff --git a/.github/workflows/nightly.yaml b/.github/workflows/nightly.yaml
new file mode 100644
index 0000000..c7dee29
--- /dev/null
+++ b/.github/workflows/nightly.yaml
@@ -0,0 +1,75 @@
+name: Nightly Build
+
+on:
+ schedule:
+ - cron: '0 2 * * *'
+ workflow_dispatch:
+
+concurrency:
+ group: "bookworm-nightly"
+ cancel-in-progress: true
+
+jobs:
+ build:
+ strategy:
+ matrix:
+ build_arch: ["armhf", "arm64"]
+ uses: ./.github/workflows/builder.yaml
+ with:
+ os_version: nightly
+ debian_release: bookworm
+ build_arch: ${{ matrix.build_arch }}
+ release:
+ needs: build
+ runs-on: ubuntu-latest
+ steps:
+ - name: Download artifacts
+ uses: actions/download-artifact@v4
+ with:
+ path: out/
+ pattern: |
+ berryos-*-image
+ merge-multiple: true
+ - name: Update nightly release
+ uses: ncipollo/release-action@v1
+ with:
+ tag: bookworm-nightly
+ name: BerryOS Bookworm Nightly
+ prerelease: true
+ body: |
+ ## Nightly Builds
+
+ This is an automated nightly release. It includes daily built version of the BerryOS images.
+
+ ### Why use a nightly build?
+
+ Nightly builds allow you to make sure you are using an image that includes the latest version of all install packages. Making the initial setup of BerryOS faster.
+
+ It shouldn't be much different than using a stable release, but it might be a bit more unstable, especially during major updates (when BerryOS needs to be synced with the latest changes from Raspberry Pi OS).
+
+ ### Disclaimer
+
+ These builds are provided without any warranty. No manual testing or benchmarks have been performed.
+
+ If you prefer a stable release, please download the [latest stable release](https://github.com/0rax/BerryOS/releases/latest).
+
+ ## Compatibility
+
+ - `BerryOS/armhf`
+ - Image: [`berryos-armhf-bookworm-nightly.img.xz`](https://github.com/0rax/BerryOS/releases/download/bookworm-nightly/berryos-armhf-bookworm-nightly.img.xz)
+ - Compatibility: all Raspberry Pi models
+
+ - `BerryOS/arm64`
+ - Image [`berryos-arm64-bookworm-nightly.img.xz`](https://github.com/0rax/BerryOS/releases/download/bookworm-nightly/berryos-arm64-bookworm-nightly.img.xz)
+ - Compatibility:
+ - Raspberry Pi 3B, 3B+, 4 B & 400
+ - Compute Module 3, 3+ & 4
+ - Raspberry Pi Zero 2 W
+ - Raspberry Pi 5
+
+ ## Issues
+
+ If you find any issues when using a nightly build, please report them to the [issue tracker](https://github.com/0rax/BerryOS/issues). Make sure to include the content of `/etc/rpi-issue` in your report so we can pin-point the specific build you are using.
+ artifacts: "out/*"
+ allowUpdates: true
+ removeArtifacts: true
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
new file mode 100644
index 0000000..16f9faf
--- /dev/null
+++ b/.github/workflows/release.yaml
@@ -0,0 +1,58 @@
+name: Release
+
+on:
+ workflow_dispatch:
+ inputs:
+ os_version:
+ type: string
+ description: "OS Version"
+ default: "nightly"
+ debian_release:
+ type: choice
+ required: true
+ description: "Base Debian release"
+ default: bookworm
+ options:
+ - bullseye
+ - bookworm
+
+jobs:
+ build:
+ strategy:
+ matrix:
+ build_arch: ["armhf", "arm64"]
+ uses: ./.github/workflows/builder.yaml
+ with:
+ os_version: ${{ inputs.os_version }}
+ debian_release: ${{ inputs.debian_release }}
+ build_arch: ${{ matrix.build_arch }}
+ draft-release:
+ needs: build
+ runs-on: ubuntu-latest
+ steps:
+ - name: Download artifacts
+ uses: actions/download-artifact@v4
+ with:
+ path: out/
+ pattern: |
+ berryos-*-image
+ merge-multiple: true
+ - name: Generate environment
+ env:
+ OS_VERSION: ${{ inputs.os_version }}
+ DEBIAN_RELEASE: ${{ inputs.debian_release }}
+ run: |
+ echo "RELEASE_NAME=BerryOS ${DEBIAN_RELEASE^} ${OS_VERSION^}" >> "${GITHUB_ENV}"
+ echo "ARTIFACT_SUFFIX=${DEBIAN_RELEASE,,}-${OS_VERSION//.}" >> "${GITHUB_ENV}"
+ - name: Generate release-note
+ uses: ncipollo/release-action@v1
+ with:
+ tag: ${{ inputs.debian_release }}-${{ inputs.os_version }}
+ name: ${{ env.RELEASE_NAME }}
+ draft: true
+ generateReleaseNotes: true
+ artifacts: "out/*"
+ allowUpdates: false
+ skipIfReleaseExists: true
+ updateOnlyUnreleased: true
+ removeArtifacts: true
diff --git a/Makefile b/Makefile
index 7c63dbf..65feea1 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,6 @@ OS_NAME ?= BerryOS
OS_VERSION ?= $(shell date --utc "+%Y.%m.%d")
OS_REPO ?= https://github.com/0rax/BerryOS
GIT_HASH ?= $(shell git rev-parse HEAD)
-DEBIAN_VERSION ?= 12
DEBIAN_RELEASE ?= bookworm
.DEFAULT: armhf
@@ -17,23 +16,21 @@ builder:
armhf: builder
$(info [BerryOS] Build for armhf)
- docker compose run builder make rootfs image \
+ docker compose run builder make rootfs image checksums \
OS_NAME="$(OS_NAME)" \
OS_VERSION="$(OS_VERSION)" \
OS_REPO="$(OS_REPO)" \
GIT_HASH="$(GIT_HASH)" \
- DEBIAN_VERSION="$(DEBIAN_VERSION)" \
DEBIAN_RELEASE="$(DEBIAN_RELEASE)" \
BUILD_ARCH=armhf
arm64: builder
$(info [BerryOS] Build for arm64)
- docker compose run builder make rootfs image \
+ docker compose run builder make rootfs image checksums \
OS_NAME="$(OS_NAME)" \
OS_VERSION="$(OS_VERSION)" \
OS_REPO="$(OS_REPO)" \
GIT_HASH="$(GIT_HASH)" \
- DEBIAN_VERSION="$(DEBIAN_VERSION)" \
DEBIAN_RELEASE="$(DEBIAN_RELEASE)" \
BUILD_ARCH=arm64
@@ -48,7 +45,6 @@ rootfs:
OS_VERSION="$(OS_VERSION)" \
OS_REPO="$(OS_REPO)" \
GIT_HASH="$(GIT_HASH)" \
- DEBIAN_VERSION="$(DEBIAN_VERSION)" \
DEBIAN_RELEASE="$(DEBIAN_RELEASE)" \
BUILD_ARCH="$(BUILD_ARCH)" \
./scripts/00-bootstrap.sh
@@ -62,24 +58,14 @@ image:
BUILD_ARCH="$(BUILD_ARCH)" \
./scripts/10-export.sh
-.PHONY: rootfs image
-
-## Release rules
-
-release: armhf arm64 checksums
-
+checksums: BUILD_ARCH ?= armhf
checksums:
- $(info [BerryOS] Generate checksums)
+ $(info [BerryOS/$(BUILD_ARCH)] Generate checksums)
cd out/ \
&& sha256sum \
- berryos-arm64-$(DEBIAN_RELEASE)-$(subst .,,$(OS_VERSION))-rootfs.tar.xz \
- berryos-arm64-$(DEBIAN_RELEASE)-$(subst .,,$(OS_VERSION))-packages.txt \
- berryos-arm64-$(DEBIAN_RELEASE)-$(subst .,,$(OS_VERSION)).img.xz \
- > berryos-arm64-$(DEBIAN_RELEASE)-$(subst .,,$(OS_VERSION))-checksums.txt \
- && sha256sum \
- berryos-armhf-$(DEBIAN_RELEASE)-$(subst .,,$(OS_VERSION))-rootfs.tar.xz \
- berryos-armhf-$(DEBIAN_RELEASE)-$(subst .,,$(OS_VERSION))-packages.txt \
- berryos-armhf-$(DEBIAN_RELEASE)-$(subst .,,$(OS_VERSION)).img.xz \
- > berryos-armhf-$(DEBIAN_RELEASE)-$(subst .,,$(OS_VERSION))-checksums.txt
+ berryos-$(BUILD_ARCH)-$(DEBIAN_RELEASE)-$(subst .,,$(OS_VERSION))-rootfs.tar.xz \
+ berryos-$(BUILD_ARCH)-$(DEBIAN_RELEASE)-$(subst .,,$(OS_VERSION))-packages.txt \
+ berryos-$(BUILD_ARCH)-$(DEBIAN_RELEASE)-$(subst .,,$(OS_VERSION)).img.xz \
+ > berryos-$(BUILD_ARCH)-$(DEBIAN_RELEASE)-$(subst .,,$(OS_VERSION))-checksums.txt \
-.PHONY: release checksums
+.PHONY: rootfs image checksums
diff --git a/compose.yaml b/compose.yaml
index f17de6f..bb12271 100644
--- a/compose.yaml
+++ b/compose.yaml
@@ -1,8 +1,6 @@
-version: '3.8'
-
services:
builder:
- image: berryos-bootstraper
+ image: ghcr.io/0rax/berryos-builder
build:
context: .
dockerfile: Dockerfile
@@ -11,7 +9,7 @@ services:
working_dir: /opt/bootstrap
privileged: true
docs:
- image: berryos-jekyll
+ image: ghcr.io/0rax/berryos-jekyll
build:
context: .
dockerfile: Dockerfile.docs
diff --git a/docs/_config.yml b/docs/_config.yml
index 59f0975..bf0c04c 100644
--- a/docs/_config.yml
+++ b/docs/_config.yml
@@ -15,7 +15,7 @@ aux_links_new_tab: true
heading_anchors: true
back_to_top: true
back_to_top_text: "Back to top"
-footer_content: "Copyright © 2022 Jean-Philippe Roemer. Distributed under an ISC license."
+footer_content: "Copyright © 2025 JP \"0rax\" Roemer. Distributed under an ISC license."
gh_edit_link: true
gh_edit_link_text: "Edit this page on GitHub."
gh_edit_repository: "https://github.com/0rax/BerryOS"
diff --git a/scripts/00-bootstrap.sh b/scripts/00-bootstrap.sh
index 0c1744c..a37e90b 100755
--- a/scripts/00-bootstrap.sh
+++ b/scripts/00-bootstrap.sh
@@ -15,13 +15,27 @@ GIT_HASH="${GIT_HASH:-"main"}"
## Debian base
DEBIAN_VARIANT="Debian GNU/Linux"
-DEBIAN_VERSION="${DEBIAN_VERSION:-"12"}"
DEBIAN_RELEASE="${DEBIAN_RELEASE:-"bookworm"}"
+DEBIAN_VERSION=""
+case "${DEBIAN_RELEASE}" in
+ "bullseye")
+ DEBIAN_VERSION="11";;
+ "bookworm")
+ DEBIAN_VERSION="12";;
+ "trixie")
+ DEBIAN_VERSION="13";;
+ "forky")
+ DEBIAN_VERSION="14";;
+ "duke")
+ DEBIAN_VERSION="15";;
+esac
+
## Build path
+SCRIPT_DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")"
BUILD_DIR="${BUILD_DIR:-/opt/bootstrap}"
FILES_DIR="${BUILD_DIR}/rootfs"
-OUTPUT_DIR="${BUILD_DIR}/out"
+OUTPUT_DIR="${OUTPUT_DIR:-${BUILD_DIR}/out}"
ROOTFS_TAR="${OUTPUT_DIR}/${OS_NAME,,}-${BUILD_ARCH}-${DEBIAN_RELEASE}-${OS_VERSION//.}-rootfs.tar.xz"
ROOTFS_PKGS="${OUTPUT_DIR}/${OS_NAME,,}-${BUILD_ARCH}-${DEBIAN_RELEASE}-${OS_VERSION//.}-packages.txt"
@@ -124,7 +138,7 @@ configure_rootfs () {
DEBIAN_VARIANT="${DEBIAN_VARIANT}" \
DEBIAN_RELEASE="${DEBIAN_RELEASE}" \
DEBOOTSTRAP_URL="${DEBOOTSTRAP_URL}" \
- /bin/bash < "${BUILD_DIR}/scripts/01-chroot.sh"
+ /bin/bash < "${SCRIPT_DIR}/01-chroot.sh"
chroot "${ROOTFS_DIR}" dpkg --get-selections | awk '{ print $1 }' > "${ROOTFS_PKGS}"
# Copy static system configuration files
diff --git a/scripts/01-chroot.sh b/scripts/01-chroot.sh
index 1be1a0f..0086266 100755
--- a/scripts/01-chroot.sh
+++ b/scripts/01-chroot.sh
@@ -10,6 +10,7 @@ fi
OS_NAME="${OS_NAME?}"
OS_VERSION="${OS_VERSION?}"
BUILD_ARCH="${BUILD_ARCH:-$(dpkg --print-architecture)}"
+GIT_HASH="${GIT_HASH?}"
## Debian base
DEBIAN_VARIANT="${DEBIAN_VARIANT?}"
@@ -108,10 +109,12 @@ rm -f /etc/sudoers.d/010_pi-nopasswd
## Setup OS specifics
# Setup rpi-issue
-tee /etc/rpi-issue << EOF
-${OS_NAME} ${OS_VERSION}
-Generated using berryos-builder, ${OS_REPO}, ${GIT_HASH}, ${BUILD_ARCH}
-EOF
+if [ "${OS_VERSION}" = "nightly" ]; then
+ echo "${OS_NAME}/${BUILD_ARCH} ${DEBIAN_RELEASE^} ${OS_VERSION^} ($(date --utc "+%Y-%m-%d"))" | tee /etc/rpi-issue
+else
+ echo "${OS_NAME}/${BUILD_ARCH} ${DEBIAN_RELEASE^} ${OS_VERSION^}" | tee /etc/rpi-issue
+fi
+echo "Generated using berryos-builder, ${OS_REPO}, ${GIT_HASH}, ${BUILD_ARCH}" | tee -a /etc/rpi-issue
install -m 644 /etc/rpi-issue /boot/firmware/issue.txt
if ! [ -L /boot/issue.txt ]; then
@@ -122,7 +125,7 @@ fi
DEBIAN_ISSUE=$(cat /etc/issue.net)
tee /etc/motd << EOF
-${OS_NAME}/${BUILD_ARCH} ${OS_VERSION} (${DEBIAN_ISSUE})
+${OS_NAME}/${BUILD_ARCH} ${DEBIAN_RELEASE^} ${OS_VERSION^} (${DEBIAN_ISSUE})
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
diff --git a/scripts/10-export.sh b/scripts/10-export.sh
index a445d01..26205f4 100755
--- a/scripts/10-export.sh
+++ b/scripts/10-export.sh
@@ -14,7 +14,7 @@ DEBIAN_RELEASE="${DEBIAN_RELEASE:-"bookworm"}"
## Build path
BUILD_DIR="${BUILD_DIR:-/opt/bootstrap}"
-OUTPUT_DIR="${BUILD_DIR}/out"
+OUTPUT_DIR="${OUTPUT_DIR:-${BUILD_DIR}/out}"
ROOTFS_TAR="${OUTPUT_DIR}/${OS_NAME,,}-${BUILD_ARCH}-${DEBIAN_RELEASE}-${OS_VERSION//.}-rootfs.tar.xz"
IMAGE_PATH="${OUTPUT_DIR}/${OS_NAME,,}-${BUILD_ARCH}-${DEBIAN_RELEASE}-${OS_VERSION//.}.img"