68 Commits

Author SHA1 Message Date
cce226198c Push changes from server for re-install 2026-05-26 07:22:49 -07:00
3769527869 Add flatpaks 2026-04-11 05:29:20 -07:00
3605a5d6d9 fix package names 2026-04-03 16:29:35 -07:00
e192680586 defaults i forgot 2026-04-03 02:30:22 -07:00
e623db2e4b Fixes 2026-04-03 02:26:38 -07:00
235a12a5ed Improve build system, use configs for more control 2026-03-29 20:33:58 -07:00
53ffdefe2e Improve squashfs 2026-03-29 19:42:14 -07:00
49d398fd6a Theme changes 2026-03-29 16:39:57 -07:00
8a573b2607 fix typo in TZ 2026-03-29 03:33:34 -07:00
b804679127 Stable base? 2026-03-29 03:29:03 -07:00
4e163d64be Remove ISO export, improve file names, update packages 2026-03-28 21:41:34 -07:00
01f7143e9d Fix build errors, and update livefs 2026-03-28 16:04:01 -07:00
c2676fb3a2 Improve OS 2026-03-28 00:40:34 -07:00
9b556d2151 Stable base 2026-03-12 12:21:07 -07:00
d4ad00d796 New basegit status! 2026-03-12 06:20:21 -07:00
135c13cada new base? 2026-03-10 06:30:47 -07:00
4017f4c727 arm64 (rpi) changes 2026-03-07 05:56:42 -08:00
7ac792cb05 Fix oopsies 2026-03-07 05:13:07 -08:00
2f51d3d82a cleanup 2026-03-07 04:48:53 -08:00
a7e6e0178d quick change 2026-03-07 04:19:01 -08:00
370c0f435a Seperate arm specific for rpi specefic stuff too. 2026-03-07 04:18:14 -08:00
74e2382e56 Fix raspbian sources 2026-03-07 04:06:46 -08:00
2d698e6643 Forgot to install the pgp file to rootfs 2026-03-07 02:46:29 -08:00
247d318f0f Add missing key 2026-03-07 02:04:13 -08:00
e726efa2a1 Fix raspian sources 2026-03-07 01:53:36 -08:00
5da74d42ea broke arm64 builds somehow? 2026-03-07 01:05:29 -08:00
ca0b8ab84f Update license 2026-03-07 00:07:15 -08:00
011b11a163 fix iso export? 2026-03-06 21:37:49 -08:00
99e6532afe fixes 2026-03-06 15:00:46 -08:00
dc8792f39f remove xcompmgr 2026-03-06 14:45:42 -08:00
50d7468379 Remove Xorg in favor of Wayland 2026-03-06 14:42:42 -08:00
5ddf03bfbb Remove gnome-initial-setup from liveboot 2026-03-06 14:29:01 -08:00
d6c501b94c iso stuff 2026-03-06 13:41:35 -08:00
9e64b989da fix perms 2026-03-06 13:40:04 -08:00
96294e9f10 fix ISO? 2026-03-06 13:26:05 -08:00
d0139cfb68 Change liveboot 2026-03-05 14:02:15 -08:00
ae50844db4 Fix exec perms 2026-03-05 13:44:52 -08:00
2b923dedf4 Remove obsolete packages 2026-03-05 13:33:29 -08:00
67d766af84 Update apt url 2026-03-05 13:08:05 -08:00
0666b4d8ce Restructure 2026-03-05 08:32:01 -08:00
eeab7c0066 Main base maybe? 2026-03-05 08:16:21 -08:00
6ff686f46a export squashfs instead of ISO for now 2026-03-05 06:25:58 -08:00
4fac4173d8 change arg 2026-03-05 05:58:32 -08:00
3a2392dbe0 Maybe? 2026-03-05 05:56:14 -08:00
dfbeff3a8f IDFK 2026-03-05 05:47:27 -08:00
ba03830786 Fix deps 2026-03-05 05:36:12 -08:00
5dd1df81e2 ISO shit 2026-03-05 05:34:27 -08:00
9171b33eb2 Fix exec 2026-03-05 05:08:49 -08:00
d2d9121392 Confused... 2026-03-05 05:04:08 -08:00
b93580ba3b Working on it... 2026-03-05 04:55:55 -08:00
aa82b77d91 You know, the kernel is kinda important 2026-03-05 04:39:54 -08:00
ee1ff065d7 Closer: Part 2 2026-03-05 04:33:50 -08:00
cfe6f5a670 fixes 2026-03-05 04:05:52 -08:00
239f5e37df Immutable/snapshot system? 2026-03-05 03:50:33 -08:00
aaf0466521 fix packages 2026-03-05 03:35:56 -08:00
34d6df8eb9 Closer 2026-03-05 03:25:05 -08:00
194d65db6b ISO Base? 2026-03-05 03:20:02 -08:00
810b9743f6 Almost 2026-03-05 03:13:45 -08:00
692d3fbad9 forgot rpi stuff 2026-03-05 03:06:23 -08:00
618e154632 i hate ifs 2026-03-05 03:03:51 -08:00
7f75c718b4 Fix: 2 2026-03-05 02:59:37 -08:00
2db3002313 Package fix #2 2026-03-05 02:49:08 -08:00
4916473dc9 Fix packages for amd64 build 2026-03-05 02:45:34 -08:00
1f6e023eab Add default debian sources for amd64 builds 2026-03-05 02:42:15 -08:00
7d499ebb72 It's been a hot minute ok.. 2026-03-05 02:35:28 -08:00
86538fe574 Fixes 2026-03-05 02:27:49 -08:00
104e7bd4cc Test 2026-03-05 02:16:50 -08:00
oxmc
07b8db1a74 Trixie base 2025-12-26 02:48:07 -08:00
147 changed files with 1422 additions and 1097 deletions

View File

@@ -6,7 +6,7 @@ ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get -y update && \
apt-get -y install --no-install-recommends \
git vim parted \
quilt coreutils qemu-user-static debootstrap zerofree zip dosfstools \
quilt coreutils qemu-user-static debootstrap zerofree zip dosfstools e2fsprogs \
libarchive-tools libcap2-bin rsync grep udev xz-utils curl xxd file kmod bc \
binfmt-support ca-certificates fdisk gpg pigz arch-test \
&& rm -rf /var/lib/apt/lists/*

View File

@@ -1,3 +1,4 @@
Copyright (c) 2026 Seth Olivarez
Copyright (c) 2015 Raspberry Pi (Trading) Ltd.
All rights reserved.

View File

@@ -1,37 +1,33 @@
# ChillcraftOS Build System
# VesperOS Build System
ChillcraftOS is a custom Raspberry Pi OS built using a system based on `pi-gen`. This build system is specifically designed to create **ChillcraftOS** images, not general Raspberry Pi OS images.
**Important Notes:**
- The 32-bit versions of ChillcraftOS are based on Raspbian.
- The 64-bit versions of ChillcraftOS are based on Debian.
VesperOS is a custom Debian-based OS built using a system based on `pi-gen`.
## Dependencies
The ChillcraftOS Build System relies on `pi-gen` and is compatible with Debian-based operating systems released after 2017. We recommend using the latest OS versions for better security.
The VesperOS Build System relies on `pi-gen` and is compatible with Debian-based operating systems released after 2017. We recommend using the latest OS versions for better security.
For other Linux distributions, you can use the Docker-based build method provided below.
To install the required dependencies for building ChillcraftOS, run the following command:
To install the required dependencies for building VesperOS, run the following command:
```bash
apt-get install coreutils quilt parted qemu-user-static debootstrap zerofree zip \
dosfstools libarchive-tools libcap2-bin grep rsync xz-utils file git curl bc \
gpg pigz xxd arch-test
apt install coreutils quilt parted qemu-user-static debootstrap zerofree zip \
dosfstools e2fsprogs libarchive-tools libcap2-bin grep rsync xz-utils file git curl bc \
gpg pigz xxd arch-test bmap-tools kmod squashfs-tools xorriso mtools
```
The `depends` file in the repository lists all the necessary tools, formatted as `<tool>[:<debian-package>]`.
## Getting Started with Building ChillcraftOS
## Getting Started with Building VesperOS
To start building ChillcraftOS, clone the ChillcraftOS Build System repository:
To start building VesperOS, clone the os-builder repository:
```bash
git clone https://git.oxmc.me/Chillcraft/ChillcraftOS.git
git clone https://git.oxmc.me/VesperOS/os-builder.git
```
For a shallow clone containing only the latest revision, you can add `--depth 1`. **However, avoid using this on your development machine**.
Make sure the repository is cloned to a directory **without spaces**, as spaces in the base path may cause `pi-gen` to fail.
Once cloned, you're ready to configure and start building ChillcraftOS.
Once cloned, you're ready to configure and start building VesperOS.

View File

@@ -85,10 +85,10 @@ BUILD_OPTS="$(echo "${BUILD_OPTS:-}" | sed -E 's@\-c\s?([^ ]+)@-c /config@')"
# Check the arch of the machine we're running on. If it's 64-bit, use a 32-bit base image instead
case "$(uname -m)" in
x86_64|aarch64)
BASE_IMAGE=i386/debian:bookworm
BASE_IMAGE=i386/debian:trixie
;;
*)
BASE_IMAGE=debian:bookworm
BASE_IMAGE=debian:trixie
;;
esac
${DOCKER} build --build-arg BASE_IMAGE=${BASE_IMAGE} -t pi-gen "${DIR}"
@@ -151,7 +151,7 @@ time ${DOCKER} run \
pi-gen \
bash -e -o pipefail -c "
dpkg-reconfigure qemu-user-static &&
# binfmt_misc is sometimes not mounted with debian bookworm image
# binfmt_misc is sometimes not mounted with debian trixie image
(mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc || true) &&
cd /pi-gen; ./build.sh ${BUILD_OPTS} &&
rsync -av work/*/build.log deploy/

103
build.sh
View File

