trixie statt bookworm: bookworm ist inzwischen oldstable, trixie liefert ausserdem von Haus aus einen neueren Kernel - direkt relevant fuers Ziel 'moeglichst breite Hardwareunterstuetzung'. Secure-Boot-Kette (shim-signed/grub-efi-amd64-signed) funktioniert in beiden Suiten identisch, kein Unterschied dort. WLAN-Paketliste erweitert: firmware-brcm80211 (Broadcom, vorher nicht abgedeckt), wireless-regdb (Regulatory-Datenbank - ohne sie Kanal-/Sendeleistungs-Einschraenkungen, leicht zu uebersehen), wpasupplicant explizit (kam vorher nur transitiv mit), iw + rfkill (Diagnose/Kontrolle). Noch nicht neu gebaut/getestet - naechster Schritt. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
194 lines
7.8 KiB
Bash
Executable File
194 lines
7.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -Eeuo pipefail
|
|
|
|
# Baut das schlanke "Golden Image" fuer das Curtin/FAI-artige Deployment-
|
|
# Backend (siehe ADR-0024 und den Plan unter
|
|
# platform-docs/adr/0024-*.md) - eine reine, unbeaufsichtigte
|
|
# debootstrap-Basis OHNE Desktop-Umgebung. Cinnamon/Mint-Tools/Theming
|
|
# kommen NICHT hierher, sondern werden nach dem ersten Boot vom
|
|
# Provisioning Agent per Ansible-Blueprint ausgerollt (ADR-0002) - dieses
|
|
# Image muss nur ueberall booten und Netzwerk haben.
|
|
#
|
|
# Bewusst reines Debian (nicht Mints Ubuntu-Basis) als Zielsystem: die
|
|
# kundensichtbare Identitaet kommt komplett aus der Ansible-Schicht, die
|
|
# exakte Basis-Distribution des Images ist zweitrangig - siehe
|
|
# Plan-Kontext. Kein Root-Passwort, keine SSH-Hostkeys im Ergebnis (siehe
|
|
# Kommentare unten) - echte Zugangsdaten entstehen erst durch den
|
|
# Provisioning Agent nach der Installation, ein Golden Image mit
|
|
# eingebrannten Zugangsdaten waere ein Sicherheitsrisiko fuer JEDES damit
|
|
# ausgerollte Kundengeraet, nicht nur fuer einen einzelnen Testlauf.
|
|
#
|
|
# Laeuft auf jedem Debian-basierten Host mit debootstrap - keine VM
|
|
# noetig (real auf enterprise/LMDE 6 verifiziert, siehe Kommentar bei
|
|
# SUITE weiter unten).
|
|
|
|
usage() {
|
|
echo "Usage: $0 <output.tar.zst> [suite] [arch]" >&2
|
|
echo " suite: Debian-Suite fuer debootstrap (Standard: trixie)" >&2
|
|
echo " arch: Zielarchitektur (Standard: amd64)" >&2
|
|
}
|
|
|
|
OUTPUT_FILE="${1:-}"
|
|
# trixie (Debian 13) statt bookworm (30.08.2026 umgestellt): bookworm ist
|
|
# inzwischen oldstable, trixie liefert ausserdem von Haus aus einen
|
|
# neueren Kernel - direkt relevant fuers Ziel "moeglichst breite
|
|
# Hardwareunterstuetzung", staerker als der Secure-Boot-Aspekt (die
|
|
# shim-signed/grub-efi-amd64-signed-Kette funktioniert in beiden Suiten
|
|
# identisch, kein Unterschied). debootstrap braucht dafuer keine
|
|
# Uebereinstimmung mit der Suite des Build-Hosts (hier: LMDE 6/bookworm-
|
|
# basiert) - das Bootstrapping laeuft komplett isoliert im chroot.
|
|
SUITE="${2:-trixie}"
|
|
ARCH="${3:-amd64}"
|
|
MIRROR="http://deb.debian.org/debian"
|
|
|
|
if [[ -z "${OUTPUT_FILE}" ]]; then
|
|
usage
|
|
exit 1
|
|
fi
|
|
|
|
if [[ "${EUID}" -ne 0 ]]; then
|
|
echo "Fehler: muss als root laufen (debootstrap/chroot/mount)." >&2
|
|
exit 1
|
|
fi
|
|
|
|
for cmd in debootstrap chroot tar zstd; do
|
|
command -v "${cmd}" >/dev/null 2>&1 ||
|
|
{ echo "Fehler: benötigtes Werkzeug fehlt: ${cmd}" >&2; exit 1; }
|
|
done
|
|
|
|
WORK_DIR="$(mktemp -d /var/tmp/tuxflotte-golden-image.XXXXXX)"
|
|
readonly WORK_DIR
|
|
|
|
MOUNTED=()
|
|
|
|
cleanup() {
|
|
local mnt
|
|
# In umgekehrter Reihenfolge aushaengen - /dev/pts vor /dev usw.
|
|
for ((i = ${#MOUNTED[@]} - 1; i >= 0; i--)); do
|
|
mnt="${MOUNTED[i]}"
|
|
umount --recursive "${mnt}" 2>/dev/null ||
|
|
umount --lazy "${mnt}" 2>/dev/null || true
|
|
done
|
|
chmod -R u+w "${WORK_DIR}" 2>/dev/null || true
|
|
rm -rf "${WORK_DIR}"
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
bind_mount() {
|
|
local target="$1"
|
|
mount --bind "${target}" "${WORK_DIR}${target}"
|
|
MOUNTED+=("${WORK_DIR}${target}")
|
|
}
|
|
|
|
echo "==> debootstrap ${SUITE}/${ARCH} nach ${WORK_DIR}"
|
|
debootstrap --arch="${ARCH}" "${SUITE}" "${WORK_DIR}" "${MIRROR}"
|
|
|
|
# Real beim Testen entdeckt (29.08.2026): mktemp -d legt WORK_DIR mit Modus
|
|
# 0700 an (sein eigenes Sicherheitsstandardverhalten) - debootstrap aendert
|
|
# die Rechte des ihm uebergebenen Zielverzeichnisses selbst nicht, und
|
|
# tar -p uebernimmt diesen Modus beim spaeteren Verpacken/Entpacken 1:1 als
|
|
# Root-Verzeichnis-Rechte des gesamten ausgerollten Dateisystems. Ergebnis:
|
|
# JEDER nicht-root-Prozess (z.B. dbus-daemon, das nach dem Start auf den
|
|
# unprivilegierten "messagebus"-Benutzer wechselt) bekommt dann "Permission
|
|
# denied" schon beim Traversieren von "/" - reale Boot-Fehlerkaskade
|
|
# (dbus/logind/NetworkManager/wpa_supplicant schlagen alle fehl) live auf
|
|
# der QEMU-Testplatte beobachtet. Ein Root-Dateisystem MUSS 0755 sein wie
|
|
# bei jeder normalen Linux-Installation.
|
|
chmod 0755 "${WORK_DIR}"
|
|
|
|
echo "==> apt-Quellen fuer non-free-firmware + backports einrichten"
|
|
# non-free-firmware ist seit Debian 12 eine eigene, standardmaessig NICHT
|
|
# aktive Komponente (anders als bei Ubuntu/Mint) - ohne sie fehlt auf
|
|
# vielen echten Geraeten die WLAN-/GPU-Firmware. Backports fuer einen
|
|
# neueren Kernel (bessere Hardwareunterstuetzung auf aktueller Hardware
|
|
# als der Suite-Standardkernel).
|
|
cat > "${WORK_DIR}/etc/apt/sources.list" <<EOF
|
|
deb ${MIRROR} ${SUITE} main contrib non-free-firmware
|
|
deb ${MIRROR} ${SUITE}-updates main contrib non-free-firmware
|
|
deb ${MIRROR}-security ${SUITE}-security main contrib non-free-firmware
|
|
deb ${MIRROR} ${SUITE}-backports main contrib non-free-firmware
|
|
EOF
|
|
|
|
echo "==> /dev, /proc, /sys, /dev/pts einbinden fuer chroot-Paketinstallation"
|
|
bind_mount /dev
|
|
mount -t proc proc "${WORK_DIR}/proc"
|
|
MOUNTED+=("${WORK_DIR}/proc")
|
|
mount -t sysfs sysfs "${WORK_DIR}/sys"
|
|
MOUNTED+=("${WORK_DIR}/sys")
|
|
mount -t devpts devpts "${WORK_DIR}/dev/pts"
|
|
MOUNTED+=("${WORK_DIR}/dev/pts")
|
|
|
|
# DNS-Aufloesung im chroot braucht eine eigene resolv.conf - der
|
|
# Netzwerk-Namespace wird zwar geteilt, aber /etc/resolv.conf ist eine
|
|
# normale Datei innerhalb des debootstrap-Baums, nicht automatisch mit
|
|
# der des Hosts identisch.
|
|
cp /etc/resolv.conf "${WORK_DIR}/etc/resolv.conf"
|
|
|
|
echo "==> Pakete im chroot installieren (Kernel, Firmware, Netzwerk, SSH)"
|
|
# Paketliste ist ein erster, plausibler Startpunkt - wird nach dem ersten
|
|
# echten Boot-Test (Phase 1 des Plans) voraussichtlich noch angepasst,
|
|
# je nachdem was auf der Testhardware/-VM tatsaechlich fehlt.
|
|
#
|
|
# WLAN-Abdeckung bewusst breit (30.08.2026 ergaenzt) - die gaengigen
|
|
# Chip-Hersteller bei Consumer-PCs/Notebooks sind ueberschaubar (Intel,
|
|
# Realtek, MediaTek, Broadcom, Qualcomm Atheros):
|
|
# - firmware-iwlwifi/firmware-realtek/firmware-atheros: je Hersteller
|
|
# - firmware-brcm80211: Broadcom (BCM43xx) - haeufig in aelteren/gewissen
|
|
# OEM-Notebooks, wurde vorher NICHT explizit abgedeckt
|
|
# - firmware-misc-nonfree: Sammelpaket, deckt u.a. MediaTek-Restfaelle ab
|
|
# - wireless-regdb: die Regulatory-Datenbank fuers Funkband - ohne sie
|
|
# schraenkt der Kernel Kanaele/Sendeleistung ein bzw. verweigert
|
|
# bestimmte Betriebsmodi, leicht zu uebersehen, da WLAN grundsaetzlich
|
|
# noch "geht" (nur eingeschraenkter/non-compliant)
|
|
# - wpasupplicant: WPA/WPA2/WPA3-Handshake - kam bisher nur transitiv als
|
|
# NetworkManager-Abhaengigkeit mit, jetzt explizit fuer Klarheit
|
|
# - iw, rfkill: Diagnose/Kontrollwerkzeuge (Funk-Kill-Switch, manuelle
|
|
# Fehlersuche) - kein Laufzeit-Erfordernis, aber Standardausstattung
|
|
chroot "${WORK_DIR}" /bin/bash -c '
|
|
set -e
|
|
export DEBIAN_FRONTEND=noninteractive
|
|
apt-get update
|
|
apt-get install -y \
|
|
linux-image-amd64 \
|
|
firmware-linux \
|
|
firmware-realtek \
|
|
firmware-iwlwifi \
|
|
firmware-atheros \
|
|
firmware-brcm80211 \
|
|
firmware-misc-nonfree \
|
|
wireless-regdb \
|
|
wpasupplicant \
|
|
iw \
|
|
rfkill \
|
|
network-manager \
|
|
openssh-server \
|
|
sudo \
|
|
locales \
|
|
curl \
|
|
ca-certificates \
|
|
parted
|
|
apt-get clean
|
|
'
|
|
|
|
echo "==> Golden Image von eingebrannten Zugangsdaten befreien"
|
|
# Debootstrap setzt kein Root-Passwort (Konto bleibt gesperrt) - das
|
|
# bleibt bewusst so. openssh-server generiert beim Postinst aber eigene
|
|
# Hostkeys, die JEDES aus diesem Image ausgerollte Geraet sonst identisch
|
|
# mit-ausliefern wuerde (Kollisionsrisiko + Sicherheitsproblem) - werden
|
|
# hier entfernt, die Deployment-Mechanik (Plan Phase 1) erzeugt sie beim
|
|
# eigentlichen Ausrollen pro Geraet frisch.
|
|
rm -f "${WORK_DIR}"/etc/ssh/ssh_host_*
|
|
: > "${WORK_DIR}/etc/machine-id"
|
|
|
|
echo "==> Aushaengen"
|
|
for ((i = ${#MOUNTED[@]} - 1; i >= 0; i--)); do
|
|
umount --recursive "${MOUNTED[i]}"
|
|
done
|
|
MOUNTED=()
|
|
|
|
echo "==> Packe als ${OUTPUT_FILE}"
|
|
tar --numeric-owner --xattrs -C "${WORK_DIR}" -cf - . |
|
|
zstd -f -T0 -19 -o "${OUTPUT_FILE}"
|
|
|
|
echo "==> Fertig: ${OUTPUT_FILE} ($(du -h "${OUTPUT_FILE}" | cut -f1))"
|