diff --git a/docs/superpowers/plans/2026-07-30-host-uebernahme-bootstrap-skript.md b/docs/superpowers/plans/2026-07-30-host-uebernahme-bootstrap-skript.md index 02e9c05..588324d 100644 --- a/docs/superpowers/plans/2026-07-30-host-uebernahme-bootstrap-skript.md +++ b/docs/superpowers/plans/2026-07-30-host-uebernahme-bootstrap-skript.md @@ -13,6 +13,17 @@ - **Vollfassung des Entwurfs:** `docs/superpowers/specs/2026-07-30-host-uebernahme-statt-installation-design.md`. Bei Widerspruch gewinnt die Spec. - **DIE WICHTIGSTE AUFLAGE: das Wissen liegt schon im Repository, erfinde es nicht neu.** Die heutigen Pipeline-Schritte enthalten alles, was hier gebraucht wird — und sie werden vom Plattform-Plan **gelöscht**. Lies sie, **bevor** das passiert: - `app/Provisioning/Steps/Host/InstallProxmoxVe.php` — die Codename-Tabelle (Debian 13/trixie ↔ PVE 9), die Paketquellen, die Reihenfolge. Der Handoff hält fest, dass ein fest verdrahtetes `bookworm` heute PVE-8-Quellen gegen Debian 13 gesetzt hätte. + - `app/Provisioning/Steps/Host/RebootIntoPveKernel.php` — **der Neustart ist das + einzige Unumkehrbare am ganzen Vorgang.** Die Datei beweist den Bootpfad, + *bevor* sie neu startet, statt ihn aus „apt hat nicht gemeckert" zu + schließen: `/boot/vmlinuz-*-pve` vorhanden, `/boot/initrd.img-*-pve` + vorhanden (ein volles `/boot` hinterlässt genau die halbe Initramfs), und + `update-grub` **an seinem Exit-Status** geprüft — den der Vorgänger verwarf. + Alle drei scheitern hart statt zu wiederholen, weil keine sich von selbst + behebt. Dazu die 15-Minuten-Frist, die ihre eigenen Marker löscht, damit ein + Wiederholungslauf frisch neu startet statt sofort wieder in die abgelaufene + Frist zu laufen. **Diese Datei stand nicht in der ersten Fassung dieser + Liste, steht aber auf der Löschliste des Plattform-Plans.** - `app/Provisioning/Steps/Host/ConfigureProxmox.php` — die vollständige Diagnose zu `vmbr0`: warum Proxmox auf Debian keine anlegt, was eine falsche Brücke anrichtet, und die Datacenter-Firewall, ohne die die „nur 80/443"-Regeln der Kunden-VMs **wirkungslos** sind. - `app/Provisioning/Steps/Host/SecureHostFirewall.php` — die nftables-Regeln, samt der Korrektur, dass **nicht jedes ICMP** verworfen werden darf (sonst sind IPv6 und PMTUD gebrochen). - `app/Provisioning/Steps/Host/ConfigureWireguard.php` — wie `wg0` systemd-aktiviert wird. Der Handoff hält fest, dass ein `||`-Rückfall die fehlende Aktivierung verdeckte und der Neustart eine nicht mehr bootende Maschine hinterlassen konnte. @@ -118,8 +129,30 @@ Der Neustart ist die erste Stelle, an der das Skript die Kontrolle verliert. Es hinterlässt deshalb einen systemd-Dienst, der es nach dem Hochfahren **selbst wieder aufnimmt** — mit demselben Code und derselben Fortschrittsdatei. +**Und genau das ist der Punkt, an dem „dieselbe Fortschrittsdatei" Arbeit ist und +keine Feststellung.** Das Rettungssystem läuft im Arbeitsspeicher; sein +Wurzelverzeichnis ist nach dem Neustart weg. Bevor neu gestartet wird, gehen +deshalb **in das frisch installierte System hinüber**: + +- `/var/lib/clupilot/progress.jsonl` — sonst gehen `rescue_checked` und + `debian_installed` verloren. +- das Skript selbst samt `lib/`, +- die Aufrufargumente aus Task 1, in einer Datei, die nur `root` lesen kann — + der WireGuard-Schlüssel steht darin. + +Ohne diesen Handgriff meldet das Skript nach dem Neustart bei Null. Und weil +`flush_reports` erst in Task 6 läuft, **also nach dem Neustart**, fiele der +Verlust nirgends auf — die zwei Abschnitte kämen in der Konsole schlicht nie an. +Genau das prüft Task 6 Step 2, wenn er **alle fünf** vorherigen Abschnitte +verlangt. + +Zum Neustart selbst: **lies `RebootIntoPveKernel.php`.** Der Bootpfad wird +bewiesen, bevor neu gestartet wird, nicht danach gehofft. + - [ ] **Step 2: Auf echter Hardware prüfen** — und ausdrücklich, dass es nach dem - Neustart von allein weiterläuft. + Neustart von allein weiterläuft. **Dazu: nach dem Hochfahren in + `/var/lib/clupilot/progress.jsonl` nachsehen, dass die Zeilen von *vor* dem + Neustart noch dort stehen, mit ihren ursprünglichen Zeitstempeln.** - [ ] **Step 3: Committen.** `Write Debian and survive the first reboot` --- @@ -260,13 +293,41 @@ Eckdaten. Die Antwort trägt das dauerhafte Host-Token für Traefik. verwerfen. Die Gegenseite nimmt erst auf und entfernt dann — aber das Skript darf sich auch von seiner Seite nicht vorzeitig abschneiden. +**Und der Tausch braucht denselben Beweis wie der Beitritt.** Task 6 lässt den +Tunnel erst mit bewiesenem Handshake gelten; hier wird genau dieser Tunnel unter +laufendem Betrieb auf einen neuen Schlüssel umgestellt. Die Reihenfolge allein +schützt davor nicht — sie sagt nur, wann verworfen wird, nicht ob das Neue +trägt. Deshalb, in dieser Folge: + +1. neues Schlüsselpaar erzeugen, registrieren, Antwort haben, +2. `wg0` auf den neuen privaten Schlüssel umstellen, +3. **erneuten Handshake beweisen** — dieselbe Prüfung wie in Task 6, nicht die + geschriebene Datei, +4. **erst dann** den alten Schlüssel verwerfen. + +Kommt der Handshake nicht, wird auf den alten Schlüssel zurückgestellt und der +Abschnitt scheitert laut. Ein Host, der sich im letzten Schritt selbst +aussperrt, ist der eine Fall, den niemand aus der Ferne repariert — und er +passiert am Ende eines Laufs, der bis dahin alles richtig gemacht hat. + Zum Schluss: `pveum acl modify … || true` und `pveum user add … || true` **nicht** übernehmen. Der Handoff nennt sie als offenen Punkt — sie verdecken Fehler, dieselbe Klasse wie der bereits behobene `role add`. +Das ist aber **keine Regel gegen `|| true` an sich**, und wer sie so liest, +bricht Task 3. `RebootIntoPveKernel.php` toleriert +`apt-get -y remove linux-image-amd64 || true` **mit Begründung**: ein Image, das +das Metapaket nie hatte, lässt apt ohne Fehler in der Sache von Null verschieden +enden — und ob der Debian-Kernel weg ist, ist ohnehin nicht die Frage, sondern +ob ein Proxmox-Kernel bootet, was drei Zeilen später eigenständig geprüft wird. +Die Regel lautet: **kein `|| true` über einem Befehl, dessen Fehlschlag etwas +bedeutet** — und wo eines steht, steht der Grund daneben. + - [ ] **Step 2: Auf echter Hardware prüfen.** Der Host steht in der Konsole auf `active`, die sechs Schritte der Kette laufen durch, und die Bereitschaftsseite - meldet `provisioning.usable_host` als erfüllt. + meldet `provisioning.usable_host` als erfüllt. **Und der Tunnel steht danach + noch** — nach dem Schlüsseltausch einmal `wg show` ansehen und einen frischen + Handshake mit dem *neuen* Schlüssel sehen, nicht den alten Zählerstand. - [ ] **Step 3: Committen.** `Hand over the token and let the console take it from here` ---