@@ -5,7 +5,7 @@ run_sub_stage() {
log "Begin ${SUB_STAGE_DIR}"
pushd "${SUB_STAGE_DIR}" >/dev/null
for i in {00..99}; do
for DEBCONF_FILE in "${i}-debconf-${ARCH}" "${i}-debconf-arm-only" "${i}-debconf"; do
for DEBCONF_FILE in "${i}-debconf-${ARCH}" "${i}-debconf-${PLATFORM}-only" "${i}-debconf-arm-only" "${i}-debconf"; do
if [ -f "${SUB_STAGE_DIR}/${DEBCONF_FILE}" ]; then
# Skip arm-only if not arm
if [[ "${DEBCONF_FILE}" == *"-debconf-arm-only" ]] && [[ "${ARCH}" != "armhf" && "${ARCH}" != "arm64" ]]; then
@@ -23,7 +23,7 @@ EOF
log "End ${SUB_STAGE_DIR}/${DEBCONF_FILE}"
fi
done
for PACKAGE_LIST in "${i}-packages-nr-${ARCH}" "${i}-packages-nr-arm-only" "${i}-packages-nr"; do
for PACKAGE_LIST in "${i}-packages-nr-${ARCH}" "${i}-packages-nr-${PLATFORM}-only" "${i}-packages-nr-arm-only" "${i}-packages-nr"; do
if [ -f "${SUB_STAGE_DIR}/${PACKAGE_LIST}" ]; then
# Skip arm-only packages if not arm architecture
if [[ "${PACKAGE_LIST}" == *"-nr-arm-only" ]] && [[ "${ARCH}" != "armhf" && "${ARCH}" != "arm64" ]]; then
@@ -43,7 +43,7 @@ EOF
log "End ${SUB_STAGE_DIR}/${PACKAGE_LIST}"
fi
done
for PACKAGE_LIST in "${i}-packages-${ARCH}" "${i}-packages-arm-only" "${i}-packages"; do
for PACKAGE_LIST in "${i}-packages-${ARCH}" "${i}-packages-${PLATFORM}-only" "${i}-packages-arm-only" "${i}-packages"; do
if [ -f "${SUB_STAGE_DIR}/${PACKAGE_LIST}" ]; then
# Skip arm-only packages if not arm architecture
if [[ "${PACKAGE_LIST}" == *"-packages-arm-only" ]] && [[ "${ARCH}" != "armhf" && "${ARCH}" != "arm64" ]]; then
@@ -63,7 +63,7 @@ EOF
log "End ${SUB_STAGE_DIR}/${PACKAGE_LIST}"
fi
done
for PATCH_DIR in "${i}-patches-${ARCH}" "${i}-patches-arm-only" "${i}-patches"; do
for PATCH_DIR in "${i}-patches-${ARCH}" "${i}-patches-${PLATFORM}-only" "${i}-patches-arm-only" "${i}-patches"; do
if [ -d "${SUB_STAGE_DIR}/${PATCH_DIR}" ]; then
# Check arm-only patches should only apply for armhf/arm64
if [[ "${PATCH_DIR}" == *"-patches-arm-only" ]] && [[ "${ARCH}" != "armhf" && "${ARCH}" != "arm64" ]]; then
@@ -101,7 +101,7 @@ EOF
log "End ${SUB_STAGE_DIR}/${PATCH_DIR}"
fi
done
for RUN_SCRIPT in "${i}-run-${ARCH}.sh" "${i}-run-arm-only.sh" "${i}-run.sh"; do
for RUN_SCRIPT in "${i}-run-${ARCH}.sh" "${i}-run-${PLATFORM}-only.sh" "${i}-run-arm-only.sh" "${i}-run.sh"; do
if [ -x "${SUB_STAGE_DIR}/${RUN_SCRIPT}" ]; then
# Skip arm-only if not arm
if [[ "${RUN_SCRIPT}" == *"-arm-only.sh" ]] && [[ "${ARCH}" != "armhf" && "${ARCH}" != "arm64" ]]; then
@@ -111,9 +111,11 @@ EOF
log "Begin ${SUB_STAGE_DIR}/${RUN_SCRIPT}"
"./${RUN_SCRIPT}"
log "End ${SUB_STAGE_DIR}/${RUN_SCRIPT}"
elif [ "${RUN_SCRIPT}" = "${i}-run.sh" ] && [ -f "${SUB_STAGE_DIR}/${i}-run.sh" ]; then
log "Skip ${SUB_STAGE_DIR}/${i}-run.sh (not executable)"
fi
done
for CHROOT_SCRIPT in "${i}-run-chroot-${ARCH}.sh" "${i}-run-chroot-arm-only.sh" "${i}-run-chroot.sh"; do
for CHROOT_SCRIPT in "${i}-run-chroot-${ARCH}.sh" "${i}-run-chroot-${PLATFORM}-only.sh" "${i}-run-chroot-arm-only.sh" "${i}-run-chroot.sh"; do
if [ -f "${SUB_STAGE_DIR}/${CHROOT_SCRIPT}" ]; then
# Skip arm-only if not arm
if [[ "${CHROOT_SCRIPT}" == *"-arm-only.sh" ]] && [[ "${ARCH}" != "armhf" && "${ARCH}" != "arm64" ]]; then
@@ -141,11 +143,6 @@ run_stage() {
unmount "${WORK_DIR}/${STAGE}"
if [ ! -f SKIP_IMAGES ]; then
if [ -f "${STAGE_DIR}/EXPORT_IMAGE" ]; then
EXPORT_DIRS="${EXPORT_DIRS} ${STAGE_DIR}"
fi
fi
if [ ! -f SKIP ]; then
if [ "${CLEAN}" = "1" ]; then
if [ -d "${ROOTFS_DIR}" ]; then
@@ -159,7 +156,7 @@ run_stage() {
fi
for SUB_STAGE_DIR in "${STAGE_DIR}"/*; do
if [ -d "${SUB_STAGE_DIR}" ]; then
if [ ! -f "${SUB_STAGE_DIR}/SKIP" ] && [ ! -f "${SUB_STAGE_DIR}/SKIP_${ARCH}" ]; then
if [ ! -f "${SUB_STAGE_DIR}/SKIP" ] && [ ! -f "${SUB_STAGE_DIR}/SKIP_${ARCH}" ] && { [ -z "${PLATFORM}" ] || [ ! -f "${SUB_STAGE_DIR}/SKIP_${PLATFORM}" ]; }; then
run_sub_stage
fi
fi
@@ -182,7 +179,7 @@ term() {
log "Build finished"
fi
unmount "${STAGE_WORK_DIR}"
if [ "$STAGE" = "export-image" ]; then
if [ "$STAGE" = "exports/img" ]; then
for img in "${STAGE_WORK_DIR}/"*.img; do
unmount_image "$img"
done
@@ -226,8 +223,9 @@ export PI_GEN_REPO=${PI_GEN_REPO:-https://github.com/RPi-Distro/pi-gen}
export PI_GEN_RELEASE=${PI_GEN_RELEASE:-Raspberry Pi reference}
export ARCH="${ARCH:-arm64}"
export RELEASE=${RELEASE:-bookworm}
export IMG_NAME="${IMG_NAME:-chillcraftos-$RELEASE-$ARCH}"
export PLATFORM="${PLATFORM:-}"
export RELEASE=${RELEASE:-trixie}
export IMG_NAME="${IMG_NAME:-vesperos-$RELEASE-$ARCH}"
export USE_QEMU="${USE_QEMU:-0}"
export IMG_DATE="${IMG_DATE:-"$(date +%Y-%m-%d)"}"
@@ -242,9 +240,7 @@ export DEPLOY_COMPRESSION=${DEPLOY_COMPRESSION:-xz}
export COMPRESSION_LEVEL=${COMPRESSION_LEVEL:-6}
export LOG_FILE="${WORK_DIR}/build.log"
export TARGET_HOSTNAME=${TARGET_HOSTNAME:-chillcraftos}
export FIRST_USER_NAME=${FIRST_USER_NAME:-system}
export FIRST_USER_ISSYSTEM=${FIRST_USER_ISSYSTEM:-true}
export TARGET_HOSTNAME=${TARGET_HOSTNAME:-vesperos}
export WPA_COUNTRY
export ENABLE_SSH="${ENABLE_SSH:-0}"
export PUBKEY_ONLY_SSH="${PUBKEY_ONLY_SSH:-0}"
@@ -254,12 +250,10 @@ export LOCALE_DEFAULT="${LOCALE_DEFAULT:-en_US.UTF-8}"
export KEYBOARD_KEYMAP="${KEYBOARD_KEYMAP:-us}"
export KEYBOARD_LAYOUT="${KEYBOARD_LAYOUT:-English (US)}"
export TIMEZONE_DEFAULT="${TIMEZONE_DEFAULT:-Americas/Los_Angeles}"
export TIMEZONE_DEFAULT="${TIMEZONE_DEFAULT:-America/Los_Angeles}"
export GIT_HASH=${GIT_HASH:-"$(git rev-parse HEAD)"}
export PUBKEY_SSH_FIRST_USER
export CLEAN
export APT_PROXY
export TEMP_REPO
@@ -272,8 +266,6 @@ export PREV_STAGE_DIR
export ROOTFS_DIR
export PREV_ROOTFS_DIR
export IMG_SUFFIX
export NOOBS_NAME
export NOOBS_DESCRIPTION
export EXPORT_DIR
export EXPORT_ROOTFS_DIR
@@ -282,6 +274,10 @@ export QUILT_NO_DIFF_INDEX=1
export QUILT_NO_DIFF_TIMESTAMPS=1
export QUILT_REFRESH_ARGS="-p ab"
export ENABLE_CLOUD_INIT=${ENABLE_CLOUD_INIT:-1}
export LIVEBOOT=${LIVEBOOT:-0}
export EXPORTS="${EXPORTS:-}"
# shellcheck source=scripts/common
source "${SCRIPT_DIR}/common"
# shellcheck source=scripts/dependencies_check
@@ -317,12 +313,6 @@ if ! arch-test -n "$ARCH"; then
fi
fi
#check username is valid
if [[ ! "$FIRST_USER_NAME" =~ ^[a-z][-a-z0-9_]*$ ]]; then
echo "Invalid FIRST_USER_NAME: $FIRST_USER_NAME"
exit 1
fi
if [[ -n "${APT_PROXY}" ]] && ! curl --silent "${APT_PROXY}" >/dev/null; then
echo "Could not reach APT_PROXY server: ${APT_PROXY}"
exit 1
@@ -333,53 +323,44 @@ if [[ -n "${WPA_PASSWORD}" && ${#WPA_PASSWORD} -lt 8 || ${#WPA_PASSWORD} -gt 63
exit 1
fi
if [[ "${PUBKEY_ONLY_SSH}" = "1" && -z "${PUBKEY_SSH_FIRST_USER}" ]]; then
echo "Must set 'PUBKEY_SSH_FIRST_USER' to a valid SSH public key if using PUBKEY_ONLY_SSH"
exit 1
fi
log "Begin ${BASE_DIR}"
STAGE_LIST=${STAGE_LIST:-${BASE_DIR}/stage*}
export STAGE_LIST
EXPORT_CONFIG_DIR=$(realpath "${EXPORT_CONFIG_DIR:-"${BASE_DIR}/export-image"}")
if [ ! -d "${EXPORT_CONFIG_DIR}" ]; then
echo "EXPORT_CONFIG_DIR invalid: ${EXPORT_CONFIG_DIR} does not exist"
exit 1
fi
export EXPORT_CONFIG_DIR
for STAGE_DIR in $STAGE_LIST; do
STAGE_DIR=$(realpath "${STAGE_DIR}")
run_stage
done
CLEAN=1
for EXPORT_DIR in ${EXPORT_DIRS}; do
STAGE_DIR=${EXPORT_CONFIG_DIR}
# shellcheck source=/dev/null
source "${EXPORT_DIR}/EXPORT_IMAGE"
EXPORT_ROOTFS_DIR=${WORK_DIR}/$(basename "${EXPORT_DIR}")/rootfs
if [ -e "${EXPORT_DIR}/EXPORT_ISO" ]; then
# shellcheck source=/dev/null
source "${EXPORT_DIR}/EXPORT_ISO"
STAGE_DIR="${BASE_DIR}/export-iso"
# Exports declared in config: EXPORTS="stage3:squashfs stage2:img ..."
for export_spec in ${EXPORTS}; do
stage_name="${export_spec%%:*}"
export_type="${export_spec##*:}"
EXPORT_DIR="${BASE_DIR}/${stage_name}"
EXPORT_ROOTFS_DIR="${WORK_DIR}/${stage_name}/rootfs"
case "${export_type}" in
img)
STAGE_DIR="${BASE_DIR}/exports/img"
run_stage
elif [ -e "${EXPORT_DIR}/EXPORT_IMAGE" ]; then
# shellcheck source=/dev/null
source "${EXPORT_DIR}/EXPORT_IMAGE"
STAGE_DIR="${BASE_DIR}/export-image"
;;
squashfs)
STAGE_DIR="${BASE_DIR}/exports/squashfs"
run_stage
fi
if [ "${USE_QEMU}" != "1" ]; then
if [ -e "${EXPORT_DIR}/EXPORT_NOOBS" ]; then
# shellcheck source=/dev/null
source "${EXPORT_DIR}/EXPORT_NOOBS"
STAGE_DIR="${BASE_DIR}/export-noobs"
;;
noobs)
if [ "${USE_QEMU}" != "1" ]; then
STAGE_DIR="${BASE_DIR}/exports/noobs"
run_stage
fi
fi
;;
*)
log "Unknown export type '${export_type}' in EXPORTS spec '${export_spec}'"
false
;;
esac
done
if [ -x "${BASE_DIR}/postrun.sh" ]; then

View File

@@ -1 +0,0 @@
ARCH=amd64

View File

@@ -1 +0,0 @@
ARCH=arm64

21
configs/amd64 Normal file
View File

@@ -0,0 +1,21 @@
# This builds VesperOS for amd64
ARCH=amd64
# Suffix to append to the image name
#IMG_SUFFIX="-rainier"
# Exports to produce
EXPORTS="stage3:squashfs"
# Weather to export the image with compression (zip, gz, xz) or not (none)
DEPLOY_COMPRESSION="none"
# Set LIVEBOOT=1 to also produce a livefs.squashfs with Calamares installed
# for use with gen-installmedia. Outputs deploy/livefs.{squashfs,vmlinuz,initrd.img}
# alongside the clean deploy/rootfs.squashfs.
LIVEBOOT=1
# Live boot options
LIVE_USERNAME="vesper"
LIVE_USER_FULLNAME="VesperOS Live User"
LIVE_USER_PASSWORD="vesper"

11
configs/arm64 Normal file
View File

@@ -0,0 +1,11 @@
# This builds VesperOS for arm64
ARCH=arm64
# Suffix to append to the image name
#IMG_SUFFIX="-rainier"
# Exports to produce
EXPORTS="stage3:squashfs"
# Weather to export the image with compression (zip, gz, xz) or not (none)
DEPLOY_COMPRESSION="none"

17
configs/rpi4 Normal file
View File

@@ -0,0 +1,17 @@
# Raspberry Pi OS only targets arm64 since the rpi4.
# So VesperOS will also only target arm64 for the rpi4 and up.
# This builds VesperOS for arm64
ARCH=arm64
# This tells the build system we are targetting a raspberry pi
PLATFORM=rpi
# Suffix to append to the image name
IMG_SUFFIX="-rainier-rpi"
# Exports to produce
EXPORTS="stage3:squashfs"
# Weather to export the image with compression (zip, gz, xz) or not (none)
DEPLOY_COMPRESSION="none"

View File

@@ -6,6 +6,7 @@ debootstrap
zerofree
zip
mkdosfs:dosfstools
mke2fs:e2fsprogs
capsh:libcap2-bin
bsdtar:libarchive-tools
grep
@@ -20,3 +21,6 @@ bc
gpg
pigz
arch-test
mksquashfs:squashfs-tools
xorriso
grub-mkrescue:grub-common

View File

@@ -1,172 +1,133 @@
## Config
# Config
Upon execution, `build.sh` will source the file `config` in the current
working directory. This bash shell fragment is intended to set needed
environment variables.
The following environment variables are supported:
* `IMG_NAME` (Default: `raspios-$RELEASE-$ARCH`, for example: `raspios-bookworm-armhf`)
The name of the image to build with the current stage directories. Use this
variable to set the root name of your OS, eg `IMG_NAME=Frobulator`.
Export files in stages may add suffixes to `IMG_NAME`.
* `PI_GEN_RELEASE` (Default: `Raspberry Pi reference`)
The release name to use in `/etc/issue.txt`. The default should only be used
for official Raspberry Pi builds.
* `RELEASE` (Default: `bookworm`)
The release version to build images against. Valid values are any supported
Debian release. However, since different releases will have different sets of
packages available, you'll need to either modify your stages accordingly, or
checkout the appropriate branch. For example, if you'd like to build a
`bullseye` image, you should do so from the `bullseye` branch.
* `APT_PROXY` (Default: unset)
If you require the use of an apt proxy, set it here. This proxy setting
will not be included in the image, making it safe to use an `apt-cacher` or
similar package for development.
* `TEMP_REPO` (Default: unset)
An additional temporary apt repo to be used during the build process. This
could be useful if you require pre-release software to be included in the
image. The variable should contain sources in [one-line-style format](https://manpages.debian.org/stable/apt/sources.list.5.en.html#ONE-LINE-STYLE_FORMAT).
"RELEASE" will be replaced with the RELEASE variable.
* `BASE_DIR` (Default: location of `build.sh`)
**CAUTION**: Currently, changing this value will probably break build.sh
Top-level directory for `pi-gen`. Contains stage directories, build
scripts, and by default both work and deployment directories.
* `WORK_DIR` (Default: `$BASE_DIR/work`)
Directory in which `pi-gen` builds the target system. This value can be
changed if you have a suitably large, fast storage location for stages to
be built and cached. Note, `WORK_DIR` stores a complete copy of the target
system for each build stage, amounting to tens of gigabytes in the case of
Raspbian.
**CAUTION**: If your working directory is on an NTFS partition you probably won't be able to build: make sure this is a proper Linux filesystem.
* `DEPLOY_DIR` (Default: `$BASE_DIR/deploy`)
Output directory for target system images and NOOBS bundles.
* `DEPLOY_COMPRESSION` (Default: `zip`)
Set to:
* `none` to deploy the actual image (`.img`).
* `zip` to deploy a zipped image (`.zip`).
* `gz` to deploy a gzipped image (`.img.gz`).
* `xz` to deploy a xzipped image (`.img.xz`).
* `DEPLOY_ZIP` (Deprecated)
This option has been deprecated in favor of `DEPLOY_COMPRESSION`.
If `DEPLOY_ZIP=0` is still present in your config file, the behavior is the
same as with `DEPLOY_COMPRESSION=none`.
* `COMPRESSION_LEVEL` (Default: `6`)
Compression level to be used when using `zip`, `gz` or `xz` for
`DEPLOY_COMPRESSION`. From 0 to 9 (refer to the tool man page for more
information on this. Usually 0 is no compression but very fast, up to 9 with
the best compression but very slow ).
* `USE_QEMU` (Default: `0`)
Setting to '1' enables the QEMU mode - creating an image that can be mounted via QEMU for an emulated
environment. These images include "-qemu" in the image file name.
* `LOCALE_DEFAULT` (Default: 'en_GB.UTF-8' )
Default system locale.
* `TARGET_HOSTNAME` (Default: 'raspberrypi' )
Setting the hostname to the specified value.
* `KEYBOARD_KEYMAP` (Default: 'gb' )
Default keyboard keymap.
To get the current value from a running system, run `debconf-show
keyboard-configuration` and look at the
`keyboard-configuration/xkb-keymap` value.
* `KEYBOARD_LAYOUT` (Default: 'English (UK)' )
Default keyboard layout.
To get the current value from a running system, run `debconf-show
keyboard-configuration` and look at the
`keyboard-configuration/variant` value.
* `TIMEZONE_DEFAULT` (Default: 'Europe/London' )
Default time zone.
To get the current value from a running system, look in
`/etc/timezone`.
* `FIRST_USER_NAME` (Default: `system`)
Username for the first user. This user only exists during the image creation process.
* `WPA_COUNTRY` (Default: unset)
Sets the default WLAN regulatory domain and unblocks WLAN interfaces. This should be a 2-letter ISO/IEC 3166 country Code, i.e. `GB`
* `ENABLE_SSH` (Default: `0`)
Setting to `1` will enable ssh server for remote log in. Note that if you are using a common password such as the defaults there is a high risk of attackers taking over you Raspberry Pi.
* `PUBKEY_SSH_FIRST_USER` (Default: unset)
Setting this to a value will make that value the contents of the FIRST_USER_NAME's ~/.ssh/authorized_keys. Obviously the value should
therefore be a valid authorized_keys file. Note that this does not
automatically enable SSH.
* `PUBKEY_ONLY_SSH` (Default: `0`)
* Setting to `1` will disable password authentication for SSH and enable
public key authentication. Note that if SSH is not enabled this will take
effect when SSH becomes enabled.
* `SETFCAP` (Default: unset)
* Setting to `1` will prevent pi-gen from dropping the "capabilities"
feature. Generating the root filesystem with capabilities enabled and running
it from a filesystem that does not support capabilities (like NFS) can cause
issues. Only enable this if you understand what it is.
* `STAGE_LIST` (Default: `stage*`)
If set, then instead of working through the numeric stages in order, this list will be followed. For example setting to `"stage0 stage1 mystage stage2"` will run the contents of `mystage` before stage2. Note that quotes are needed around the list. An absolute or relative path can be given for stages outside the pi-gen directory.
* `EXPORT_CONFIG_DIR` (Default: `$BASE_DIR/export-image`)
If set, use this directory path as the location of scripts to run when generating images. An absolute or relative path can be given for a location outside the pi-gen directory.
A simple example for building Raspberry Pi OS:
`build.sh` sources the file `config` in the current working directory at startup. It can also be specified explicitly:
```bash
IMG_NAME='raspios'
sudo ./build.sh -c build_amd64
```
The config file can also be specified on the command line as an argument the `build.sh` or `build-docker.sh` scripts.
## Variables
```
./build.sh -c myconfig
### Core
* `IMG_NAME` (Default: `vesperos-$RELEASE-$ARCH`)
Base name for output files.
* `RELEASE` (Default: `trixie`)
Debian release to build against.
* `ARCH` (Default: `arm64`)
Target architecture. One of: `arm64`, `armhf`, `amd64`.
### Directories
* `WORK_DIR` (Default: `$BASE_DIR/work`)
Where stage rootfs directories are built. Should be on a Linux filesystem — NTFS will not work.
* `DEPLOY_DIR` (Default: `$BASE_DIR/deploy`)
Where finished images and archives are placed.
### Network / SSH
* `ENABLE_SSH` (Default: `0`)
Set to `1` to enable the SSH server in the built image.
* `PUBKEY_SSH_FIRST_USER` (Default: unset)
If set, written to `~/.ssh/authorized_keys` for the first user.
* `PUBKEY_ONLY_SSH` (Default: `0`)
Set to `1` to disable password auth and require public key auth for SSH.
* `APT_PROXY` (Default: unset)
Apt proxy URL (e.g. `http://192.168.1.1:3142`). Not included in the final image.
* `TEMP_REPO` (Default: unset)
Additional temporary apt repo used only during the build. Supports `RELEASE` substitution.
### Locale / Keyboard
* `LOCALE_DEFAULT` (Default: `en_US.UTF-8`)
* `KEYBOARD_KEYMAP` (Default: `en`)
* `KEYBOARD_LAYOUT` (Default: `English (US)`)
* `TIMEZONE_DEFAULT` (Default: `America/Los Angeles`)
### Cloud-init
* `ENABLE_CLOUD_INIT` (Default: `1`)
Set to `1` to install and configure cloud-init. On RPi, seed files go to `/boot/firmware/`. On amd64, they go to `/var/lib/cloud/seed/nocloud/`.
### Other
* `USE_QEMU` (Default: `0`)
Set to `1` to produce a QEMU-compatible image (adds `-qemu` suffix).
* `SETFCAP` (Default: unset)
Set to `1` to preserve Linux capabilities in the rootfs. Only needed for NFS or capability-sensitive deployments.
* `STAGE_LIST` (Default: `stage*`)
Override the list of stages to run. Example: `"stage0 stage1 mystage stage2"`.
* `EXPORTS` (Default: unset)
Space-separated list of `stage:type` pairs declaring what to export and from which stage. Supported types: `squashfs`, `img`, `noobs`. Example:
```bash
EXPORTS="stage3:squashfs"
EXPORTS="stage3:squashfs stage2:img"
```
### Live boot (squashfs only)
* `LIVEBOOT` (Default: `0`)
Set to `1` to produce a second `-live` squashfs alongside the raw one. Installs `live-boot`, configures GDM autologin, and rebuilds the initramfs. Only applies to `amd64`.
* `LIVE_USERNAME` (Default: `vesperos`)
* `LIVE_USER_FULLNAME` (Default: `Live User`)
* `LIVE_USER_PASSWORD` (Default: `vesperos`)
### NOOBS
* `NOOBS_NAME` — Display name shown in the NOOBS menu.
* `NOOBS_DESCRIPTION` — Short description shown in the NOOBS menu.
Both must be set in the config when using `noobs` in `EXPORTS`.
## Example Config Files
### amd64 with live boot
```bash
ARCH='amd64'
EXPORTS="stage3:squashfs"
DEPLOY_COMPRESSION="none"
LIVEBOOT=1
LIVE_USERNAME="vesper"
LIVE_USER_PASSWORD="vesper"
```
This is parsed after `config` so can be used to override values set there.
### Raspberry Pi (arm64)
```bash
ARCH='arm64'
EXPORTS="stage3:squashfs"
DEPLOY_COMPRESSION="none"
ENABLE_CLOUD_INIT=1
```

View File

@@ -1,47 +1,55 @@
## Docker Build
# Docker Build
Docker can be used to perform the build inside a container. This partially isolates
the build from the host system, and allows using the script on non-debian based
systems (e.g. Fedora Linux). The isolation is not complete due to the need to use
some kernel level services for arm emulation (binfmt) and loop devices (losetup).
Docker can be used to run the build inside a container. This is useful on non-Debian hosts (e.g. Fedora, Arch, macOS with Linux VM) or to keep the build environment isolated from the host system.
To build:
> **Note**: The Docker build is not fully isolated — it still needs kernel-level access for `binfmt_misc` (ARM emulation) and `losetup` (loop devices for `.img` builds).
## Building
```bash
vi config # Edit your config file. See above.
cp config.example config # edit as needed
./build-docker.sh
```
If everything goes well, your finished image will be in the `deploy/` folder.
You can then remove the build container with `docker rm -v pigen_work`
Output will be in `deploy/`.
If you encounter errors during the build, you can edit the corresponding scripts, and
continue:
## Continuing After a Failure
Edit the failing script, then resume without restarting from scratch:
```bash
CONTINUE=1 ./build-docker.sh
```
To examine the container after a failure you can enter a shell within it using:
## Inspecting the Container After a Failure
```bash
sudo docker run -it --privileged --volumes-from=pigen_work pi-gen /bin/bash
sudo docker run -it --privileged --volumes-from=pigen_work vesperos-build /bin/bash
```
After successful build, the build container is by default removed. This may be undesired when making incremental changes to a customized build. To prevent the build script from remove the container add
## Preserving the Container Between Runs
By default the container is removed after a successful build. To keep it for incremental development:
```bash
PRESERVE_CONTAINER=1 ./build-docker.sh
```
There is a possibility that even when running from a docker container, the
installation of `qemu-user-static` will silently fail when building the image
because `binfmt-support` _must be enabled on the underlying kernel_. An easy
fix is to ensure `binfmt-support` is installed on the host machine before
starting the `./build-docker.sh` script (or using your own docker build
solution).
## Passing Extra Docker Arguments
### Passing arguments to Docker
Use `PIGEN_DOCKER_OPTS` to pass additional flags to `docker run`:
When the docker image is run various required command line arguments are provided. For example the system mounts the `/dev` directory to the `/dev` directory within the docker container. If other arguments are required they may be specified in the PIGEN_DOCKER_OPTS environment variable. For example setting `PIGEN_DOCKER_OPTS="--add-host foo:192.168.0.23"` will add '192.168.0.23 foo' to the `/etc/hosts` file in the container. The `--name`
and `--privileged` options are already set by the script and should not be redefined.
```bash
PIGEN_DOCKER_OPTS="--add-host myrepo:192.168.1.10" ./build-docker.sh
```
The `--name` and `--privileged` flags are already set by the script and should not be redefined.
## binfmt_misc on Docker Hosts
If building ARM images, `binfmt_misc` must be enabled on the host kernel before starting the build:
```bash
sudo apt-get install binfmt-support qemu-user-static
sudo update-binfmts --enable
```

View File

@@ -1,48 +1,73 @@
# pi-gen
# Getting Started
Tool used to create Raspberry Pi OS images, and custom images based on Raspberry Pi OS,
which was in turn derived from the Raspbian project.
VesperOS is a Debian Trixie-based OS for Raspberry Pi (arm64/armhf) and amd64, built using a modified pi-gen pipeline.
**Note**: Raspberry Pi OS 32 bit images are based primarily on Raspbian, while
Raspberry Pi OS 64 bit images are based primarily on Debian.
## Supported Architectures
**Note**: 32 bit images should be built from the `master` branch.
64 bit images should be built from the `arm64` branch.
| Arch | Target | Output |
|---------|-------------------------------|----------------|
| `arm64` | Raspberry Pi 3/4/5 (64-bit) | `.squashfs` / `.img` |
| `amd64` | x86_64 PCs | `.squashfs` |
## Dependencies
## Build Host Requirements
pi-gen runs on Debian-based operating systems released after 2017, and we
always advise you use the latest OS for security reasons.
The build must run on a Debian-based Linux host. Ubuntu 22.04+ or Debian Bookworm/Trixie are recommended.
On other Linux distributions it may be possible to use the Docker build described
below.
To install the required dependencies for `pi-gen` you should run:
Install dependencies:
```bash
apt-get install coreutils quilt parted qemu-user-static debootstrap zerofree zip \
sudo apt-get install coreutils quilt parted qemu-user-static debootstrap zerofree zip \
dosfstools libarchive-tools libcap2-bin grep rsync xz-utils file git curl bc \
gpg pigz xxd arch-test
gpg pigz xxd arch-test squashfs-tools xorriso grub-common
```
The file `depends` contains a list of tools needed. The format of this
package is `<tool>[:<debian-package>]`.
The `depends` file in the repo root lists all required tools in `<tool>[:<debian-package>]` format.
## Getting started with building your images
Getting started is as simple as cloning this repository on your build machine. You
can do so with:
## Cloning
```bash
git clone https://github.com/RPI-Distro/pi-gen.git
git clone https://github.com/oxmc/VesperOS.git
cd VesperOS
```
`--depth 1` can be added after `git clone` to create a shallow clone, only containing
the latest revision of the repository. Do not do this on your development machine.
Do not clone to a path containing spaces — `debootstrap` does not support them.
Also, be careful to clone the repository to a base path **NOT** containing spaces.
This configuration is not supported by debootstrap and will lead to `pi-gen` not
running.
## Configuration
After cloning the repository, you can move to the next step and start configuring
your build.
Use one of the provided configs in `configs/`:
```bash
sudo ./build.sh -c configs/amd64
sudo ./build.sh -c configs/arm64
sudo ./build.sh -c configs/rpi4
```
Or create your own. See [config.md](config.md) for all available options. At minimum set:
```bash
ARCH='amd64' # or arm64
EXPORTS="stage3:squashfs"
```
## Building
```bash
sudo ./build.sh -c configs/amd64
```
Output files are placed in `deploy/`.
- `squashfs` builds produce a `.squashfs` (and `-live.squashfs` if `LIVEBOOT=1`).
- `img` builds produce a `.img` file you can flash with Balena Etcher or `dd`.
## Skipping Stages (Faster Iteration)
Add a `SKIP` file to any stage you don't want to re-run:
```bash
# Skip stages 0-2 to iterate on stage3 only
touch stage0/SKIP stage1/SKIP stage2/SKIP
sudo CLEAN=1 ./build.sh -c configs/amd64
```
Remove the `SKIP` files before a full clean build.

View File

@@ -1,43 +1,56 @@
## How the build process works
# How the Build Process Works
The following process is followed to build images:
`build.sh` iterates through stage directories in alphanumeric order and processes each one.
* Iterate through all of the stage directories in alphanumeric order
## Stage Processing
* Bypass a stage directory if it contains a file called
"SKIP"
For each stage directory:
* Run the script `prerun.sh` which is generally just used to copy the build
directory between stages.
1. Skip the stage entirely if a `SKIP` file is present.
2. Run `prerun.sh` — typically copies the rootfs from the previous stage.
3. Iterate through each numbered subdirectory (e.g. `00-configure-apt`, `01-sys-tweaks`) in order.
4. Within each subdirectory, process these files if present:
* In each stage directory iterate through each subdirectory and then run each of the
install scripts it contains, again in alphanumeric order. **These need to be named
with a two digit padded number at the beginning.**
There are a number of different files and directories which can be used to
control different parts of the build process:
| File | Description |
|------|-------------|
| `00-run.sh` | Shell script run on the host (must be executable) |
| `00-run-chroot.sh` | Shell script run inside the chroot (must be executable) |
| `00-debconf` | Passed to `debconf-set-selections` |
| `00-packages` | Packages installed via `apt-get install` |
| `00-packages-nr` | Same, but with `--no-install-recommends` |
| `00-packages-<arch>` | Arch-specific packages (e.g. `00-packages-amd64`, `00-packages-arm-only`) |
| `00-packages-nr-<arch>` | Arch-specific packages without recommends |
| `00-patches` | Directory of quilt patches applied to the rootfs |
| `00-patches-<arch>` | Arch-specific quilt patches |
- **00-run.sh** - A unix shell script. Needs to be made executable for it to run.
## Export Pipeline
- **00-run-chroot.sh** - A unix shell script which will be run in the chroot
of the image build directory. Needs to be made executable for it to run.
After all stages are processed, the build runs the export pipelines declared in the config via the `EXPORTS` variable:
- **00-debconf** - Contents of this file are passed to debconf-set-selections
to configure things like locale, etc.
```bash
EXPORTS="stage3:squashfs" # single export
EXPORTS="stage3:squashfs stage2:img" # multiple exports
```
- **00-packages** - A list of packages to install. Can have more than one, space
separated, per line.
| Export type | Pipeline | Output |
|-------------|----------|--------|
| `squashfs` | `exports/squashfs/` | `.squashfs` filesystem archive |
| `img` | `exports/img/` | `.img` disk image |
| `noobs` | `exports/noobs/` | NOOBS-compatible archive |
- **00-packages-nr** - As 00-packages, except these will be installed using
the `--no-install-recommends -y` parameters to apt-get.
### squashfs pipeline
- **00-patches** - A directory containing patch files to be applied, using quilt.
If a file named 'EDIT' is present in the directory, the build process will
be interrupted with a bash session, allowing an opportunity to create/revise
the patches.
1. `prerun.sh` — rsync rootfs into work dir
2. `01-set-sources` — clean apt sources
3. `02-network` — configure resolv.conf
4. `03-finalise` — rebuild initramfs, clean up rootfs
5. `04-export` — build squashfs; if `LIVEBOOT=1`, also applies live-boot config and produces a second `-live` squashfs
* If the stage directory contains files called "EXPORT_NOOBS" or "EXPORT_IMAGE" then
add this stage to a list of images to generate
## Arch-Specific Logic
* Generate the images for any stages that have specified them
Scripts and package files support arch suffixes:
- `-arm-only` — runs on `arm64` and `armhf` only
- `-amd64` — runs on `amd64` only
- `-${ARCH}` — can be any specific arch string
It is recommended to examine build.sh for finer details.
Scripts that handle arch themselves check `${ARCH}` and exit early if not applicable.

View File

@@ -1,84 +1,61 @@
## Stage Anatomy
# Stage Anatomy
### Raspbian Stage Overview
VesperOS is built in stages. Each stage builds on the previous one.
The build of Raspbian is divided up into several stages for logical clarity
and modularity. This causes some initial complexity, but it simplifies
maintenance and allows for more easy customization.
## Stages
- **Stage 0** - bootstrap. The primary purpose of this stage is to create a
usable filesystem. This is accomplished largely through the use of
`debootstrap`, which creates a minimal filesystem suitable for use as a
base.tgz on Debian systems. This stage also configures apt settings and
installs `raspberrypi-bootloader` which is missed by debootstrap. The
minimal core is installed but not configured. As a result, this stage will not boot.
### Stage 0 — Bootstrap
- **Stage 1** - truly minimal system. This stage makes the system bootable by
installing system files like `/etc/fstab`, configures the bootloader, makes
the network operable, and installs packages like raspi-config. At this
stage the system should boot to a local console from which you have the
means to perform basic tasks needed to configure and install the system.
Bootstraps a minimal Debian Trixie filesystem using `debootstrap`. Configures apt sources (including the VesperOS apt repo), installs firmware packages, and sets up the base package state. Does not produce a bootable system.
- **Stage 2** - lite system. This stage produces the Raspberry Pi OS Lite image.
Stage 2 installs some optimized memory functions, sets timezone and charmap
defaults, installs fake-hwclock and ntp, wireless LAN and bluetooth support,
dphys-swapfile, and other basics for managing the hardware. It also
creates necessary groups and gives the pi user access to sudo and the
standard console hardware permission groups.
- RPi: installs `raspi-firmware`, `linux-image-rpi-v8`, `linux-image-rpi-2712`
- amd64: installs `grub2`, `linux-image-amd64`
Note: Raspberry Pi OS Lite contains a number of tools for development,
including `Python`, `Lua` and the `build-essential` package. If you are
creating an image to deploy in products, be sure to remove extraneous development
tools before deployment.
### Stage 1 — Minimal Bootable System
- **Stage 3** - desktop system. Here's where you get the full desktop system
with X11 and LXDE, web browsers, git for development, Raspberry Pi OS custom UI
enhancements, etc. This is a base desktop system, with some development
tools installed.
Makes the system bootable. Installs `/etc/fstab` (arch-specific), configures the hostname, locale, and basic networking. At this stage the system can boot to a console.
- **Stage 4** - Normal Raspberry Pi OS image. System meant to fit on a 4GB card.
This is the stage that installs most things that make Raspberry Pi OS friendly
to new users - e.g. system documentation.
- RPi fstab: `/boot/firmware` (vfat) + btrfs root with subvolumes
- amd64 fstab: `/boot` (vfat) + `/boot/efi` + btrfs root with subvolumes
- **Stage 5** - The Raspberry Pi OS Full image. More development
tools, an email client, learning tools like Scratch, specialized packages
like sonic-pi, office productivity, etc.
Both use btrfs subvolumes: `@`, `@home`, `@var`, `@snapshots`.
### Stage specification
### Stage 2 — System Layer
If you wish to build up to a specified stage (such as building up to stage 2
for a lite system), place an empty file named `SKIP` in each of the `./stage`
directories you wish not to include.
Installs the core system utilities, tools, and services. This is the "lite" layer.
Then add an empty file named `SKIP_IMAGES` to `./stage4` and `./stage5` (if building up to stage 2) or
to `./stage2` (if building a minimal system).
Key additions:
- `zsh` as the system-wide default shell
- `btrfs-progs` + `snapper` for filesystem snapshots
- `cloud-init` + `netplan` for first-boot configuration
- Bluetooth, Wi-Fi, avahi, SSH, cups, and other system services
- Python 3, Lua, build tools
### Stage 3 — Desktop
Installs the full GNOME desktop environment and user-facing applications.
Key additions:
- GNOME Shell and core apps
- Firefox ESR
- amd64: `live-boot`, `live-config`, `live-config-systemd`, `grub-efi-amd64`
This stage triggers the export pipeline via `EXPORT_ISO` and/or `EXPORT_SQUASHFS` for amd64, and `EXPORT_IMAGE` for RPi.
## Export Outputs
| Stage | Arch | Marker | Output |
|-------|------|--------|--------|
| stage3 | amd64 | `EXPORT_ISO` | Bootable live ISO |
| stage3 | amd64 | `EXPORT_SQUASHFS` | Raw squashfs archive |
| stage3 | arm64/armhf | `EXPORT_IMAGE` | Flashable `.img` |
## Skipping Stages for Development
Place a `SKIP` file in any stage directory to skip it. Use `SKIP_IMAGES` to prevent an export from running without skipping the stage itself.
```bash
# Example for building a lite system
echo "IMG_NAME='raspios'" > config
touch ./stage3/SKIP ./stage4/SKIP ./stage5/SKIP
touch ./stage4/SKIP_IMAGES ./stage5/SKIP_IMAGES
sudo ./build.sh # or ./build-docker.sh
# Only rebuild stage3 (assumes stage0-2 already built)
touch stage0/SKIP stage1/SKIP stage2/SKIP
sudo CLEAN=1 ./build.sh -c config
```
If you wish to build further configurations upon (for example) the lite
system, you can also delete the contents of `./stage3` and `./stage4` and
replace with your own contents in the same format.
## Skipping stages to speed up development
If you're working on a specific stage the recommended development process is as
follows:
* Add a file called SKIP_IMAGES into the directories containing EXPORT_* files
(currently stage2, stage4 and stage5)
* Add SKIP files to the stages you don't want to build. For example, if you're
basing your image on the lite image you would add these to stages 3, 4 and 5.
* Run build.sh to build all stages
* Add SKIP files to the earlier successfully built stages
* Modify the last stage
* Rebuild just the last stage using `sudo CLEAN=1 ./build.sh` (or, for docker builds
`PRESERVE_CONTAINER=1 CONTINUE=1 CLEAN=1 ./build-docker.sh`)
* Once you're happy with the image you can remove the SKIP_IMAGES files and
export your image to test

View File

@@ -1,45 +1,59 @@
# Troubleshooting
## `64 Bit Systems`
A 64 bit image can be generated from the `arm64` branch in this repository. Just
replace the command from [this section](#getting-started-with-building-your-images)
by the one below, and follow the rest of the documentation:
```bash
git clone --branch arm64 https://github.com/RPI-Distro/pi-gen.git
```
## binfmt_misc (cross-arch builds)
If you want to generate a 64 bits image from a Raspberry Pi running a 32 bits
version, you need to add `arm_64bit=1` to your `config.txt` file and reboot your
machine. This will restart your machine with a 64 bits kernel. This will only
work from a Raspberry Pi with a 64-bit capable processor (i.e. Raspberry Pi Zero
2, Raspberry Pi 3 or Raspberry Pi 4).
## `binfmt_misc`
Linux is able to execute binaries from other architectures, meaning that it should be
possible to make use of `pi-gen` on an x86_64 system, even though it will be running
ARM binaries. This requires support from the [`binfmt_misc`](https://en.wikipedia.org/wiki/Binfmt_misc)
kernel module.
You may see one of the following errors:
When building ARM images on an x86_64 host, Linux uses `binfmt_misc` to run ARM binaries via QEMU. If you see:
```
update-binfmts: warning: Couldn't load the binfmt_misc module.
```
```
W: Failure trying to run: chroot "/pi-gen/work/test/stage0/rootfs" /bin/true
and/or
chroot: failed to run command '/bin/true': Exec format error
```
To resolve this, ensure that the following files are available (install them if necessary):
Fix:
```
/lib/modules/$(uname -r)/kernel/fs/binfmt_misc.ko
/usr/bin/qemu-aarch64-static
```bash
sudo modprobe binfmt_misc
sudo apt-get install qemu-user-static binfmt-support
sudo update-binfmts --enable
```
You may also need to load the module by hand - run `modprobe binfmt_misc`.
On WSL2 you may need to install `binfmt-support` on the host Windows side or use Docker instead.
If you are using WSL to build you may have to enable the service `sudo update-binfmts --enable`
## "Required dependencies not installed"
The `depends` file lists tools that must be present on the build host. Read the README for the current install commands.
Note: `grub-efi-amd64-bin` and `grub-pc-bin` are data packages with no associated binary — they are not checked by the dependency checker but must be installed for `grub-mkrescue` to work.
## ISO doesn't boot
- Verify the ISO was written correctly: use Balena Etcher or `dd` — do not just copy the file.
- In VMware/VirtualBox, set firmware to UEFI.
- If GRUB appears but the system hangs after selecting a menu entry, try the "safe mode" entry (adds `nomodeset`).
## Squashfs / initramfs errors during export-iso
- `mkinitramfs: failed to determine device for /` — This happens when `MODULES=dep` is set in a chroot. The build sets `MODULES=most` to avoid this.
- `W: Couldn't identify type of root file system` — Expected during initramfs generation in a live build; the fstab is rewritten for live-boot and has no real block devices to detect.
## Stage fails despite SKIP file
`SKIP` files only skip re-running the stage scripts. They do not skip the export pipeline. Use `SKIP_IMAGES` to skip exports while still running the stage.
## Build fails on NTFS / exFAT partition
The work directory must be on a Linux filesystem (ext4, btrfs, xfs). NTFS and exFAT do not support the required file attributes. Set `WORK_DIR` to a path on a Linux filesystem:
```bash
export WORK_DIR=/mnt/linux-disk/vesperos-work
```
## Apt errors: "doesn't support architecture"
The VesperOS apt repo (`cdn.oxmc.me/apt`) currently only supports `arm64`/`armhf`. On amd64 builds you will see:
```
Notice: Skipping ... doesn't support architecture 'amd64'
```
This is expected and not an error — standard Debian repos are used for amd64 packages.

View File

@@ -1,15 +0,0 @@
#!/bin/bash -e
IMG_FILE="${STAGE_WORK_DIR}/${IMG_FILENAME}${IMG_SUFFIX}.img"
IMGID="$(dd if="${IMG_FILE}" skip=440 bs=1 count=4 2>/dev/null | xxd -e | cut -f 2 -d' ')"
BOOT_PARTUUID="${IMGID}-01"
ROOT_PARTUUID="${IMGID}-02"
#HOME_PARTUUID="${IMGID}-03"
sed -i "s/BOOTDEV/PARTUUID=${BOOT_PARTUUID}/" "${ROOTFS_DIR}/etc/fstab"
sed -i "s/ROOTDEV/PARTUUID=${ROOT_PARTUUID}/" "${ROOTFS_DIR}/etc/fstab"
#sed -i "s/HOMEDEV/PARTUUID=${HOME_PARTUUID}/" "${ROOTFS_DIR}/etc/fstab"
sed -i "s/ROOTDEV/PARTUUID=${ROOT_PARTUUID}/" "${ROOTFS_DIR}/boot/firmware/cmdline.txt"

View File

@@ -1,141 +0,0 @@
#!/bin/bash -e
IMG_FILE="${STAGE_WORK_DIR}/${IMG_FILENAME}${IMG_SUFFIX}.img"
INFO_FILE="${STAGE_WORK_DIR}/${IMG_FILENAME}${IMG_SUFFIX}.info"
SBOM_FILE="${STAGE_WORK_DIR}/${IMG_FILENAME}${IMG_SUFFIX}.sbom"
BMAP_FILE="${STAGE_WORK_DIR}/${IMG_FILENAME}${IMG_SUFFIX}.bmap"
on_chroot << EOF
update-initramfs -k all -c
if [ -x /etc/init.d/fake-hwclock ]; then
/etc/init.d/fake-hwclock stop
fi
if hash hardlink 2>/dev/null; then
hardlink -t /usr/share/doc
fi
EOF
if [ -f "${ROOTFS_DIR}/etc/initramfs-tools/update-initramfs.conf" ]; then
sed -i 's/^update_initramfs=.*/update_initramfs=yes/' "${ROOTFS_DIR}/etc/initramfs-tools/update-initramfs.conf"
sed -i 's/^MODULES=.*/MODULES=dep/' "${ROOTFS_DIR}/etc/initramfs-tools/initramfs.conf"
fi
#if [ -d "${ROOTFS_DIR}/home/${FIRST_USER_NAME}/.config" ]; then
# chmod 700 "${ROOTFS_DIR}/home/${FIRST_USER_NAME}/.config"
#fi
rm -f "${ROOTFS_DIR}/usr/bin/qemu-arm-static"
if [ "${USE_QEMU}" != "1" ]; then
if [ -e "${ROOTFS_DIR}/etc/ld.so.preload.disabled" ]; then
mv "${ROOTFS_DIR}/etc/ld.so.preload.disabled" "${ROOTFS_DIR}/etc/ld.so.preload"
fi
fi
rm -f "${ROOTFS_DIR}/etc/network/interfaces.dpkg-old"
rm -f "${ROOTFS_DIR}/etc/apt/sources.list~"
rm -f "${ROOTFS_DIR}/etc/apt/trusted.gpg~"
rm -f "${ROOTFS_DIR}/etc/passwd-"
rm -f "${ROOTFS_DIR}/etc/group-"
rm -f "${ROOTFS_DIR}/etc/shadow-"
rm -f "${ROOTFS_DIR}/etc/gshadow-"
rm -f "${ROOTFS_DIR}/etc/subuid-"
rm -f "${ROOTFS_DIR}/etc/subgid-"
rm -f "${ROOTFS_DIR}"/var/cache/debconf/*-old
rm -f "${ROOTFS_DIR}"/var/lib/dpkg/*-old
rm -f "${ROOTFS_DIR}"/usr/share/icons/*/icon-theme.cache
rm -f "${ROOTFS_DIR}/var/lib/dbus/machine-id"
true > "${ROOTFS_DIR}/etc/machine-id"
ln -nsf /proc/mounts "${ROOTFS_DIR}/etc/mtab"
find "${ROOTFS_DIR}/var/log/" -type f -exec cp /dev/null {} \;
rm -f "${ROOTFS_DIR}/root/.vnc/private.key"
rm -f "${ROOTFS_DIR}/etc/vnc/updateid"
update_issue "$(basename "${EXPORT_DIR}")"
install -m 644 "${ROOTFS_DIR}/etc/rpi-issue" "${ROOTFS_DIR}/boot/firmware/issue.txt"
if ! [ -L "${ROOTFS_DIR}/boot/issue.txt" ]; then
ln -s firmware/issue.txt "${ROOTFS_DIR}/boot/issue.txt"
fi
cp "$ROOTFS_DIR/etc/rpi-issue" "$INFO_FILE"
{
if [ -f "$ROOTFS_DIR/usr/share/doc/raspberrypi-kernel/changelog.Debian.gz" ]; then
firmware=$(zgrep "firmware as of" \
"$ROOTFS_DIR/usr/share/doc/raspberrypi-kernel/changelog.Debian.gz" | \
head -n1 | sed -n 's|.* \([^ ]*\)$|\1|p')
printf "\nFirmware: https://github.com/raspberrypi/firmware/tree/%s\n" "$firmware"
kernel="$(curl -s -L "https://github.com/raspberrypi/firmware/raw/$firmware/extra/git_hash")"
printf "Kernel: https://github.com/raspberrypi/linux/tree/%s\n" "$kernel"
uname="$(curl -s -L "https://github.com/raspberrypi/firmware/raw/$firmware/extra/uname_string7")"
printf "Uname string: %s\n" "$uname"
fi
printf "\nPackages:\n"
dpkg -l --root "$ROOTFS_DIR"
} >> "$INFO_FILE"
if hash syft 2>/dev/null; then
syft scan dir:"${ROOTFS_DIR}" \
--base-path="${ROOTFS_DIR}" \
--source-name="${IMG_NAME}${IMG_SUFFIX}" \
--source-version="${IMG_DATE}" \
-o spdx-json="${SBOM_FILE}"
fi
ROOT_DEV="$(awk "\$2 == \"${ROOTFS_DIR}\" {print \$1}" /etc/mtab)"
unmount "${ROOTFS_DIR}"
zerofree "${ROOT_DEV}"
unmount_image "${IMG_FILE}"
if hash bmaptool 2>/dev/null; then
bmaptool create \
-o "${BMAP_FILE}" \
"${IMG_FILE}"
fi
mkdir -p "${DEPLOY_DIR}"
rm -f "${DEPLOY_DIR}/${ARCHIVE_FILENAME}${IMG_SUFFIX}.*"
rm -f "${DEPLOY_DIR}/${IMG_FILENAME}${IMG_SUFFIX}.img"
case "${DEPLOY_COMPRESSION}" in
zip)
pushd "${STAGE_WORK_DIR}" > /dev/null
zip -"${COMPRESSION_LEVEL}" \
"${DEPLOY_DIR}/${ARCHIVE_FILENAME}${IMG_SUFFIX}.zip" "$(basename "${IMG_FILE}")"
popd > /dev/null
;;
gz)
pigz --force -"${COMPRESSION_LEVEL}" "$IMG_FILE" --stdout > \
"${DEPLOY_DIR}/${ARCHIVE_FILENAME}${IMG_SUFFIX}.img.gz"
;;
xz)
xz --compress --force --threads 0 --memlimit-compress=50% -"${COMPRESSION_LEVEL}" \
--stdout "$IMG_FILE" > "${DEPLOY_DIR}/${ARCHIVE_FILENAME}${IMG_SUFFIX}.img.xz"
;;
none | *)
cp "$IMG_FILE" "$DEPLOY_DIR/"
;;
esac
if [ -f "${SBOM_FILE}" ]; then
xz -c "${SBOM_FILE}" > "$DEPLOY_DIR/image_$(basename "${SBOM_FILE}").xz"
fi
if [ -f "${BMAP_FILE}" ]; then
xz -c "${BMAP_FILE}" > "$DEPLOY_DIR/image_$(basename "${BMAP_FILE}").xz"
fi
cp "$INFO_FILE" "$DEPLOY_DIR/"

