Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
207 changes: 178 additions & 29 deletions debian-rk3576-img.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@ actions:
options: [ compress=zstd, noatime, ssd, discard=async, x-systemd.growfs ]

# Subvolume layout (no reformat). /boot is a TOP-LEVEL subvolume named "boot"
# (not "@boot") so it sits outside @ -> a single shared /boot that root snapshots
# never capture, and so U-Boot, which reads the default (top-level) subvolume,
# resolves /boot/extlinux/... straight into it. Keep the default subvolume as the
# top level (do NOT set-default @) or U-Boot won't see this sibling /boot.
# (not "@boot") so it sits outside the per-profile root subvolumes -> a single shared
# /boot that root snapshots never capture, and so U-Boot, which reads the default
# (top-level) subvolume, resolves /boot/extlinux/... straight into it. Keep the default
# subvolume as the top level (do NOT set a default subvolume) or U-Boot won't see /boot.
- action: run
description: Create subvolumes and mount the layout
chroot: false
Expand All @@ -51,16 +51,16 @@ actions:
ROOTPART="$({{ $rootdev }})"

# debos has the top level (subvolid=5) mounted here; create subvolumes on it.
for sv in @ boot @home @snapshots @var-log @var-cache; do
# @Minimal is the common base / build target; @snapshots holds runtime snapshots.
for sv in @Minimal boot @home @snapshots @var-log @var-cache; do
btrfs subvolume create "$IMAGEMNTDIR/$sv"
done
umount "$IMAGEMNTDIR"

# Mount @ at the mount point debos owns, then nest the rest under it.
mount -t btrfs -o "{{ $btrfsopts }},subvol=@" "$ROOTPART" "$IMAGEMNTDIR"
# Mount @Minimal at the mount point debos owns, then nest the rest under it.
mount -t btrfs -o "{{ $btrfsopts }},subvol=@Minimal" "$ROOTPART" "$IMAGEMNTDIR"
mkdir -p "$IMAGEMNTDIR/boot" \
"$IMAGEMNTDIR/home" \
"$IMAGEMNTDIR/.snapshots" \
"$IMAGEMNTDIR/var/log" \
"$IMAGEMNTDIR/var/cache"
mount -t btrfs -o "{{ $btrfsopts }},subvol=boot" "$ROOTPART" "$IMAGEMNTDIR/boot"
Expand All @@ -69,21 +69,20 @@ actions:
# stored on the subvolume and inherited by files added later (kernel updates).
btrfs property set "$IMAGEMNTDIR/boot" compression none
mount -t btrfs -o "{{ $btrfsopts }},subvol=@home" "$ROOTPART" "$IMAGEMNTDIR/home"
# @snapshots is mounted only for the build (to write the Factory Image); it's
# not in fstab, so the .snapshots mountpoint is removed from @ before detach.
mount -t btrfs -o "{{ $btrfsopts }},subvol=@snapshots" "$ROOTPART" "$IMAGEMNTDIR/.snapshots"
mount -t btrfs -o "{{ $btrfsopts }},subvol=@var-log" "$ROOTPART" "$IMAGEMNTDIR/var/log"
mount -t btrfs -o "{{ $btrfsopts }},subvol=@var-cache" "$ROOTPART" "$IMAGEMNTDIR/var/cache"

# debos writes the standard root line into /etc/fstab and root=UUID into the
# cmdline; the root subvolume is selected by the appended rootflags=subvol=@.
# debos writes the standard root line into /etc/fstab and root=UUID into the cmdline;
# the root subvolume is selected by the appended rootflags. @Desktop is the default root
# (the desktop); the other profiles' BLS entries append rootflags=subvol=@<profile>
# and the last rootflags= on the line wins. (Deploy still happens into @Minimal.)
- action: filesystem-deploy
append-kernel-cmdline: rootflags=subvol=@ {{ $cmdline }}
append-kernel-cmdline: rootflags=subvol=@Desktop {{ $cmdline }}

