diff --git a/docs/superpowers/specs/2026-07-30-host-uebernahme-statt-installation-design.md b/docs/superpowers/specs/2026-07-30-host-uebernahme-statt-installation-design.md index 2ee3930..3210b54 100644 --- a/docs/superpowers/specs/2026-07-30-host-uebernahme-statt-installation-design.md +++ b/docs/superpowers/specs/2026-07-30-host-uebernahme-statt-installation-design.md @@ -236,6 +236,83 @@ statische Konfiguration, die das Skript schreibt. --- +## 8a. Das Netzbild, ausdrücklich + +Vom Betreiber festgelegt, und der Grund für mehrere Entscheidungen oben. + +| Auf dem Host | | +|---|---| +| **80/443** | öffentlich. Die Kunden-Clouds müssen erreichbar sein. | +| **22 (SSH)** | **nur im Tunnel.** Aus dem Netz nicht sichtbar. | +| **8006 (Proxmox)** | **nur im Tunnel.** Aus dem Netz nicht sichtbar. | +| alles übrige | zu | + +| Bei CluPilot | | +|---|---| +| öffentlich | **nur, was heute schon offen ist** — Website und Portal | +| `register`, `progress`, `routes` | ausschließlich aus dem WireGuard-Subnetz | + +**Es entsteht kein einziger neuer Weg von außen.** Das ist die härteste Bedingung +dieser Spec, und §11 Test 1 hält sie fest. + +Der Preis, bewusst getragen: fällt die Steuerungs-VM aus, holt kein Host seine +Routentabelle. Die Kunden merken davon nichts — Traefik beantwortet Anfragen aus +seiner lokalen Tabelle weiter. Verzögert wird nur eine **Änderung** (eine frisch +nachgewiesene Kundendomain, eine Kündigung), und die holt der Host beim nächsten +Abruf **von selbst** nach. Das ist besser als heute, wo ein fehlgeschlagener +Schreibvorgang verloren ist und niemand es bemerkt. + +Zur Klarstellung, weil es im Gespräch zweimal durcheinanderging: WireGuard hat +keine Verbindung, die abreißen kann — es ist zustandsloses UDP und nimmt den +Verkehr von selbst wieder auf. Was ausfallen kann, ist ein **Ende**: die +Steuerungs-VM oder der Host. Das repariert kein Protokoll, und es gilt für jede +Variante gleichermaßen. + +--- + +## 8b. Die Subdomain gehört dem Kunden + +Heute leitet `ReserveResources::uniqueSubdomain()` sie aus dem Kundennamen ab +(`Str::slug($customer->name).'-'.Str::random(5)`). Der Kunde wird nie gefragt. + +**Künftig wählt er sie an der Kasse**, mit drei Vorschlägen aus seinem eigenen +Namen und der Möglichkeit, etwas anderes einzugeben. Leeres Feld → ein +unauffälliger Zufallsname. + +### Warum an der Kasse und nicht später + +Die Subdomain ist die **Kennung** der Instanz: `instances.subdomain`, der A-Record +in unserer Zone, der interne Hostname, das erste Zertifikat, ein Eintrag in +Nextclouds `trusted_domains`. Sie nachträglich zu ändern heißt, alles davon +gleichzeitig umzuhängen — eine Migration mit Ausfall. + +**Nicht zu verwechseln mit der eigenen Domain des Kunden.** Die kommt später +**dazu** und ersetzt nichts: `ConfigureDnsAndTls` bildet +`$hostnames = array_filter([$fqdn, $customDomain])` und serviert beide. Dazunehmen +ja, umbenennen nein. + +### Warum ein Hinweis danebensteht + +Eine Subdomain ist **dauerhaft öffentlich** — nicht nur im DNS. Jedes +Let's-Encrypt-Zertifikat wird in die Certificate-Transparency-Protokolle +eingetragen; die sind öffentlich, durchsuchbar und werden nie gelöscht. +`mueller.clupilot.cloud` verrät damit für immer, dass ein Müller hier Kunde ist. +Einer GmbH ist das gleich, einer Arztpraxis womöglich nicht. Der Kunde soll das +wissen, bevor er wählt — deshalb der Satz neben dem Feld, und deshalb ein +neutraler Zufallsname als Vorgabe für alle, die nichts eintragen. + +### Regeln + +- **Sperrliste**, mindestens `www`, `mail`, `admin`, `api`, `app`, `ws`, `status`, + `vpn` — sonst nimmt sich jemand einen Namen, den die Plattform selbst braucht. +- **Eindeutig über alle Kunden**, ohne Rücksicht auf Groß- und Kleinschreibung. +- **Reserviert beim Absenden**, nicht erst wenn die VM steht: zwei gleichzeitige + Bestellungen dürfen nicht nach demselben Namen greifen. +- Länge und erlaubte Zeichen nach DNS-Regeln, keine führenden oder abschließenden + Bindestriche. + +--- + ## 9. Die Host-Kette schrumpft | Heute | Künftig | @@ -351,7 +428,52 @@ ist die Abnahme, und sie ist die einzige, die zählt. --- -## 14. Folgepunkte +## 14. Zwei beschlossene Vorhaben, die hier NICHT drin sind + +Beide im selben Gespräch entschieden, beide bekommen einen eigenen Entwurf. Sie +stehen hier, damit die Entscheidungen nicht verlorengehen. + +### Nextcloud zurücksetzen (Kundenfunktion) + +Der Kunde kann seine Nextcloud auf Werkszustand zurücksetzen — wenn er etwas +zerschossen hat oder neu anfangen will. Technisch derselbe Ablauf wie eine +Erstbereitstellung, nur für einen Kunden, der schon bezahlt hat. + +Beschlossen: **vorher ein Sicherungspunkt, 14 Tage aufbewahrt**, mit einer +Wiederherstellung, die der Kunde selbst auslösen kann. Nur der Kontoinhaber, nicht +jeder Platz. Subdomain zur Bestätigung abtippen statt nur klicken — „neu starten" +und „zurücksetzen" lesen sich zu ähnlich. Sperrfrist zwischen zwei Versuchen. +Bestätigung im Modal nach R23. + +**Die Adresse bleibt:** dieselbe Subdomain, dasselbe Zertifikat, eine hinterlegte +eigene Domain bleibt hinterlegt. Der Kunde bekommt eine leere Nextcloud unter +seiner gewohnten Adresse, keine neue Adresse. + +### Störungsmeldung an den Betreiber + +**Gemessen, dass es das heute nicht gibt:** `SyncMonitoringStatus` läuft alle fünf +Minuten und schreibt den Zustand mit, legt aber **keinen Vorfall an** und schickt +**keine Mail**. In `app/Mail/` gibt es keine einzige Störungsmeldung — alle +vorhandenen Mails gehen an Kunden. Eine Kunden-VM kann also ausfallen, ohne dass +jemand es erfährt. + +Beschlossen: **zwei Fehlmessungen in Folge** (der Zeitplan misst fünfminütig, das +sind die gewünschten zehn Minuten) lösen eine Störung aus. Ein einzelner Aussetzer +nicht. + +**Fällt ein ganzer Host aus, kommt EINE Meldung** — „Host pve-fsn-1 antwortet +nicht, 40 Instanzen betroffen" — statt vierzig einzelner. Vierzig Mails sagen +nicht, dass es ein Host ist; eine sagt es sofort. Einzelne VMs melden sich +weiterhin einzeln. + +Damit es Signal bleibt und nicht Lärm: keine Meldung während eines angekündigten +Wartungsfensters, keine für gekündigte oder abgeschaltete Instanzen, **eine Mail je +Störung** statt alle fünf Minuten eine neue, und eine Entwarnung, wenn es zurück +ist. + +--- + +## 15. Folgepunkte - Die zwei Seed-Hosts aus `DatabaseSeeder` entfernen. Sie stehen auf `active`, haben keinen Token und tragen Adressen aus RFC 5737.