View File

@@ -1,134 +0,0 @@
#!/bin/bash -e
IMG_NAME="${IMG_FILENAME}${IMG_SUFFIX}"
IMG_FILE="${STAGE_WORK_DIR}/${IMG_NAME}.img"
MOUNT_DIR="${ROOTFS_DIR}"
BOOT_SIZE=$((512 * 1024 * 1024))
EFI_SIZE=$((128 * 1024 * 1024)) # 128MB EFI partition
RECOVERY_SIZE=$((256 * 1024 * 1024))
ALIGN=$((4 * 1024 * 1024))
unmount_image "${IMG_FILE}"
rm -f "${IMG_FILE}"
rm -rf "${MOUNT_DIR}"
mkdir -p "${MOUNT_DIR}"
# Calculate rootfs size
ROOT_SIZE=$(du -x --apparent-size -s "${EXPORT_ROOTFS_DIR}" --exclude var/cache/apt/archives --exclude boot/firmware --block-size=1 | cut -f 1)
ROOT_MARGIN="$(echo "($ROOT_SIZE * 0.2 + 200 * 1024 * 1024) / 1" | bc)"
BOOT_PART_START=$((ALIGN))
BOOT_PART_SIZE=$(((BOOT_SIZE + ALIGN - 1) / ALIGN * ALIGN))
EFI_PART_START=$((BOOT_PART_START + BOOT_PART_SIZE))
EFI_PART_SIZE=$(((EFI_SIZE + ALIGN - 1) / ALIGN * ALIGN))
ROOT_PART_START=$((EFI_PART_START + EFI_PART_SIZE))
ROOT_PART_SIZE=$(((ROOT_SIZE + ROOT_MARGIN + ALIGN - 1) / ALIGN * ALIGN))
RECOVERY_PART_START=$((ROOT_PART_START + ROOT_PART_SIZE))
RECOVERY_PART_SIZE=$(((RECOVERY_SIZE + ALIGN - 1) / ALIGN * ALIGN))
IMG_SIZE=$((BOOT_PART_START + BOOT_PART_SIZE + EFI_PART_SIZE + ROOT_PART_SIZE + RECOVERY_PART_SIZE))
# Create raw image
truncate -s "${IMG_SIZE}" "${IMG_FILE}"
parted --script "${IMG_FILE}" mklabel gpt
parted --script "${IMG_FILE}" unit B mkpart primary fat32 "${BOOT_PART_START}" "$((BOOT_PART_START + BOOT_PART_SIZE - 1))"
parted --script "${IMG_FILE}" set 1 boot on
parted --script "${IMG_FILE}" unit B mkpart primary fat32 "${EFI_PART_START}" "$((EFI_PART_START + EFI_PART_SIZE - 1))"
parted --script "${IMG_FILE}" set 2 esp on
parted --script "${IMG_FILE}" unit B mkpart primary ext4 "${ROOT_PART_START}" "$((ROOT_PART_START + ROOT_PART_SIZE - 1))"
parted --script "${IMG_FILE}" unit B mkpart primary ext4 "${RECOVERY_PART_START}" "$((RECOVERY_PART_START + RECOVERY_PART_SIZE - 1))"
# Create loop device
cnt=0
until ensure_next_loopdev && LOOP_DEV="$(losetup --show --find --partscan "$IMG_FILE")"; do
((cnt++))
if [ $cnt -ge 5 ]; then echo "ERROR: losetup failed"; exit 1; fi
echo "Retrying losetup..."; sleep 5
done
ensure_loopdev_partitions "$LOOP_DEV"
BOOT_DEV="${LOOP_DEV}p1"
EFI_DEV="${LOOP_DEV}p2"
ROOT_DEV="${LOOP_DEV}p3"
RECOVERY_DEV="${LOOP_DEV}p4"
# Format partitions
FAT_SIZE=$([ "$BOOT_SIZE" -lt 134742016 ] && echo 16 || echo 32)
mkdosfs -n bootfs -F "$FAT_SIZE" -s 4 "$BOOT_DEV"
mkfs.fat -F 32 -n EFI "$EFI_DEV"
mkfs.ext4 -L rootfs -O "^64bit,^huge_file" "$ROOT_DEV"
mkfs.ext4 -L recovery "$RECOVERY_DEV"
# Mount and copy rootfs
mount "$ROOT_DEV" "$MOUNT_DIR" -t ext4
mkdir -p "${MOUNT_DIR}/boot"
mount "$BOOT_DEV" "${MOUNT_DIR}/boot" -t vfat
mkdir -p "${MOUNT_DIR}/boot/efi"
mount "$EFI_DEV" "${MOUNT_DIR}/boot/efi" -t vfat
rsync -aHAXx --exclude /var/cache/apt/archives --exclude /boot/firmware --exclude /boot/overlays "${EXPORT_ROOTFS_DIR}/" "${MOUNT_DIR}/"
# Recovery partition
mkdir -p "${MOUNT_DIR}/recovery"
mount "$RECOVERY_DEV" "${MOUNT_DIR}/recovery" -t ext4
# Optionally copy recovery tools
# cp recovery-tools/recovery.sh "${MOUNT_DIR}/recovery/"
# Install GRUB (BIOS)
mkdir -p "${MOUNT_DIR}/boot/grub"
cat > "${MOUNT_DIR}/boot/grub/grub.cfg" <<EOF
set default=0
set timeout=5
menuentry "Linux" {
linux /boot/vmlinuz root=/dev/sda3
initrd /boot/initrd.img
}
EOF
grub-install \
--target=i386-pc \
--boot-directory="${MOUNT_DIR}/boot" \
--modules="part_msdos ext2 fat normal biosdisk" \
--force \
--no-floppy \
--boot-directory="${MOUNT_DIR}/boot" \
"$LOOP_DEV"
# Install GRUB (UEFI)
mkdir -p "${MOUNT_DIR}/boot/efi/EFI/boot"
grub-install \
--target=x86_64-efi \
--efi-directory="${MOUNT_DIR}/boot/efi" \
--boot-directory="${MOUNT_DIR}/boot" \
--removable \
--no-nvram \
--modules="part_gpt part_msdos ext2 fat normal efi_gop efi_uga biosdisk" \
--bootloader-id=GRUB \
--recheck
# Unmount all
umount -l "${MOUNT_DIR}/boot/efi"
umount -l "${MOUNT_DIR}/boot"
umount -l "${MOUNT_DIR}/recovery"
umount -l "${MOUNT_DIR}"
losetup -d "$LOOP_DEV"
# Create hybrid ISO using xorriso (make sure it's installed)
ISO_FILE="${STAGE_WORK_DIR}/${IMG_NAME}.iso"
EFI_IMG="${STAGE_WORK_DIR}/efi.img"
dd if=/dev/zero of="${EFI_IMG}" bs=1M count=128
mkfs.vfat "${EFI_IMG}"
mmd -i "${EFI_IMG}" ::/EFI ::/EFI/boot
mcopy -i "${EFI_IMG}" "${MOUNT_DIR}/boot/efi/EFI/boot/bootx64.efi" ::/EFI/boot/bootx64.efi
xorriso -as mkisofs \
-r -J -joliet -l \
-b boot/grub/i386-pc/eltorito.img \
-no-emul-boot -boot-load-size 4 -boot-info-table \
-eltorito-alt-boot \
-e efi.img \
-no-emul-boot \
-isohybrid-gpt-basdat \
-o "${ISO_FILE}" \
"${MOUNT_DIR}" \
--efi-boot-part --efi-boot-image --protective-msdos-label
echo "Bootable ISO with BIOS and UEFI support created at ${ISO_FILE}"