# Add fstab entries for the non-root subvolumes (debos only generated the root
# line). The FSUUID is read back at build time. @snapshots is intentionally
# omitted -- it holds the Factory Image and is mounted on demand for rollback,
# never auto-mounted at runtime.
# line). The FSUUID is read back at build time. These (/boot, /home, /var/log,
# /var/cache) are shared by every profile root. @snapshots is intentionally omitted
# -- it holds runtime snapshots, managed on demand, never auto-mounted.
- action: run
description: Append subvolume entries to /etc/fstab
chroot: false
Expand Down Expand Up @@ -120,25 +119,175 @@ actions:
chroot: true
command: find /var/cache/linux-kernel -name linux-image-\*.deb -a ! -name \*-dbg_\* -print0 | xargs -0 apt install -y

# Read-only "Factory Image" snapshot of @, taken once the rootfs and kernel are
# fully deployed. It captures @ only -- the nested subvols (boot/home/var-*) are
# separate and excluded.
# Default session for every profile: the no-DE multi-user target, where the cog-seat1
# kiosk runs (and @TV's kodi, enabled under multi-user). Only @Desktop overrides this to
# graphical.target (for sddm); @Minimal/@Router/@TV all stay on multi-user.
- action: run
description: Create the read-only Factory Image snapshot of @
chroot: false
command: btrfs subvolume snapshot -r "$IMAGEMNTDIR" "$IMAGEMNTDIR/.snapshots/@_Factory-Image"
description: Set the default boot target to multi-user (only @Desktop overrides)
chroot: true
command: systemctl set-default multi-user.target

# ===========================================================================
# Stock (RO) bases + per-profile bootable roots.
#
# @Minimal_stock is the RO golden image of the common base. Each profile is a
# WRITABLE snapshot of it (COW: shares the base, only profile packages add new extents),
# mounted at $IMAGEMNTDIR so standard debos `apt`/`overlay` actions install into it;
# it is then locked RO and the writable @<profile> bootable root is snapshotted from it.
# BLS selects a profile via rootflags=subvol=@<profile>. The kernel lives in
# @Minimal_stock (installed above), so every profile inherits it via COW. /boot,
# @home and @var-* are separate top-level subvols shared by all profiles.
#
# KDE and TV-Media-Box install their packages (apt) + config (overlay); only @Desktop changes
# its default target (to graphical, for sddm) -- TV/Router/Minimal stay on multi-user.
# Router applies only its config overlay (NM AP/WAN + ip-forwarding); no packages needed.
# ===========================================================================

# Unmount the nested subvolumes (deepest first), leaving @ mounted at
# $IMAGEMNTDIR. debos' image-partition Cleanup unmounts @ and detaches the loop;
# without this it would fail with EBUSY on the still-mounted children.
- action: run
description: Unmount nested subvolumes before debos detaches the loop
description: Lock @Minimal_stock (RO), re-create @Minimal from it, free the mountpoint
chroot: false
command: |
set -eu
sync
ROOTPART="$({{ $rootdev }})" # @Minimal is still mounted at $IMAGEMNTDIR
# Mount the btrfs top level at a fixed path and KEEP it mounted for the whole profile
# sequence: it is our stable handle for `findmnt --target` (device lookup then works in
# every debos mode, whether or not $IMAGEMNTDIR is mounted) and where the subvols live.
TOP="${IMAGEMNTDIR%/}.toplevel"
mkdir -p "$TOP"
mount -t btrfs -o subvolid=5 "$ROOTPART" "$TOP"
btrfs subvolume snapshot -r "$TOP/@Minimal" "$TOP/@Minimal_stock"
# release @Minimal and its nested submounts so we can replace it and profile
# factories can mount here
findmnt -rno TARGET --submounts "$IMAGEMNTDIR" \
| awk -v root="$IMAGEMNTDIR" '$0 != root' \
| awk '{ print length, $0 }' | sort -rn | cut -d" " -f2- \
| while read -r mp; do umount "$mp"; done
rmdir "$IMAGEMNTDIR/.snapshots"
# Re-create @Minimal as a writable child of the golden base (parent = @Minimal_stock)
# so it matches the other profiles -- which are snapshots of their _stock -- instead
# of being the build origin with no parent.
btrfs subvolume delete "$TOP/@Minimal"
btrfs subvolume snapshot "$TOP/@Minimal_stock" "$TOP/@Minimal"

