Phase 3: Personalisierung (Aktivierungscode/WLAN) funktioniert jetzt ohne
Xorriso-Extraktion der ganzen ISO / Casper-Hook-Injection. /opt/tuxflotte/
liegt innerhalb von /live/filesystem.squashfs (read-only) - ein direktes
xorriso -update auf eine Datei darin traf live getestet ins Leere.
Stattdessen: Squashfs entpacken (unsquashfs), installer.conf ersetzen, neu
packen (mksquashfs -comp xz, ~1 Minute reine Kompression, kein
debootstrap/apt), als Ganzes per xorriso -update einspielen. Muss als root
laufen (Datei-Eigentuemer im Squashfs sonst falsch).
Beim ersten echten End-to-End-Testlauf mit dem vollen Golden-Image-Archiv
(vorher nie bis zum Ende gekommen - immer am Ubiquity-Bug oder an einem
Commit-Gate gestoppt) vier echte, bisher unentdeckte Bugs gefunden und
behoben:
1. Golden-Image-Download landete in /run/tuxflotte/backend/ (RAM-Tmpfs,
hier 392 MB) statt auf echtem Speicher - "curl: (23) Failure writing
output to destination" bei 2,3 GB Archiv, unabhaengig von RAM-Groesse.
Fix: image_deploy_extract_image_from_url() streamt Download direkt in
die Extraktion (curl | tar), kein Zwischenspeichern mehr noetig.
backend_launch() partitioniert/formatiert/mountet jetzt VOR dem
Download-Versuch statt danach.
2. /etc/resolv.conf im Zielbaum ist bei der echten Referenz-VM ein von
NetworkManager verwalteter Symlink - "cp" verweigerte das Schreiben
"through a dangling symlink". Fix: Ziel vor dem Kopieren explizit
entfernen.
3. mount --bind auf /dev, /proc, /sys schlug fehl, weil diese Verzeichnisse
nach dem Entpacken gar nicht existierten (package_golden_image.sh
schliesst sie bewusst aus) - und zwar SILENT, weil das bisherige
"cmd && stack_ref+=(...)"-Muster einen Fehlschlag unter "set -e" nicht
als Statement-Fehler wertet. Fiel dadurch erst beim naechsten
chroot-Aufruf auf ("ssh-keygen -A: Couldn't open /dev/null"), weit weg
von der eigentlichen Ursache. Fix: neue image_deploy_restore_excluded_dirs()
legt alle sechs von package_golden_image.sh ausgeschlossenen
Verzeichnisse (proc/sys/dev/run/tmp/var-tmp) direkt nach der Extraktion
wieder an; jeder Mount wird jetzt einzeln explizit geprueft statt auf
&&-Verkettung zu vertrauen.
4. package_golden_image.sh: "--exclude=dev" (ohne "./"-Praefix) matcht bei
GNU tar gegen JEDEN Verzeichnis-Basisnamen im ganzen Baum, nicht nur
den Top-Level-Eintrag - hat dadurch auch kernel/drivers/net/can/dev/
(ein zufaellig gleichnamiger, voellig unverwandter Kernelmodul-Ordner)
aus dem Archiv gerissen, update-initramfs scheiterte an fehlenden
can-dev.ko.zst-Abhaengigkeiten. Lokal mit einem Wegwerf-Testbaum
verifiziert (wie beim "run"-Fund vom selben Tag): "./"-Praefix
verankert das Muster auf den exakten Top-Level-Pfad, gleichnamige
verschachtelte Ordner bleiben erhalten. Betrifft das AKTUELL AUF ANODE
GEHOSTETE Archiv - muss mit dem korrigierten Skript auf der
Referenz-VM neu gepackt und hochgeladen werden (steht noch aus,
Nutzer verschlankt die Referenz-VM gerade zusaetzlich).
Live-Fortschritt in der enterprise-QEMU-VM: nach Fix 1-3 kam der
Deployment-Versuch bis kurz vor update-initramfs durch (Partitionierung,
Formatierung, Mounten, Download+Extraktion, chroot-Fixup bis machine-id +
SSH-Hostkeys liefen alle sauber) - Fund 4 (das defekte Archiv) ist der
letzte noch offene Blocker fuer einen vollstaendig erfolgreichen
End-to-End-Durchlauf.
100 lines
4.7 KiB
Bash
Executable File
100 lines
4.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -Eeuo pipefail
|
|
|
|
# Baut das Golden Image aus einer bereits fertig installierten
|
|
# Referenz-VM (siehe ADR-0024-Nachtrag "Referenz-VM statt debootstrap") -
|
|
# laeuft DIREKT AUF der Referenz-VM (als root), anders als
|
|
# build_golden_image.sh, das auf einem separaten Build-Host ein
|
|
# Basissystem von Grund auf neu baut. Bereinigt zuerst alle maschinen-/
|
|
# betriebsspezifischen Spuren, packt danach den verbleibenden Dateibaum
|
|
# in genau dem Format, das image_deploy_extract_image()
|
|
# (scripts/lib/image_deploy.sh, Phase 1) erwartet - tar/zstd, keine
|
|
# Blockgeraete-Kopie.
|
|
#
|
|
# WICHTIG: entfernt als Teil der Bereinigung auch den bisherigen
|
|
# Betriebs-/Testzugang zu dieser Maschine (Testkonto, SSH-Autorisierung,
|
|
# Root-Passwort) - das ist beabsichtigt (jede damit ausgerollte
|
|
# Kundeninstallation wuerde sonst dieselben, bekannten Zugangsdaten
|
|
# tragen), nicht versehentlich. Das Ergebnis-Archiv muss ueber dieselbe,
|
|
# bereits authentifizierte Verbindung abgeholt werden, mit der dieses
|
|
# Skript gestartet wurde (z.B. per SSH-ControlMaster) - eine NEUE
|
|
# Verbindung nach dem Lauf funktioniert nicht mehr. Ein Proxmox-Snapshot
|
|
# von VOR diesem Lauf ist die vorgesehene Rueckfallebene fuer kuenftige
|
|
# Wartung/Versions-Upgrades der Referenz-VM (siehe Plan).
|
|
|
|
OUTPUT_FILE="${1:-/root/golden-image.tar.zst}"
|
|
|
|
if [[ "${EUID}" -ne 0 ]]; then
|
|
echo "Fehler: muss als root laufen." >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "==> Entferne Betriebs-/Testzugang (nicht Teil des Kundenimages)"
|
|
if id tuxflotte >/dev/null 2>&1; then
|
|
userdel -r tuxflotte 2>/dev/null || userdel tuxflotte 2>/dev/null || true
|
|
fi
|
|
mkdir -p /root/.ssh
|
|
: > /root/.ssh/authorized_keys
|
|
passwd -l root >/dev/null
|
|
|
|
echo "==> Entferne maschinenspezifische Identität"
|
|
rm -f /etc/ssh/ssh_host_*
|
|
: > /etc/machine-id
|
|
# Manche Distributionen legen /var/lib/dbus/machine-id als echte Kopie an
|
|
# statt als Symlink auf /etc/machine-id (siehe ADR-0024-Fund, 29.08.2026) -
|
|
# beide Fälle abdecken, ein Symlink zeigt ohnehin automatisch auf die
|
|
# gerade geleerte Datei.
|
|
if [[ -e /var/lib/dbus/machine-id && ! -L /var/lib/dbus/machine-id ]]; then
|
|
: > /var/lib/dbus/machine-id
|
|
fi
|
|
|
|
echo "==> Entferne Netzwerk-Zugangsdaten der Referenz-VM"
|
|
rm -f /etc/NetworkManager/system-connections/*
|
|
|
|
echo "==> Bereinige Caches/Logs/temporäre Dateien"
|
|
apt-get clean
|
|
rm -rf /var/lib/apt/lists/*
|
|
find /var/log -type f -exec truncate -s0 {} \;
|
|
rm -rf /tmp/* /var/tmp/*
|
|
rm -f /root/.bash_history
|
|
rm -f /home/*/.bash_history 2>/dev/null || true
|
|
|
|
# Paketauswahl eindampfen (Browser, Office-Pakete o.Ä.) bewusst NICHT im
|
|
# ersten Lauf - siehe Plan ("erster Durchlauf zeigt, wie groß das Archiv
|
|
# real wird, dann gezielt nachschärfen"). Blindes Purgen ohne die
|
|
# tatsächliche Paketliste gesehen zu haben, riskiert eher kaputte
|
|
# Abhängigkeiten als sinnvolle Einsparung. Nach diesem Lauf:
|
|
# `dpkg-query -Wf '${Installed-Size}\t${Package}\n' | sort -rn | head -30`
|
|
# auf der Referenz-VM zeigt die groessten Kandidaten fuer einen gezielten
|
|
# zweiten Durchlauf.
|
|
|
|
echo "==> Packe nach ${OUTPUT_FILE}"
|
|
# WICHTIG: tar -C / erzeugt relative Elementnamen (./proc/..., ./sys/...),
|
|
# nicht absolute (/proc/...) - ein --exclude mit fuehrendem Slash matcht
|
|
# dagegen NICHT (live am 31.08.2026 entdeckt: das lief zunaechst
|
|
# unbemerkt gegen die echte Referenz-VM und haette u.a. /proc/kcore mit
|
|
# eingepackt).
|
|
#
|
|
# ZWEITER FUND (31.08.2026, spaeter am selben Tag): ein --exclude OHNE
|
|
# fuehrenden Slash UND ohne "./" matcht bei GNU tar gegen den Basisnamen
|
|
# JEDER Datei/jedes Verzeichnisses im ganzen Baum, nicht nur den
|
|
# Top-Level-Eintrag - "--exclude=dev" hat dadurch auch
|
|
# kernel/drivers/net/can/dev/ (ein voellig unverwandter, aber zufaellig
|
|
# gleichnamiger Kernelmodul-Ordner) mit ausgeschlossen und damit das
|
|
# gesamte CAN-Bus-Treibermodul aus dem Archiv gerissen - live erst beim
|
|
# tatsaechlichen Deployment aufgefallen (update-initramfs scheiterte an
|
|
# fehlenden can-dev.ko.zst-Abhaengigkeiten). Ein Praefix "./" verankert
|
|
# das Muster auf den exakten Top-Level-Pfad (ein "/" im Muster laesst tar
|
|
# gegen den vollen Namen matchen statt nur den Basisnamen) - lokal mit
|
|
# einem Wegwerf-Testbaum verifiziert: ./dev/./proc/./run schliessen nur
|
|
# die Top-Level-Eintraege aus, kernel/drivers/net/can/dev/ und
|
|
# nested/proc/... bleiben erhalten.
|
|
tar --numeric-owner --xattrs \
|
|
--exclude=./proc --exclude=./sys --exclude=./dev \
|
|
--exclude=./run --exclude=./tmp --exclude=./var/tmp \
|
|
--exclude="./${OUTPUT_FILE#/}" \
|
|
-C / -cf - . | zstd -f -T0 -19 -o "${OUTPUT_FILE}"
|
|
|
|
echo "==> Fertig: ${OUTPUT_FILE} ($(du -h "${OUTPUT_FILE}" | cut -f1))"
|
|
echo "==> Root-Zugang zu dieser Maschine ist jetzt gesperrt (Testkonto entfernt, SSH-Autorisierung geleert, Root-Passwort gesperrt) - Proxmox-Snapshot ist die Rueckfallebene fuer kuenftige Laeufe."
|