View File

@@ -5,14 +5,17 @@ INFO_FILE="${STAGE_WORK_DIR}/${IMG_FILENAME}${IMG_SUFFIX}.info"
SBOM_FILE="${STAGE_WORK_DIR}/${IMG_FILENAME}${IMG_SUFFIX}.sbom"
BMAP_FILE="${STAGE_WORK_DIR}/${IMG_FILENAME}${IMG_SUFFIX}.bmap"
on_chroot << EOF
update-initramfs -k all -c
if [ -x /etc/init.d/fake-hwclock ]; then
/etc/init.d/fake-hwclock stop
fi
if hash hardlink 2>/dev/null; then
hardlink -t /usr/share/doc
fi
on_chroot <<- EOF
update-initramfs -k all -c
if hash hardlink 2>/dev/null; then
hardlink -t /usr/share/doc
fi
if [ -f /usr/lib/systemd/system/apt-listchanges.service ]; then
python3 -m apt_listchanges.populate_database --profile apt
systemctl disable apt-listchanges.timer
fi
install -m 755 -o systemd-timesync -g systemd-timesync -d /var/lib/systemd/timesync
install -m 644 -o systemd-timesync -g systemd-timesync /dev/null /var/lib/systemd/timesync/clock
EOF
if [ -f "${ROOTFS_DIR}/etc/initramfs-tools/update-initramfs.conf" ]; then
@@ -51,7 +54,7 @@ rm -f "${ROOTFS_DIR}"/usr/share/icons/*/icon-theme.cache
rm -f "${ROOTFS_DIR}/var/lib/dbus/machine-id"
true > "${ROOTFS_DIR}/etc/machine-id"
echo "uninitialized" > "${ROOTFS_DIR}/etc/machine-id"
ln -nsf /proc/mounts "${ROOTFS_DIR}/etc/mtab"

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 50 KiB

View File

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

View File

Before

Width:  |  Height:  |  Size: 104 KiB

After

Width:  |  Height:  |  Size: 104 KiB

View File

Before

Width:  |  Height:  |  Size: 93 KiB

After

Width:  |  Height:  |  Size: 93 KiB

View File

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 79 KiB

View File

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 65 KiB

View File

Before

Width:  |  Height:  |  Size: 104 KiB

After

Width:  |  Height:  |  Size: 104 KiB

View File

@@ -1,11 +1,7 @@
#!/bin/bash -e
if [[ "${ARCH}" == "arm64" || "${ARCH}" == "armhf" ]]; then
if [ ! -x "${ROOTFS_DIR}/usr/bin/qemu-arm-static" ]; then
cp /usr/bin/qemu-arm-static "${ROOTFS_DIR}/usr/bin/"
fi
if [ -e "${ROOTFS_DIR}/etc/ld.so.preload" ]; then
mv "${ROOTFS_DIR}/etc/ld.so.preload" "${ROOTFS_DIR}/etc/ld.so.preload.disabled"
fi
fi
fi

View File

@@ -1,10 +1,10 @@
#!/bin/bash -e
rm -f "${ROOTFS_DIR}/etc/apt/apt.conf.d/51cache"
rm -f "${ROOTFS_DIR}/etc/apt/sources.list.d/00-temp.list"
find "${ROOTFS_DIR}/var/lib/apt/lists/" -type f -delete
on_chroot << EOF
apt-get update
apt-get -y dist-upgrade --auto-remove --purge
apt-get clean
apt-file update
EOF

View File

@@ -0,0 +1,53 @@
#!/bin/bash -e
# Ensure update-initramfs actually runs — it silently exits if update_initramfs=no/disabled,
# which may have been set during the build to suppress apt-hook rebuilds.
if [ -f "${ROOTFS_DIR}/etc/initramfs-tools/update-initramfs.conf" ]; then
sed -i 's/^update_initramfs=.*/update_initramfs=yes/' "${ROOTFS_DIR}/etc/initramfs-tools/update-initramfs.conf"
fi
on_chroot <<- EOF
# Ensure Plymouth plymouthd.conf has the correct theme before packing initramfs.
# update-alternatives only sets the symlink; the initramfs hook reads plymouthd.conf.
if which plymouth-set-default-theme > /dev/null 2>&1; then
plymouth-set-default-theme vesperos
fi
update-initramfs -k all -c
if hash hardlink 2>/dev/null; then
hardlink -t /usr/share/doc
fi
if [ -f /usr/lib/systemd/system/apt-listchanges.service ]; then
python3 -m apt_listchanges.populate_database --profile apt
systemctl disable apt-listchanges.timer
fi
install -m 755 -o systemd-timesync -g systemd-timesync -d /var/lib/systemd/timesync
install -m 644 -o systemd-timesync -g systemd-timesync /dev/null /var/lib/systemd/timesync/clock
EOF
rm -f "${ROOTFS_DIR}/usr/bin/qemu-arm-static"
if [ "${USE_QEMU}" != "1" ]; then
if [ -e "${ROOTFS_DIR}/etc/ld.so.preload.disabled" ]; then
mv "${ROOTFS_DIR}/etc/ld.so.preload.disabled" "${ROOTFS_DIR}/etc/ld.so.preload"
fi
fi
rm -f "${ROOTFS_DIR}/etc/network/interfaces.dpkg-old"
rm -f "${ROOTFS_DIR}/etc/apt/sources.list~"
rm -f "${ROOTFS_DIR}/etc/apt/trusted.gpg~"
rm -f "${ROOTFS_DIR}/etc/passwd-"
rm -f "${ROOTFS_DIR}/etc/group-"
rm -f "${ROOTFS_DIR}/etc/shadow-"
rm -f "${ROOTFS_DIR}/etc/gshadow-"
rm -f "${ROOTFS_DIR}/etc/subuid-"
rm -f "${ROOTFS_DIR}/etc/subgid-"
rm -f "${ROOTFS_DIR}"/var/cache/debconf/*-old
rm -f "${ROOTFS_DIR}"/var/lib/dpkg/*-old
rm -f "${ROOTFS_DIR}"/usr/share/icons/*/icon-theme.cache
rm -f "${ROOTFS_DIR}/var/lib/dbus/machine-id"
echo "uninitialized" > "${ROOTFS_DIR}/etc/machine-id"
ln -nsf /proc/mounts "${ROOTFS_DIR}/etc/mtab"
find "${ROOTFS_DIR}/var/log/" -type f -exec cp /dev/null {} \;