# --- @Desktop ------------------------------------------------------------------
- action: run
description: Snapshot writable @Desktop_stock and mount it
chroot: false
command: |
set -eu
TOP="${IMAGEMNTDIR%/}.toplevel"
ROOTPART="$(findmnt -fn --nofsroot -o SOURCE --target "$TOP")"
btrfs subvolume snapshot "$TOP/@Minimal_stock" "$TOP/@Desktop_stock"
mount -t btrfs -o "{{ $btrfsopts }},subvol=@Desktop_stock" "$ROOTPART" "$IMAGEMNTDIR"
- action: apt
description: KDE desktop packages
recommends: false # image is minbase/no-recommends; deps are listed explicitly
packages:
- bluedevil
- blueman
- breeze-gtk-theme
- kde-config-gtk-style
- kde-config-screenlocker
- kde-spectacle
- kde-standard
- konsole
- kscreen
- mpv
- plasma-discover
- plasma-nm
- plasma-systemmonitor
- powerdevil
- sddm
- sddm-theme-breeze
- systemsettings
- action: overlay
description: KDE profile config (sddm autologin, plasma, wallpaper)
source: overlays/profile-kde
destination: /
- action: run
description: Make the KDE desktop the default session on @Desktop
chroot: true
command: systemctl set-default graphical.target
- action: run
description: Lock @Desktop_stock RO and spawn writable @Desktop
chroot: false
command: |
set -eu
TOP="${IMAGEMNTDIR%/}.toplevel"
umount "$IMAGEMNTDIR"
btrfs property set "$TOP/@Desktop_stock" ro true
btrfs subvolume snapshot "$TOP/@Desktop_stock" "$TOP/@Desktop"

# --- @TV-Media-Box ---------------------------------------------------------
- action: run
description: Snapshot writable @TV-Media-Box_stock and mount it
chroot: false
command: |
set -eu
TOP="${IMAGEMNTDIR%/}.toplevel"
ROOTPART="$(findmnt -fn --nofsroot -o SOURCE --target "$TOP")"
btrfs subvolume snapshot "$TOP/@Minimal_stock" "$TOP/@TV-Media-Box_stock"
mount -t btrfs -o "{{ $btrfsopts }},subvol=@TV-Media-Box_stock" "$ROOTPART" "$IMAGEMNTDIR"
- action: apt
description: TV media box packages
recommends: false
packages:
- cage
- kodi
- kodi-eventclients-kodi-send
- action: overlay
description: TV media box profile config (kodi, enabled under multi-user)
source: overlays/profile-tv-media-box
destination: /
- action: run
description: Lock @TV-Media-Box_stock RO and spawn writable @TV-Media-Box
chroot: false
command: |
set -eu
TOP="${IMAGEMNTDIR%/}.toplevel"
umount "$IMAGEMNTDIR"
btrfs property set "$TOP/@TV-Media-Box_stock" ro true
btrfs subvolume snapshot "$TOP/@TV-Media-Box_stock" "$TOP/@TV-Media-Box"