View File

@@ -0,0 +1,14 @@
#!/bin/sh
# Runs at live boot only. Sets DCONF_PROFILE=live for the live user
# so the live dconf database is used instead of the installed default.
# Source live-config variables (provides LIVE_USERNAME etc.)
. /etc/live/config.conf 2>/dev/null || true
LIVE_USER="${LIVE_USERNAME:-vesperos}"
LIVE_HOME="/home/${LIVE_USER}"
if [ -d "${LIVE_HOME}" ]; then
mkdir -p "${LIVE_HOME}/.config/environment.d"
echo 'DCONF_PROFILE=live' > "${LIVE_HOME}/.config/environment.d/dconf.conf"
chown -R "${LIVE_USER}:${LIVE_USER}" "${LIVE_HOME}/.config"
fi

View File

@@ -0,0 +1,3 @@
user-db:user
system-db:live
system-db:local

View File

@@ -0,0 +1,4 @@
#[org/gnome/desktop/background]
#picture-uri='file:///usr/share/backgrounds/vesperos-live.png'
#picture-uri-dark='file:///usr/share/backgrounds/vesperos-live.png'
#picture-options='zoom'

View File

@@ -0,0 +1,222 @@
#!/bin/bash -e
SQUASHFS_FILE="${STAGE_WORK_DIR}/${IMG_FILENAME}${IMG_SUFFIX}.squashfs"
unmount "${ROOTFS_DIR}"
# ── 1. Raw squashfs ────────────────────────────────────────────────────────────
mksquashfs "${ROOTFS_DIR}" "${SQUASHFS_FILE}" \
-comp xz \
-noappend \
-e boot/efi
# Locate kernel and initrd inside the rootfs
VMLINUZ=$(find "${ROOTFS_DIR}/boot" -maxdepth 1 -name "vmlinuz-*" | sort | tail -1)
INITRD=$(find "${ROOTFS_DIR}/boot" -maxdepth 1 -name "initrd.img-*" | sort | tail -1)
VMLINUZ_FILE=""
INITRD_FILE=""
if [ -n "${VMLINUZ}" ]; then
VMLINUZ_FILE="${STAGE_WORK_DIR}/${IMG_FILENAME}${IMG_SUFFIX}.vmlinuz"
cp "${VMLINUZ}" "${VMLINUZ_FILE}"
fi
if [ -n "${INITRD}" ]; then
INITRD_FILE="${STAGE_WORK_DIR}/${IMG_FILENAME}${IMG_SUFFIX}.initrd"
cp "${INITRD}" "${INITRD_FILE}"
fi
mkdir -p "${DEPLOY_DIR}"
rm -f "${DEPLOY_DIR}/${ARCHIVE_FILENAME}${IMG_SUFFIX}."*
case "${DEPLOY_COMPRESSION}" in
zip)
pushd "${STAGE_WORK_DIR}" > /dev/null
ZIP_MEMBERS="$(basename "${SQUASHFS_FILE}")"
[ -n "${VMLINUZ_FILE}" ] && ZIP_MEMBERS="${ZIP_MEMBERS} $(basename "${VMLINUZ_FILE}")"
[ -n "${INITRD_FILE}" ] && ZIP_MEMBERS="${ZIP_MEMBERS} $(basename "${INITRD_FILE}")"
# shellcheck disable=SC2086
zip -"${COMPRESSION_LEVEL}" \
"${DEPLOY_DIR}/${ARCHIVE_FILENAME}${IMG_SUFFIX}.zip" \
${ZIP_MEMBERS}
popd > /dev/null
echo "Archive created at ${DEPLOY_DIR}/${ARCHIVE_FILENAME}${IMG_SUFFIX}.zip"
;;
gz)
pigz --force -"${COMPRESSION_LEVEL}" "${SQUASHFS_FILE}" --stdout > \
"${DEPLOY_DIR}/${ARCHIVE_FILENAME}${IMG_SUFFIX}.squashfs.gz"
[ -n "${VMLINUZ_FILE}" ] && cp "${VMLINUZ_FILE}" "${DEPLOY_DIR}/${ARCHIVE_FILENAME}${IMG_SUFFIX}.vmlinuz"
[ -n "${INITRD_FILE}" ] && cp "${INITRD_FILE}" "${DEPLOY_DIR}/${ARCHIVE_FILENAME}${IMG_SUFFIX}.initrd"
echo "Squashfs exported at ${DEPLOY_DIR}/${ARCHIVE_FILENAME}${IMG_SUFFIX}.squashfs.gz"
;;
xz)
xz --compress --force --threads 0 --memlimit-compress=50% -"${COMPRESSION_LEVEL}" \
--stdout "${SQUASHFS_FILE}" > "${DEPLOY_DIR}/${ARCHIVE_FILENAME}${IMG_SUFFIX}.squashfs.xz"
[ -n "${VMLINUZ_FILE}" ] && cp "${VMLINUZ_FILE}" "${DEPLOY_DIR}/${ARCHIVE_FILENAME}${IMG_SUFFIX}.vmlinuz"
[ -n "${INITRD_FILE}" ] && cp "${INITRD_FILE}" "${DEPLOY_DIR}/${ARCHIVE_FILENAME}${IMG_SUFFIX}.initrd"
echo "Squashfs exported at ${DEPLOY_DIR}/${ARCHIVE_FILENAME}${IMG_SUFFIX}.squashfs.xz"
;;
none | *)
cp "${SQUASHFS_FILE}" "${DEPLOY_DIR}/${ARCHIVE_FILENAME}${IMG_SUFFIX}.squashfs"
[ -n "${VMLINUZ_FILE}" ] && cp "${VMLINUZ_FILE}" "${DEPLOY_DIR}/${ARCHIVE_FILENAME}${IMG_SUFFIX}.vmlinuz"
[ -n "${INITRD_FILE}" ] && cp "${INITRD_FILE}" "${DEPLOY_DIR}/${ARCHIVE_FILENAME}${IMG_SUFFIX}.initrd"
echo "Squashfs exported at ${DEPLOY_DIR}/${ARCHIVE_FILENAME}${IMG_SUFFIX}.squashfs"
;;
esac
# ── 2. Liveboot squashfs (only when LIVEBOOT=1 and amd64) ──────────────────────
if [ "${LIVEBOOT}" == "1" ]; then
if [ "${ARCH}" != "amd64" ]; then
echo "squashfs-export: skipping live boot squashfs for non-amd64 arch (${ARCH})"
else
echo "squashfs-export: applying live boot changes for liveboot squashfs"
on_chroot << EOF
apt-get install -y \
live-boot \
live-boot-initramfs-tools \
live-config \
live-config-systemd
EOF
# Write live-config user settings
mkdir -p "${ROOTFS_DIR}/etc/live"
cat > "${ROOTFS_DIR}/etc/live/config.conf" << EOF
LIVE_USERNAME="${LIVE_USERNAME:-vesperos}"
LIVE_USER_FULLNAME="${LIVE_USER_FULLNAME:-Live User}"
LIVE_USER_DEFAULT_GROUPS="audio cdrom dip floppy video plugdev netdev bluetooth"
LIVE_USER_SHELL="/bin/zsh"
LIVE_USER_PASSWORD="${LIVE_USER_PASSWORD:-vesperos}"
LIVE_LOGIN="true"
EOF
# Rewrite fstab for the live environment.
# live-boot manages root via overlayfs — build-time disk entries cause fsck failures at boot.
cat > "${ROOTFS_DIR}/etc/fstab" << 'FSTABEOF'
# Live system fstab — root is managed by live-boot via overlayfs, not this file.
tmpfs /tmp tmpfs defaults,nosuid,nodev 0 0
FSTABEOF
# Remove first-boot trigger so GDM uses autologin in the live session.
rm -f "${ROOTFS_DIR}/var/lib/gdm/run-initial-setup"
# Make GDM wait for live-config
mkdir -p "${ROOTFS_DIR}/etc/systemd/system/gdm.service.d"
cat > "${ROOTFS_DIR}/etc/systemd/system/gdm.service.d/override.conf" << EOF
[Unit]
After=live-config.service
EOF
# Enable autoLogin on GDM
mkdir -p "${ROOTFS_DIR}/etc/gdm3"
cat > "${ROOTFS_DIR}/etc/gdm3/daemon.conf" << EOF
[daemon]
AutomaticLoginEnable=true
AutomaticLogin=${LIVE_USERNAME:-vesperos}
EOF
# Configure initramfs for live boot — squashfs and overlay are required
if [ -f "${ROOTFS_DIR}/etc/initramfs-tools/initramfs.conf" ]; then
sed -i 's/^MODULES=.*/MODULES=most/' "${ROOTFS_DIR}/etc/initramfs-tools/initramfs.conf"
fi
for mod in squashfs overlay; do
grep -qx "${mod}" "${ROOTFS_DIR}/etc/initramfs-tools/modules" 2>/dev/null || \
echo "${mod}" >> "${ROOTFS_DIR}/etc/initramfs-tools/modules"
done
# Enable live-config system wide, instead of via grub
on_chroot << EOF
systemctl enable live-config.service
EOF
# Live-only dconf: separate database + profile so the live wallpaper
# is shown in the live session but not on the real installed system.
FINALISE_DIR="$(dirname "$0")/../03-finalise"
mkdir -p "${ROOTFS_DIR}/etc/dconf/db/live.d"
install -m 644 "${FINALISE_DIR}/files/live-default-settings" "${ROOTFS_DIR}/etc/dconf/db/live.d/00-default-settings"
install -m 644 "${FINALISE_DIR}/files/dconf-profile-live-user" "${ROOTFS_DIR}/etc/dconf/profile/live"
# Hook sets DCONF_PROFILE=live for the live user at boot
install -m 755 "${FINALISE_DIR}/files/9999-vesperos-dconf" "${ROOTFS_DIR}/lib/live/config/9999-vesperos-dconf"
on_chroot << EOF
dconf update
EOF
# Add calamares installer and related packages to the live image
on_chroot << EOF
apt-get install -y calamares calamares-settings-vesperos \
libcrack2 cracklib-runtime \
grub-efi-amd64 grub-pc-bin efibootmgr \
parted gdisk dosfstools e2fsprogs
EOF
# Set quiet splash after grub installs its default /etc/default/grub
sed -i 's/^GRUB_CMDLINE_LINUX_DEFAULT=.*/GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"/' \
"${ROOTFS_DIR}/etc/default/grub"
# Keep the graphical framebuffer so Plymouth can render its splash.
# Without this, GRUB switches to text mode before handing off to the kernel
# and Plymouth falls back to a hidden/text renderer, showing nothing.
grep -q 'GRUB_GFXPAYLOAD_LINUX' "${ROOTFS_DIR}/etc/default/grub" || \
echo 'GRUB_GFXPAYLOAD_LINUX=keep' >> "${ROOTFS_DIR}/etc/default/grub"
# Rebuild initramfs with live-boot modules
on_chroot << EOF
update-initramfs -k all -u
EOF
LIVE_SQUASHFS_FILE="${STAGE_WORK_DIR}/${IMG_FILENAME}${IMG_SUFFIX}-live.squashfs"
unmount "${ROOTFS_DIR}"
mksquashfs "${ROOTFS_DIR}" "${LIVE_SQUASHFS_FILE}" \
-comp xz \
-noappend \
-e boot/efi
# Locate updated kernel/initrd for liveboot
LIVE_VMLINUZ=$(find "${ROOTFS_DIR}/boot" -maxdepth 1 -name "vmlinuz-*" | sort | tail -1)
LIVE_INITRD=$(find "${ROOTFS_DIR}/boot" -maxdepth 1 -name "initrd.img-*" | sort | tail -1)
case "${DEPLOY_COMPRESSION}" in
zip)
pushd "${STAGE_WORK_DIR}" > /dev/null
LIVE_ZIP_MEMBERS="$(basename "${LIVE_SQUASHFS_FILE}")"
# shellcheck disable=SC2086
zip -"${COMPRESSION_LEVEL}" \
"${DEPLOY_DIR}/${ARCHIVE_FILENAME}${IMG_SUFFIX}-live.zip" \
${LIVE_ZIP_MEMBERS}
popd > /dev/null
echo "Live archive created at ${DEPLOY_DIR}/${ARCHIVE_FILENAME}${IMG_SUFFIX}-live.zip"
;;
gz)
pigz --force -"${COMPRESSION_LEVEL}" "${LIVE_SQUASHFS_FILE}" --stdout > \
"${DEPLOY_DIR}/${ARCHIVE_FILENAME}${IMG_SUFFIX}-live.squashfs.gz"
echo "Live squashfs exported at ${DEPLOY_DIR}/${ARCHIVE_FILENAME}${IMG_SUFFIX}-live.squashfs.gz"
;;
xz)
xz --compress --force --threads 0 --memlimit-compress=50% -"${COMPRESSION_LEVEL}" \
--stdout "${LIVE_SQUASHFS_FILE}" > "${DEPLOY_DIR}/${ARCHIVE_FILENAME}${IMG_SUFFIX}-live.squashfs.xz"
echo "Live squashfs exported at ${DEPLOY_DIR}/${ARCHIVE_FILENAME}${IMG_SUFFIX}-live.squashfs.xz"
;;
none | *)
cp "${LIVE_SQUASHFS_FILE}" "${DEPLOY_DIR}/${ARCHIVE_FILENAME}${IMG_SUFFIX}-live.squashfs"
echo "Live squashfs exported at ${DEPLOY_DIR}/${ARCHIVE_FILENAME}${IMG_SUFFIX}-live.squashfs"
;;
esac
[ -n "${LIVE_VMLINUZ}" ] && cp "${LIVE_VMLINUZ}" "${DEPLOY_DIR}/${ARCHIVE_FILENAME}${IMG_SUFFIX}-live.vmlinuz"
[ -n "${LIVE_INITRD}" ] && cp "${LIVE_INITRD}" "${DEPLOY_DIR}/${ARCHIVE_FILENAME}${IMG_SUFFIX}-live.initrd"
fi
fi
# Cleanup
#rm -f "${SQUASHFS_FILE}"
#[ -n "${VMLINUZ_FILE}" ] && rm -f "${VMLINUZ_FILE}"
#[ -n "${INITRD_FILE}" ] && rm -f "${INITRD_FILE}"
# cleanup stage work dir
#rm -rf "${STAGE_WORK_DIR}"

6
exports/squashfs/prerun.sh Executable file
View File

@@ -0,0 +1,6 @@
#!/bin/bash -e
rm -rf "${ROOTFS_DIR}"
mkdir -p "${ROOTFS_DIR}"
rsync -aHAXx --exclude /var/cache/apt/archives "${EXPORT_ROOTFS_DIR}/" "${ROOTFS_DIR}/"

View File

@@ -17,7 +17,10 @@ bootstrap(){
BOOTSTRAP_ARGS+=("$@")
printf -v BOOTSTRAP_STR '%q ' "${BOOTSTRAP_ARGS[@]}"
capsh $CAPSH_ARG -- -c "'${BOOTSTRAP_CMD}' $BOOTSTRAP_STR" || true
setarch linux32 capsh $CAPSH_ARG -- -c "'${BOOTSTRAP_CMD}' $BOOTSTRAP_STR" || true
# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1050719
rm -f wget-log*
if [ -d "$2/debootstrap" ] && ! rmdir "$2/debootstrap"; then
cp "$2/debootstrap/debootstrap.log" "${STAGE_WORK_DIR}"
@@ -131,4 +134,4 @@ ensure_loopdev_partitions() {
command -v udevadm >/dev/null 2>&1 || return 0
udevadm settle 10
}
export -f ensure_loopdev_partitions
export -f ensure_loopdev_partitions

View File

@@ -1,16 +1,26 @@
#!/bin/bash -e
# Configure apt sources
install -m 644 files/sources.list "${ROOTFS_DIR}/etc/apt/"
sed -i "s/RELEASE/${RELEASE}/g" "${ROOTFS_DIR}/etc/apt/sources.list"
true > "${ROOTFS_DIR}/etc/apt/sources.list"
if [[ "${ARCH}" == "arm64" || "${ARCH}" == "armhf" ]]; then
install -m 644 files/raspi.list "${ROOTFS_DIR}/etc/apt/sources.list.d/"
sed -i "s/RELEASE/${RELEASE}/g" "${ROOTFS_DIR}/etc/apt/sources.list.d/raspi.list"
# Add APT Sources
if [ "${PLATFORM}" == "rpi" ]; then
# On rpi platforms add rpi sources
install -m 644 files/raspbian.sources "${ROOTFS_DIR}/etc/apt/sources.list.d/"
install -m 644 files/raspi.sources "${ROOTFS_DIR}/etc/apt/sources.list.d/"
sed -i "s/RELEASE/${RELEASE}/g" "${ROOTFS_DIR}/etc/apt/sources.list.d/raspbian.sources"
sed -i "s/RELEASE/${RELEASE}/g" "${ROOTFS_DIR}/etc/apt/sources.list.d/raspi.sources"
install -m 644 files/raspberrypi-archive-keyring.pgp "${ROOTFS_DIR}/usr/share/keyrings/"
fi
install -m 644 files/oxmc.list "${ROOTFS_DIR}/etc/apt/sources.list.d/"
sed -i "s/RELEASE/${RELEASE}/g" "${ROOTFS_DIR}/etc/apt/sources.list.d/oxmc.list"
# Add default debian sources until oxmc creates a mirror for debian sources
install -m 644 files/debian.sources "${ROOTFS_DIR}/etc/apt/sources.list.d/"
sed -i "s/RELEASE/${RELEASE}/g" "${ROOTFS_DIR}/etc/apt/sources.list.d/debian.sources"
# Configure vesperos apt sources
install -m 644 files/vesperos.sources "${ROOTFS_DIR}/etc/apt/sources.list.d/"
sed -i "s/RELEASE/${RELEASE}/g" "${ROOTFS_DIR}/etc/apt/sources.list.d/vesperos.sources"
install -m 644 files/vesperos.gpg "${ROOTFS_DIR}/usr/share/keyrings/"
# Configure apt proxy
if [ -n "$APT_PROXY" ]; then
@@ -20,6 +30,7 @@ else
rm -f "${ROOTFS_DIR}/etc/apt/apt.conf.d/51cache"
fi
# Add temp repo if provided
if [ -n "$TEMP_REPO" ]; then
install -m 644 /dev/null "${ROOTFS_DIR}/etc/apt/sources.list.d/00-temp.list"
echo "$TEMP_REPO" | sed "s/RELEASE/$RELEASE/g" > "${ROOTFS_DIR}/etc/apt/sources.list.d/00-temp.list"
@@ -28,26 +39,30 @@ else
fi
# Configure apt preferences
install -m 644 files/apt-chillcraftos-prefs "${ROOTFS_DIR}/etc/apt/preferences.d/"
install -m 644 files/apt-vesperos-prefs "${ROOTFS_DIR}/etc/apt/preferences.d/"
sed -i "s/RELEASE/${RELEASE}/g" "${ROOTFS_DIR}/etc/apt/preferences.d/apt-vesperos-prefs"
if [[ "${ARCH}" == "arm64" || "${ARCH}" == "armhf" ]]; then
# Add raspberrypi-archive-keyring to apt
cat files/raspberrypi.gpg.key | gpg --dearmor > "${STAGE_WORK_DIR}/raspberrypi-archive-stable.gpg"
install -m 644 "${STAGE_WORK_DIR}/raspberrypi-archive-stable.gpg" "${ROOTFS_DIR}/etc/apt/trusted.gpg.d/"
fi
# Add oxmc-archive-keyring to apt
cat files/oxmc.gpg.key | gpg --dearmor > "${STAGE_WORK_DIR}/oxmc.gpg"
install -m 644 "${STAGE_WORK_DIR}/oxmc.gpg" "${ROOTFS_DIR}/etc/apt/trusted.gpg.d/"
# Add armhf and arm64 architectures, update and upgrade and cache policy
# Add additional architectures if needed, update and upgrade and cache policy
on_chroot <<- \EOF
SYSTEM_ARCH="$(dpkg --print-architecture)"
if [ "$SYSTEM_ARCH" = "armhf" ]; then
dpkg --add-architecture arm64
elif [ "$SYSTEM_ARCH" = "arm64" ]; then
dpkg --add-architecture armhf
# If we're building for rpi, we want to add both armhf and arm64 architectures to allow installing packages from both architectures
if [ "${PLATFORM}" == "rpi" ]; then
if [ "$SYSTEM_ARCH" = "armhf" ]; then
dpkg --add-architecture arm64
elif [ "$SYSTEM_ARCH" = "arm64" ]; then
dpkg --add-architecture armhf
fi
fi
# If we're building for amd64, we want to add i386 architecture to allow installing packages from both architectures
if [ "$SYSTEM_ARCH" = "amd64" ]; then
dpkg --add-architecture i386
elif [ "$SYSTEM_ARCH" = "i386" ]; then
dpkg --add-architecture amd64
fi
# Update and upgrade packages and show cache policy
apt-get update
apt-get dist-upgrade -y
apt-cache policy

View File

@@ -1 +1 @@
raspberrypi-archive-keyring
tailscale-repo

View File

@@ -0,0 +1 @@
raspberrypi-archive-keyring

View File

@@ -1,3 +0,0 @@
Package: *
Pin: release o=apt.oxmc.me, n=bookworm
Pin-Priority: 1001

View File

@@ -0,0 +1,3 @@
Package: *
Pin: release o=apt.oxmc.me, n=RELEASE
Pin-Priority: 1001

View File

@@ -0,0 +1,11 @@
Types: deb
URIs: https://deb.debian.org/debian
Suites: RELEASE RELEASE-updates
Components: main contrib non-free non-free-firmware
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
Types: deb
URIs: https://security.debian.org/debian-security
Suites: RELEASE-security
Components: main contrib non-free non-free-firmware
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg

View File

@@ -1,3 +0,0 @@
deb https://cdn.oxmc.me/apt RELEASE main
# Uncomment line below then 'apt-get update' to enable 'apt-get source'
#deb-src https://cdn.oxmc.me/apt RELEASE main

View File

@@ -1,30 +0,0 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.4.12 (GNU/Linux)
mQENBE/d7o8BCACrwqQacGJfn3tnMzGui6mv2lLxYbsOuy/+U4rqMmGEuo3h9m92
30E2EtypsoWczkBretzLUCFv+VUOxaA6sV9+puTqYGhhQZFuKUWcG7orf7QbZRuu
TxsEUepW5lg7MExmAu1JJzqM0kMQX8fVyWVDkjchZ/is4q3BPOUCJbUJOsE+kK/6
8kW6nWdhwSAjfDh06bA5wvoXNjYoDdnSZyVdcYCPEJXEg5jfF/+nmiFKMZBraHwn
eQsepr7rBXxNcEvDlSOPal11fg90KXpy7Umre1UcAZYJdQeWcHu7X5uoJx/MG5J8
ic6CwYmDaShIFa92f8qmFcna05+lppk76fsnABEBAAG0IFJhc3BiZXJyeSBQaSBB
cmNoaXZlIFNpZ25pbmcgS2V5iQE4BBMBAgAiBQJP3e6PAhsDBgsJCAcDAgYVCAIJ
CgsEFgIDAQIeAQIXgAAKCRCCsSmSf6MwPk6vB/9pePB3IukU9WC9Bammh3mpQTvL
OifbkzHkmAYxzjfK6D2I8pT0xMxy949+ThzJ7uL60p6T/32ED9DR3LHIMXZvKtuc
mQnSiNDX03E2p7lIP/htoxW2hDP2n8cdlNdt0M9IjaWBppsbO7IrDppG2B1aRLni
uD7v8bHRL2mKTtIDLX42Enl8aLAkJYgNWpZyPkDyOqamjijarIWjGEPCkaURF7g4
d44HvYhpbLMOrz1m6N5Bzoa5+nq3lmifeiWKxioFXU+Hy5bhtAM6ljVb59hbD2ra
X4+3LXC9oox2flmQnyqwoyfZqVgSQa0B41qEQo8t1bz6Q1Ti7fbMLThmbRHiuQEN
BE/d7o8BCADNlVtBZU63fm79SjHh5AEKFs0C3kwa0mOhp9oas/haDggmhiXdzeD3
49JWz9ZTx+vlTq0s+I+nIR1a+q+GL+hxYt4HhxoA6vlDMegVfvZKzqTX9Nr2VqQa
S4Kz3W5ULv81tw3WowK6i0L7pqDmvDqgm73mMbbxfHD0SyTt8+fk7qX6Ag2pZ4a9
ZdJGxvASkh0McGpbYJhk1WYD+eh4fqH3IaeJi6xtNoRdc5YXuzILnp+KaJyPE5CR
qUY5JibOD3qR7zDjP0ueP93jLqmoKltCdN5+yYEExtSwz5lXniiYOJp8LWFCgv5h
m8aYXkcJS1xVV9Ltno23YvX5edw9QY4hABEBAAGJAR8EGAECAAkFAk/d7o8CGwwA
CgkQgrEpkn+jMD5Figf/dIC1qtDMTbu5IsI5uZPX63xydaExQNYf98cq5H2fWF6O
yVR7ERzA2w33hI0yZQrqO6pU9SRnHRxCFvGv6y+mXXXMRcmjZG7GiD6tQWeN/3wb
EbAn5cg6CJ/Lk/BI4iRRfBX07LbYULCohlGkwBOkRo10T+Ld4vCCnBftCh5x2OtZ
TOWRULxP36y2PLGVNF+q9pho98qx+RIxvpofQM/842ZycjPJvzgVQsW4LT91KYAE
4TVf6JjwUM6HZDoiNcX6d7zOhNfQihXTsniZZ6rky287htsWVDNkqOi5T3oTxWUo
m++/7s3K3L0zWopdhMVcgg6Nt9gcjzqN1c0gy55L/g==
=mNSj
-----END PGP PUBLIC KEY BLOCK-----

View File

@@ -0,0 +1,8 @@
Types: deb
URIs: http://raspbian.raspberrypi.com/raspbian/
Architectures: armhf
Suites: RELEASE
Components: main contrib non-free rpi
Signed-By: /usr/share/keyrings/raspbian-archive-keyring.pgp
# TODO: Remove Trusted once Raspbian reissues their key with SHA256+ (SHA1 rejected by sqv since 2026-02-01)
Trusted: yes

View File

@@ -1,3 +0,0 @@
deb http://archive.raspberrypi.com/debian/ RELEASE main
# Uncomment line below then 'apt-get update' to enable 'apt-get source'
#deb-src http://archive.raspberrypi.com/debian/ RELEASE main

View File

@@ -0,0 +1,5 @@
Types: deb
URIs: http://archive.raspberrypi.com/debian/
Suites: RELEASE
Components: main
Signed-By: /usr/share/keyrings/raspberrypi-archive-keyring.pgp

View File

@@ -1,7 +0,0 @@
deb http://deb.debian.org/debian RELEASE main contrib non-free non-free-firmware
deb http://deb.debian.org/debian-security/ RELEASE-security main contrib non-free non-free-firmware
deb http://deb.debian.org/debian RELEASE-updates main contrib non-free non-free-firmware
# Uncomment deb-src lines below then 'apt-get update' to enable 'apt-get source'
#deb-src http://deb.debian.org/debian RELEASE main contrib non-free non-free-firmware
#deb-src http://deb.debian.org/debian-security/ RELEASE-security main contrib non-free non-free-firmware
#deb-src http://deb.debian.org/debian RELEASE-updates main contrib non-free non-free-firmware

View File

@@ -0,0 +1,5 @@
Types: deb
URIs: https://apt.oxmc.me/vesperos
Suites: RELEASE
Components: main
Signed-By: /usr/share/keyrings/vesperos.gpg

0
stage0/01-locale/00-run.sh Normal file → Executable file
View File

View File

@@ -1 +1 @@
grub2
linux-image-amd64

View File

@@ -1 +1 @@
console=serial0,115200 console=tty1 root=ROOTDEV rootfstype=ext4 fsck.repair=yes rootwait
console=serial0,115200 console=tty1 root=ROOTDEV rootfstype=ext4 fsck.repair=yes rootwait resize

View File

@@ -1,6 +1,6 @@
--- a/rootfs/etc/skel/.bashrc
+++ b/rootfs/etc/skel/.bashrc
@@ -43,7 +43,7 @@
--- stage1.orig/rootfs/etc/skel/.bashrc
+++ stage1/rootfs/etc/skel/.bashrc
@@ -43,7 +43,7 @@ esac
# uncomment for a colored prompt, if the terminal has the capability; turned
# off by default to not distract the user: the focus in a terminal window
# should be on the output of commands, not on the prompt
@@ -9,7 +9,7 @@
if [ -n "$force_color_prompt" ]; then
if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
@@ -57,7 +57,7 @@
@@ -57,7 +57,7 @@ if [ -n "$force_color_prompt" ]; then
fi
if [ "$color_prompt" = yes ]; then
@@ -18,7 +18,7 @@
else
PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
fi
@@ -79,9 +79,9 @@
@@ -79,9 +79,9 @@ if [ -x /usr/bin/dircolors ]; then
#alias dir='dir --color=auto'
#alias vdir='vdir --color=auto'

View File

@@ -1,18 +1,15 @@
#!/bin/bash -e
install -v -m 644 files/fstab "${ROOTFS_DIR}/etc/fstab"
# SteamOS like readonly root
install -m 755 files/system-readonly "${ROOTFS_DIR}/sbin/"
on_chroot << EOF
if ! id -u ${FIRST_USER_NAME} >/dev/null 2>&1; then
#adduser --disabled-password --gecos "" ${FIRST_USER_NAME}
if [ "${FIRST_USER_ISSYSTEM}" = "true" ]; then
useradd -r -M -d / ${FIRST_USER_NAME}
else
adduser --disabled-password --gecos "" ${FIRST_USER_NAME}
fi
if [ "${PLATFORM}" == "rpi" ]; then
install -m 644 files/fstab-rpi "${ROOTFS_DIR}/etc/fstab"
else
install -m 644 files/fstab "${ROOTFS_DIR}/etc/fstab"
fi
# Create system user and set root password
on_chroot << EOF
useradd -r -M -d / system
echo "root:root" | chpasswd
EOF
EOF

View File

@@ -1,3 +1,7 @@
proc /proc proc defaults 0 0
BOOTDEV /boot/firmware vfat defaults 0 2
ROOTDEV / ext4 defaults,noatime 0 1
proc /proc proc defaults 0 0
BOOTDEV /boot vfat defaults 0 2
EFIDEV /boot/efi vfat defaults 0 2
ROOTDEV / btrfs defaults,noatime,compress=zstd,subvol=@ 0 1
ROOTDEV /home btrfs defaults,noatime,compress=zstd,subvol=@home 0 2
ROOTDEV /var btrfs defaults,noatime,compress=zstd,subvol=@var 0 2
ROOTDEV /.snapshots btrfs defaults,noatime,compress=zstd,subvol=@snapshots 0 2

View File

@@ -0,0 +1,6 @@
proc /proc proc defaults 0 0
BOOTDEV /boot/firmware vfat defaults 0 2
ROOTDEV / btrfs defaults,noatime,compress=zstd,subvol=@ 0 1
ROOTDEV /home btrfs defaults,noatime,compress=zstd,subvol=@home 0 2
ROOTDEV /var btrfs defaults,noatime,compress=zstd,subvol=@var 0 2
ROOTDEV /.snapshots btrfs defaults,noatime,compress=zstd,subvol=@snapshots 0 2

View File

@@ -1,30 +1,36 @@
#!/bin/bash
FSTAB_FILE="/etc/fstab"
set -e
if [ "$1" == "enable" ]; then
echo "Enabling read-only mode..."
SUBVOL="/"
# Modify fstab to set root filesystem as read-only
sudo sed -i 's|\(PARTUUID=[^ ]* / .* ext4 \)defaults,noatime|\1ro,noatime|' "$FSTAB_FILE"
# Remount root as read-only
sudo mount -o remount,ro /
echo "System is now read-only. Reboot for changes to persist."
elif [ "$1" == "disable" ]; then
echo "Disabling read-only mode..."
# Modify fstab to set root filesystem as writable
sudo sed -i 's|\(PARTUUID=[^ ]* / .* ext4 \)ro,noatime|\1defaults,noatime|' "$FSTAB_FILE"
# Remount root as writable
sudo mount -o remount,rw /
echo "System is now writable. Reboot for changes to persist."
else
echo "Usage: system-readonly enable|disable"
usage() {
echo "Usage: system-readonly enable|disable|status"
exit 1
fi
}
case "$1" in
enable)
echo "Enabling read-only mode..."
btrfs property set -ts "${SUBVOL}" ro true
mount -o remount,ro "${SUBVOL}"
echo "Root is read-only. Full effect on next reboot."
;;
disable)
echo "Disabling read-only mode..."
btrfs property set -ts "${SUBVOL}" ro false
mount -o remount,rw "${SUBVOL}"
echo "Root is writable."
;;
status)
RO=$(btrfs property get -ts "${SUBVOL}" ro 2>/dev/null | awk -F= '{print $2}')
if [ "${RO}" = "true" ]; then
echo "Read-only: enabled"
else
echo "Read-only: disabled"
fi
;;
*)
usage
;;
esac