# --- @Router ---------------------------------------------------------------
- action: run
description: Snapshot writable @Router_stock and mount it
chroot: false
command: |
set -eu
TOP="${IMAGEMNTDIR%/}.toplevel"
ROOTPART="$(findmnt -fn --nofsroot -o SOURCE --target "$TOP")"
btrfs subvolume snapshot "$TOP/@Minimal_stock" "$TOP/@Router_stock"
mount -t btrfs -o "{{ $btrfsopts }},subvol=@Router_stock" "$ROOTPART" "$IMAGEMNTDIR"
# @Router needs no packages beyond Minimal (NetworkManager + dnsmasq-base + wpa_supplicant
# are common); it just adds the AP/WAN connections + ip-forwarding via the overlay. Its
# default session stays multi-user (inherited); NM autoconnect brings the router up.
- action: overlay
description: Router profile config (NM AP/WAN connections, ip-forwarding)
source: overlays/profile-router
destination: /
- action: run
description: Fix NetworkManager connection permissions on @Router
chroot: true
command: chmod 600 /etc/NetworkManager/system-connections/*.nmconnection
- action: run
description: Lock @Router_stock RO and spawn writable @Router
chroot: false
command: |
set -eu
TOP="${IMAGEMNTDIR%/}.toplevel"
umount "$IMAGEMNTDIR"
btrfs property set "$TOP/@Router_stock" ro true
btrfs subvolume snapshot "$TOP/@Router_stock" "$TOP/@Router"

# Unmount the top level and remount @Minimal at the mountpoint debos owns, so its
# image-partition Cleanup can unmount it and detach the loop. (The profile builds left
# $IMAGEMNTDIR unmounted, and the lingering top-level mount would hold the loop busy.)
- action: run
description: Unmount the top level and remount @Minimal for debos cleanup
chroot: false
command: |
set -eu
TOP="${IMAGEMNTDIR%/}.toplevel"
ROOTPART="$(findmnt -fn --nofsroot -o SOURCE --target "$TOP")"
umount "$TOP"; rmdir "$TOP"
mount -t btrfs -o "{{ $btrfsopts }},subvol=@Minimal" "$ROOTPART" "$IMAGEMNTDIR"
32 changes: 7 additions & 25 deletions debian-rk3576-ospack.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,20 @@ actions:
include:
- acl
- adduser
- avahi-daemon
- alsa-ucm-conf
- alsa-utils
- apt-transport-https
- avahi-daemon
- bash-completion
- bc
- bluedevil
- blueman
- bluez
- bluez-firmware
- bluez-meshd
- breeze-gtk-theme
- bsdextrautils
- bsdmainutils
- btrfs-compsize
- btrfs-progs
- build-essential
- cage
- ca-certificates
- cec-utils
- chromium
Expand All @@ -46,8 +42,6 @@ actions:
- dnsmasq-base
- drm-info
- duperemove
- gstreamer1.0-plugins-bad
- gstreamer1.0-tools
- e2fsprogs
- edid-decode
- evtest
Expand All @@ -58,6 +52,8 @@ actions:
- git
- glmark2-wayland
- gpiod
- gstreamer1.0-plugins-bad
- gstreamer1.0-tools
- htop
- i2c-tools
- inetutils-telnet
Expand All @@ -68,25 +64,17 @@ actions:
- iputils-ping
- iw
- iwd
- kde-config-gtk-style
- kde-config-screenlocker
- kde-spectacle
- kde-standard
- kmscube
- kodi
- kodi-eventclients-kodi-send
- konsole
- kscreen
- less
- libcanberra-pulse
- libdrm-tests
- libfreeaptx0
- liblc3-1
- libldacbt-abr2
- libldacbt-enc2
- liblc3-1
- libsbc1
- libopus0
- libsbc1
- libspa-0.2-bluetooth
- libdrm-tests
- libtypec-utils
- libubootenv-tool
- libusb-1.0-0-dev
Expand All @@ -109,10 +97,7 @@ actions:
- p7zip
- pciutils
- pipewire-alsa
- plasma-nm
- plasma-systemmonitor
- powercap-utils
- powerdevil
- pv
- python3-evdev
- python3-pandas
Expand All @@ -129,11 +114,11 @@ actions:
- systemd-resolved
- systemd-sysv
- systemd-timesyncd
- systemsettings
- tcpdump
- traceroute
- udev
- unzip
- upower
- usb-modeswitch
- usbutils
- util-linux-extra
Expand Down Expand Up @@ -261,9 +246,6 @@ actions:
- libavformat-extra
- lpac
- mesa-teflon-delegate
- mpv
- sddm
- sddm-theme-breeze

- action: overlay
description: Overlay Kodi Chromium kiosk launcher
Expand Down
Loading