View File

@@ -1,5 +0,0 @@
#!/bin/bash -e
on_chroot << EOF
SUDO_USER="${FIRST_USER_NAME}" raspi-config nonint do_net_names 1
EOF

View File

@@ -0,0 +1,5 @@
#!/bin/bash -e
on_chroot << EOF
raspi-config nonint do_net_names 1
EOF

View File

@@ -1,12 +1,6 @@
# Encoding to use on the console:
# Choices: ARMSCII-8, CP1251, CP1255, CP1256, GEORGIAN-ACADEMY, GEORGIAN-PS, IBM1133, ISIRI-3342, ISO-8859-1, ISO-8859-10, ISO-8859-11, ISO-8859-13, ISO-8859-14, ISO-8859-15, ISO-8859-16, ISO-8859-2, ISO-8859-3, ISO-8859-4, ISO-8859-5, ISO-8859-6, ISO-8859-7, ISO-8859-8, ISO-8859-9, KOI8-R, KOI8-U, TIS-620, UTF-8, VISCII
console-setup console-setup/charmap47 select UTF-8
# Character set to support:
# Choices: . Arabic, # Armenian, # Cyrillic - KOI8-R and KOI8-U, # Cyrillic - non-Slavic languages, # Cyrillic - Slavic languages (also Bosnian and Serbian Latin), . Ethiopic, # Georgian, # Greek, # Hebrew, # Lao, # Latin1 and Latin5 - western Europe and Turkic languages, # Latin2 - central Europe and Romanian, # Latin3 and Latin8 - Chichewa; Esperanto; Irish; Maltese and Welsh, # Latin7 - Lithuanian; Latvian; Maori and Marshallese, . Latin - Vietnamese, # Thai, . Combined - Latin; Slavic Cyrillic; Hebrew; basic Arabic, . Combined - Latin; Slavic Cyrillic; Greek, . Combined - Latin; Slavic and non-Slavic Cyrillic, Guess optimal character set
console-setup console-setup/codeset47 select Guess optimal character set
# Font for the console:
# Choices: Fixed, Goha, GohaClassic, Terminus, TerminusBold, TerminusBoldVGA, VGA, Do not change the boot/kernel font, Let the system select a suitable font
console-setup console-setup/fontface47 select Do not change the boot/kernel font
# Key to function as AltGr:
# Choices: The default for the keyboard layout, No AltGr key, Right Alt (AltGr), Right Control, Right Logo key, Menu key, Left Alt, Left Logo key, Keypad Enter key, Both Logo keys, Both Alt keys
keyboard-configuration keyboard-configuration/altgr select The default for the keyboard layout
@@ -25,4 +19,4 @@ keyboard-configuration keyboard-configuration/ctrl_alt_bksp boolean true
# Choices: English (UK), English (UK) - English (UK\, Colemak), English (UK) - English (UK\, Dvorak with UK punctuation), English (UK) - English (UK\, Dvorak), English (UK) - English (UK\, Macintosh international), English (UK) - English (UK\, Macintosh), English (UK) - English (UK\, extended WinKeys), English (UK) - English (UK\, international with dead keys), Other
keyboard-configuration keyboard-configuration/variant select ${KEYBOARD_LAYOUT}
# for internal use
keyboard-configuration keyboard-configuration/optionscode string PLACEHOLDER
keyboard-configuration keyboard-configuration/optionscode string PLACEHOLDER

View File

@@ -1,26 +1,24 @@
ssh less fbset sudo psmisc strace ed ncdu
ssh fbset sudo psmisc strace ed ncdu zsh zsh-common
console-setup keyboard-configuration debconf-utils parted
build-essential manpages-dev bash-completion gdb pkg-config
btrfs-progs
snapper
python-is-python3
v4l-utils
python3-spidev
python3-smbus2
avahi-daemon
bluez bluez-firmware
lua5.1
luajit
ca-certificates curl
fake-hwclock nfs-common usbutils
curl
usbutils
dosfstools
dphys-swapfile
apt-listchanges
apt-file
usb-modeswitch
libpam-chksshpwd
libmtp-runtime
rsync
htop
man-db
policykit-1
ssh-import-id
ethtool
ntfs-3g
@@ -28,5 +26,6 @@ pciutils
udisks2
unzip zip p7zip-full
file
kms++-utils
python3-venv
cups
command-not-found

View File

@@ -0,0 +1,2 @@
qemu-guest-agent
open-vm-tools

View File

@@ -1,2 +1,4 @@
cifs-utils
mkvtoolnix
hyfetch
fastfetch

View File

@@ -0,0 +1,2 @@
python3-spidev
python3-smbus2

View File

@@ -0,0 +1,10 @@
--- stage2.orig/rootfs/etc/inputrc
+++ stage2/rootfs/etc/inputrc
@@ -59,3 +59,7 @@
# "\e[F": end-of-line
$endif
+
+# mappings for up and down arrows search history
+# "\e[B": history-search-forward
+# "\e[A": history-search-backward

View File

@@ -0,0 +1 @@
02-inputrc.diff

View File

@@ -1,5 +0,0 @@
--- stage2.orig/rootfs/boot/firmware/cmdline.txt
+++ stage2/rootfs/boot/firmware/cmdline.txt
@@ -1 +1 @@
-console=serial0,115200 console=tty1 root=ROOTDEV rootfstype=ext4 fsck.repair=yes rootwait
+console=serial0,115200 console=tty1 root=ROOTDEV rootfstype=ext4 fsck.repair=yes rootwait quiet init=/usr/lib/raspberrypi-sys-mods/firstboot

View File

@@ -1 +0,0 @@
01-resize-init.diff

View File

@@ -0,0 +1,10 @@
--- stage2.orig/rootfs/etc/inputrc
+++ stage2/rootfs/etc/inputrc
@@ -69,3 +69,7 @@ $endif
# "\e[F": end-of-line
$endif
+
+# mappings for up and down arrows search history
+# "\e[B": history-search-forward
+# "\e[A": history-search-backward

View File

@@ -0,0 +1 @@
01-inputrc.diff

View File

@@ -0,0 +1,4 @@
#!/bin/bash -e
# Set the default shell to zsh in the adduser configuration, so that new users created with adduser (including the live session user) will have zsh as their default shell.
sed -i 's|^DSHELL=.*|DSHELL=/bin/zsh|' "${ROOTFS_DIR}/etc/adduser.conf"

View File

@@ -1,13 +1,11 @@
Index: jessie-stage2/rootfs/etc/default/useradd
===================================================================
--- jessie-stage2.orig/rootfs/etc/default/useradd
+++ jessie-stage2/rootfs/etc/default/useradd
--- stage2.orig/rootfs/etc/default/useradd
+++ stage2/rootfs/etc/default/useradd
@@ -5,7 +5,7 @@
# Similar to DHSELL in adduser. However, we use "sh" here because
# Similar to DSHELL in adduser. However, we use "sh" here because
# useradd is a low level utility and should be as general
# as possible
-SHELL=/bin/sh
+SHELL=/bin/bash
+SHELL=/bin/zsh
#
# The default group for users
# 100=users on Debian systems

View File

@@ -1,13 +0,0 @@
Index: jessie-stage2/rootfs/etc/dphys-swapfile
===================================================================
--- jessie-stage2.orig/rootfs/etc/dphys-swapfile
+++ jessie-stage2/rootfs/etc/dphys-swapfile
@@ -13,7 +13,7 @@
# set size to absolute value, leaving empty (default) then uses computed value
# you most likely don't want this, unless you have an special disk situation
-#CONF_SWAPSIZE=
+CONF_SWAPSIZE=512
# set size to computed value, this times RAM size, dynamically adapts,
# guarantees that there is enough swap without wasting disk space on excess

View File

@@ -1,12 +0,0 @@
Index: jessie-stage2/rootfs/etc/inputrc
===================================================================
--- jessie-stage2.orig/rootfs/etc/inputrc
+++ jessie-stage2/rootfs/etc/inputrc
@@ -65,3 +65,7 @@ $endif
# "\e[F": end-of-line
$endif
+
+# mappings for up and down arrows search history
+# "\e[B": history-search-forward
+# "\e[A": history-search-backward

View File

@@ -0,0 +1,21 @@
--- stage2.orig/rootfs/etc/login.defs
+++ stage2/rootfs/etc/login.defs
@@ -60,7 +60,7 @@ HUSHLOGIN_FILE .hushlogin
#
# (they are minimal, add the rest in the shell startup files)
ENV_SUPATH PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
-ENV_PATH PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
+ENV_PATH PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games
#
# Terminal permissions for terminals after login(1).
--- stage2.orig/rootfs/etc/profile
+++ stage2/rootfs/etc/profile
@@ -4,7 +4,7 @@
if [ "$(id -u)" -eq 0 ]; then
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
else
- PATH="/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games"
+ PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games"
fi
export PATH

View File

@@ -1,26 +0,0 @@
Index: jessie-stage2/rootfs/etc/login.defs
===================================================================
--- jessie-stage2.orig/rootfs/etc/login.defs
+++ jessie-stage2/rootfs/etc/login.defs
@@ -100,7 +100,7 @@ HUSHLOGIN_FILE .hushlogin
#
# (they are minimal, add the rest in the shell startup files)
ENV_SUPATH PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
-ENV_PATH PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
+ENV_PATH PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games
#
# Terminal permissions
Index: jessie-stage2/rootfs/etc/profile
===================================================================
--- jessie-stage2.orig/rootfs/etc/profile
+++ jessie-stage2/rootfs/etc/profile
@@ -4,7 +4,7 @@
if [ "`id -u`" -eq 0 ]; then
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
else
- PATH="/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games"
+ PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games"
fi
export PATH

View File

@@ -1,4 +1,2 @@
01-useradd.diff
02-swap.diff
03-inputrc.diff
04-path.diff
03-path.diff

View File

@@ -1,5 +0,0 @@
raspberrypi-sys-mods
pi-bluetooth
rpi-update
rpi-eeprom
raspi-utils

View File

@@ -0,0 +1,12 @@
raspberrypi-sys-mods
rpi-update
rpi-eeprom
raspi-utils
rpi-swap rpi-loop-utils
gpiod python3-libgpiod
python3-gpiozero
python3-rpi-lgpio
rpi-keyboard-config
rpi-keyboard-fw-update
rpi-usb-gadget
kms++-utils

Some files were not shown because too many files have changed in this diff Show More