Hinweis: Im Release Candidate empfehlen wir, den Umzug zuerst mit einer Kopie auf Testservern durchzuspielen. Für produktive Umzüge begleiten wir dich auf Wunsch – schreib an hello@novacontrolpanel.com.
So funktioniert der Umzug
Nova zieht eine Installation deines bisherigen Hosting-Panels (im Folgenden „Legacy-Basis“, die alten Server „Quellserver“) auf frisch installierte Nova-Hosts um. Unterstützte Versionen der Legacy-Basis nennen wir dir bei der Planung des Umzugs.
Die Quellserver bleiben maßgeblich und unberührt, bis du umschaltest. Nova wird auf neuen Hosts installiert, die Metadaten werden importiert und die Daten kopiert, während die Quellserver weiter ausliefern. Beim Cutover wird die Quelle eingefroren, ein letztes Delta läuft, Nova aktiviert alles, und DNS/MX (oder die Hetzner Primary IPs) wechseln zu Nova. Bis zum Commit trägt ein Fallback jede Änderung, die auf Nova gemacht wurde, zurück auf die Quellserver.
| Phase | Maßgeblich | Befehle | Rückweg |
|---|---|---|---|
| P1 Import | Quelle | preflight, plan, import, verify, delta, status | rollback (entfernt die Nova-Seite) |
| P2 Cutover | wechselt | cutover --legacy-frozen (wiederholen, solange Exit 75) | cutover --abort (bevor das Fenster öffnet) |
| P3 Fallback-Fenster (Standard 14 Tage, 1 bis 90) | Nova; nur Inhaltsänderungen | status | fallback --legacy-mx-holding |
| P4 Committed | Nova | commit --confirm-irreversible | keiner |
In P3 lehnt Nova strukturelle Änderungen umgezogener Mandanten ab (Sites, Postfächer, Datenbanken, Zonen, Benutzer anlegen oder löschen; Planwechsel) mit 409 NATIVE_IMPORT_FALLBACK_WINDOW_OPEN. Inhalte (Dateien, Mail, Datenbankinhalte, Passwörter, DNS-Einträge) darfst du ändern; ein Fallback trägt sie zurück.
Befehlsübersicht
Alle Befehle laufen als root auf dem Nova-Control-Host:
NI="php /opt/nova-controlpanel/application/current/src/api/application/bin/nova-import.php"
$NI preflight --profile import.json
$NI plan --profile import.json --run "$RUN"
$NI import --run "$RUN" --plan <plan_sha256>
$NI verify --run "$RUN"
$NI delta --run "$RUN"
$NI status --run "$RUN"
$NI cutover --run "$RUN" --legacy-frozen # oder: cutover --run "$RUN" --abort
$NI fallback --run "$RUN" --legacy-mx-holding # --legacy-mx-holding nur bei Läufen mit Mail-Domains
$NI commit --run "$RUN" --confirm-irreversible
$NI rollback --run "$RUN" # nur vor der ersten Cutover-Aktivierung--profileist ein Dateiname in/etc/nova-controlpanel/import/(oder ein absoluter Pfad darin). Spätere Befehle finden das Profil über den Digest, den der Lauf gespeichert hat.RUNistimp_plus 43 Zeichen ausA-Z a-z 0-9 _ -, von dir gewählt, z. B.RUN=imp_$(openssl rand -base64 32 | tr '+/' '-_' | tr -d '=').- Ausgabe: JSON-Receipts auf stdout;
planschreibt zusätzlich eine Zusammenfassung auf stderr. statusist rein lesend und sperrt nichts; er zeigt Phase, Gate, die Schritte des letzten Versuchs,rollback_allowed, das Ende des Fallback-Fensters und die letzten Fehler.
| Exit-Code | Bedeutung |
|---|---|
| 0 | erledigt |
| 3 | abgelehnt (preflight, plan) oder fehlgeschlagen (import, verify, delta) |
| 75 | ausstehend (Node-Effekte oder Datenläufe noch nicht abgeschlossen): denselben Befehl erneut ausführen |
| 64 | Aufruffehler |
| 77 | nicht root |
| 1 | sonstiger Fehler mit NOVA_IMPORT_*-Code auf stderr |
Wichtig: Aktualisiere Nova nicht zwischen
planundcommit. Ein Lauf ist an den installierten Kandidaten gebunden. Nach einem Upgrade lehnenimport,verify,delta,cutoverund der Rückweg vonfallbackmitNOVA_IMPORT_RUN_CANDIDATE_CHANGEDab. Vor der ersten Aktivierung bleibt dann nurrollbackund ein neuer Lauf, danach ist kein Fallback mehr möglich und nur nochcommit. Schließe den Umzug also vor dem nächsten Nova-Update ab.
1. Vorbereitung (Tage vorher)
1.1 Anforderungen an die Quelle
- Die Quelle muss eine unterstützte Version der Legacy-Basis sein; andere Versionen scheitern in
preflightoderplan. Ist eine Aktualisierung nötig, führst du sie mit dem Updater der Legacy-Basis selbst durch. - Ein Quellserver mit Diensten pro Nova-Node. Mehrere Quellserver auf einem Node werden abgelehnt (
PLATFORM_SERVER_NODE_SHARED). - Umgezogene Websites erhalten das Nova-Layout
/var/www/nova-controlpanel/wst_<ref>/mitweb/undprivate/(siehe Pfade umgezogener Websites). - Nicht unterstützte Typen lehnt
planab (RESOURCE_TYPE_UNSUPPORTED: XMPP, APS, OpenVZ, iptables).
Wichtig: Vertraue der Quelle, bevor du sie umziehst. In 1.0 spielt der Import Datenbank-Dumps mit administrativen Rechten auf dem Zielnode ein. Prüfe die Integrität der Quellserver: aktuelle Updates, keine unbekannten Root-Logins, SSH-Schlüssel, Cronjobs oder Systembenutzer. Im Zweifel setzt du die Quelle vor dem Umzug neu auf. Ein eigenes Import-Konto pro Datenbank ist für 1.1 geplant.
Pfade umgezogener Websites
| Quellserver | Nova | Wie |
|---|---|---|
/var/www/clients/clientN/webN/web | /var/www/nova-controlpanel/wst_<ref>/web | bei jedem Durchlauf (Import, delta, letzter Durchlauf von cutover, Rückweg von fallback) |
/var/www/clients/clientN/webN/private | /var/www/nova-controlpanel/wst_<ref>/private | dieselben Durchläufe und Regeln wie web/: keine setuid-Dateien, keine Symlinks aus dem Baum heraus, Eigentümer und Modus der Nova-Identität der Site, zählt zum Speicherlimit der Site |
cgi-bin/, log/, ssl/, tmp/ der Site | nicht übernommen | Nova schreibt eigene Logs und Zertifikate |
/var/www/clients/clientN/webN | Symlink auf wst_<ref> | beim Cutover angelegt, von fallback, rollback und beim Löschen der Site entfernt |
/var/www/<domain> | Symlink auf wst_<ref> | mit der Site, wie bei jeder Nova-Website (Tagesbetrieb) |
| – | /var/www/clients/<customer>/<domain> | mit der Site: der lesbare Pfad, den das Panel zeigt |
- Eine Quell-Site ohne
private/überspringt diesen Teil. Hat die Nova-Site später Dateien inprivate/, lehntfallbackvor jeder Übertragung mitNOVA_IMPORT_TRANSFER_LEGACY_PRIVATE_ABSENTab: legeprivate/auf der Quell-Site an (Eigentümer: Site-Benutzer) und startefallbackerneut. - Weil
/var/www/clients/clientN/webNin den Nova-Baum zeigt, funktionieren absolute Pfade der Quelle in Dateien unterweb/undprivate/, in umgezogenen Cronjobs und in Anwendungskonfigurationen nach dem Cutover weiter. PHP braucht dafür nichts (open_basedirprüft den aufgelösten Pfad). In einem Chroot (Chroot-Cronjob, Jailkit-Shell, PHP-FPM-Chroot) sieht der Prozess wie bisher/web,/private,/tmp. - Der zusätzliche Standard-Link
/var/www/clients/clientN/<domain>der Legacy-Basis wird nicht angelegt; nutze/var/www/<domain>oder den Kompatibilitätspfad. planlistet pro Site die Links (paths.links) und jeden absoluten Quellpfad in umgezogenen Cronjobs (paths.cron_paths, die Befehle selbst werden nie ausgegeben), markiert alscompat_symlink(vom Kompatibilitäts-Symlink abgedeckt),chrooted_job(sieht die Jail-Sicht) odernot_moved(Pfad einer Site außerhalb dieses Laufs: Befehl vor dem Cutover anpassen). Zwei Sites verschiedener Quellserver, die auf einem Nova-Node denselben Pfad/var/www/clients/clientN/webNbräuchten, lehntplanab (WEB_COMPAT_PATH_COLLISION).- Ein Pfad, der auf dem Nova-Node schon existiert, wird nie überschrieben: die Aktivierung stoppt mit
NOVA_WEB_PATH_ALIAS_COLLISION. Räume den Pfad auf dem Node weg und führe denselbencutovererneut aus (zweimal: der erste Aufruf reiht den nächsten Versuch ein).
1.2 Ziel-Fleet
- Installiere die Nova-Fleet auf neuen Hosts (Installation): ein Nova-Node pro Quellserver mit Diensten, mit passenden Rollen. Bei Übernahme der Primary IPs muss jeder Nova-Node am selben Hetzner-Standort und im selben privaten Netz wie sein Quellserver liegen.
- Installiere vor der Aufnahme des zweiten Nodes eine Lizenz für die gesamte Node-Anzahl (Lizenz).
- Aktiviere jede Ebene, die die Quelle nutzt (Web, Mail, Datenbank, DNS, Benutzerzugänge), und prüfe die Fleet mit den Checklisten (Tagesbetrieb).
- Ergänze auf den Ziel-Nodes die Import-Capabilities in
NOVA_AGENT_WRITE_CAPABILITIES(nur während des Umzugs, siehe Tabelle unten). - Lege den SSH-Schlüssel je Quellserver aus dem Profil als root mit
0600auf jedem Ziel-Node ab:/etc/nova-controlpanel-node-agent/import-transfer/ssh-server-<id>.key(Web, Mail) und/etc/nova-controlpanel-node-agent/import/ssh-server-<id>(Datenbank). Nur für einen Fallback zusätzlich den separaten Fallback-Schlüssel als...import-transfer/ssh-server-<id>.fallback.keyund...import/ssh-server-<id>-fallback. - PHP-Runtimes: Jede PHP-Version, die eine umgezogene Site nutzt, muss vor dem Import auf ihrem Nova-Node installiert sein –
php<v>-fpmfür PHP-FPM,php<v>-cgifür FastCGI.planlistet sie pro Node unterphp_runtimes. Eine alsnode_default_onlymarkierte Version ist entweder die eigene PHP-Serie des Nodes (Ubuntu 24.04: 8.3, Debian 13: 8.4) oder von dir zu installieren. Lass diephp-Alternative des Nodes auf seiner eigenen Serie (update-alternatives --set php /usr/bin/php8.3unter Ubuntu 24.04), sonst lehnt das nächste Nova-Upgrade seinen Preflight ab. Eine vorhandene Runtime gleicher Version, aber mit anderem FPM-Layout, deaktiviert oder fehlerhaft, wird abgelehnt (PLATFORM_PHP_RUNTIME_VERSION_SCOPE_EXISTS): erst angleichen oder reparieren. - Web-Quota und Kernel-Updates: Das Quota-Dateisystem braucht die Kernel-Module
quota_v2/quota_tree, die Ubuntu-Cloud-Kernel nur inlinux-modules-extra-<kernel>mitbringen. Der Hook/etc/kernel/postinst.d/nova-web-quota-modulelässt die Konfiguration eines Kernels ohne diese Module scheitern, damit er nie Boot-Standard wird. Danach:apt-get install --no-install-recommends linux-modules-extra-<kernel>unddpkg --configure -a. - DNS-Node-Endpunkte: Veröffentliche vor dem Cutover den Endpunkt jedes Nova-DNS-Nodes, der importierte Zonen erhält –
PUT /api/next/v1/dns-node-endpoints/{node_id}mit{"nameserver_fqdn":"ns1.example.net.","node_id":"...","transfer_ipv4":"<private address>","transfer_ipv6":null}oder im Panel unter Systemverwaltung → DNS-Server & TSIG. Der Import legt ihn nicht an.
Import-Capabilities für Schritt 4:
| Node | Capability |
|---|---|
| Web- und Mail-Nodes | import.transfer.execute.v1 |
| Datenbank-Nodes | database.import.v1 |
| der Mail-Node, der eine Mail-IP der Quelle übernimmt | mail.source-address.configure.v1 |
1.3 Zugriff auf die Quelle (auf den Quellservern)
- Ein MariaDB-Konto nur mit SELECT-Rechten auf die Datenbank der Legacy-Basis, über verifiziertes TLS oder einen Unix-Socket. Bei IP-Übernahme trägst du die private Adresse des Quellservers als Datenbank-Host ein.
- Pro Quellserver ein SSH-Konto
nova-import, dessen Schlüssel nur das Source-Gate/usr/local/sbin/nova-import-source-gateausführen darf, mit den passendenauthorized_keys- und sudoers-Zeilen. Das Source-Gate und die genauen Zeilen erhältst du mit Nova. Der Host-Key wird im Profil festgelegt (host_key_sha256). - Nur wenn du ein Fallback-Fenster willst: ein Fallback-Writer-Konto mit genau den vorgesehenen Spaltenrechten sowie separater Fallback-SSH-Schlüssel und Restore-Konto. Ohne
fallback_writerwirdfallbackabgelehnt (NOVA_IMPORT_FALLBACK_WRITER_UNCONFIGURED).
1.4 Import-Verzeichnis und Profil (Nova-Control-Host)
install -d -m 0700 /etc/nova-controlpanel/import
umask 077
openssl rand -hex 32 > /etc/nova-controlpanel/import/id-key # einmal pro Ziel; nie ändern
# Secrets: source-db-password, optional source-db-ca.pem, ssh-server-<id>, optional fallback-db-password (alle 0600 root)Schreib anschließend /etc/nova-controlpanel/import/import.json: Quelldatenbank, ein Eintrag pro Quellserver mit SSH-Zugang (optional mail_relay und addresses), node_mapping, fallback_window_days, fallback_writer. Eine kommentierte Vorlage stellen wir dir mit Nova bereit.
1.5 Adressplan: Übernahme oder Neuzuordnung
Jede Adresse, die ein Quellserver bindet (Server-IPs, IP-Zuordnungen, vHost-Adressen), muss geplant sein, sonst lehnt plan ab (ADDRESS_PLAN_MISSING):
| Plan | Bedeutung | DNS, SPF, PTR |
|---|---|---|
takeover | die Hetzner Primary IPv4 (und IPv6) des Quellservers wandert beim Cutover auf den zugeordneten Nova-Node | nichts ändert sich: A/AAAA, MX, SPF und PTR bleiben an der Adresse |
remap:<nova address> | die Adresse bleibt beim Quellserver; Nova bindet eine eigene | Cutover schreibt A/AAAA und SPF ip4:/ip6: in den importierten Zonen um; PTR der Nova-Adresse und extern gehostete Zonen pflegst du selbst |
Für remap gilt:
- Die Nova-Adresse muss bereits auf dem zugeordneten Nova-Node konfiguriert sein (sichtbar in
ip address show). - Jede Adressfamilie der Quelle braucht eine Nova-Adresse derselben Familie. Ein Quellserver mit IPv4 und IPv6 braucht ein IPv4- und ein IPv6-Ziel. Gib dem Node notfalls zuerst eine (Hetzner Primary) IPv6; dafür muss der Server ausgeschaltet sein.
Für takeover siehe Hetzner-Primary-IP-Übernahme: Führe dort check aus, bis er besteht, und set-auto-delete-off.
1.6 DNS und Mail vorbereiten
- Senke die TTL jedes Eintrags, der sich ändern wird (A/AAAA neu zugeordneter Adressen, MX, NS und Glue bei Nameserver-Wechsel), mindestens eine alte TTL vor dem Cutover auf 300 s.
- Neu zugeordnete Mail-Adresse: Setze vor dem Cutover den Reverse-DNS der Primary IP des Nova-Nodes in der Hetzner-Konsole auf den Mail-Hostnamen und ergänze die neue Adresse in SPF-Einträgen extern gehosteter Zonen.
- DKIM-Schlüssel ziehen mit ihrem bisherigen Selector um; hier ist nichts vorzubereiten.
2. Import und Generalprobe (P1, Quelle liefert weiter aus)
$NI preflight --profile import.json # Exit 0: passed
$NI plan --profile import.json --run "$RUN" # Exit 0: planned; plan_sha256 notieren
$NI import --run "$RUN" --plan <plan_sha256> # fortsetzbar; wiederholen, bis keine Arbeit mehr aussteht
$NI verify --run "$RUN" # Zähler, Digests, Mandanten- und Capability-Parität
$NI delta --run "$RUN" # beliebig oft bis zum Cutover- Behebe jede Ablehnung von
preflightundplanan der Quelle oder im Profil und plane neu. Ändert sich die Quelle nachplan, stoppt der Lauf (NOVA_IMPORT_RUN_SOURCE_CHANGED): neuen Lauf planen. - Ein neuer Lauf nach
rollbackfunktioniert mit demselbenid-key;statuszeigt die neueid_epoch. Ändere den Schlüssel dafür nie. - Eine Anlage, die während
importauf einem Node scheiterte, legt der nächsteimporterneut an; behebe vorher die Ursache auf dem Node. NOVA_IMPORT_DATABASE_ENGINE_INVENTORY_STALE(Stufeengines) heißt: kein Datenbank-Node hat innerhalb von 2 Minuten geantwortet. Prüfe die Node Agents undsystemctl status nova-controlpanel-operations-database-engine-inventory.timer.- Importierte Ressourcen bleiben bis zum Cutover inaktiv (Konten deaktiviert, nichts ausgerollt). Prüfe Websites, Postfächer und Datenbanken direkt auf den Nova-Nodes mit
curl --resolvesowie IMAP- und SQL-Logins, bevor du den Cutover planst. - Probe den Ablauf auf Testservern:
import,verify,rollback, ein zweiterimportderselben Quelle (gleiches Ergebnis), dann ein vollständiger Cutover, Fallback und zweiter Cutover.
3. Cutover (P2, Wartungsfenster)
3.1 Quelle einfrieren
Für die umziehenden Mandanten auf den Quellservern: Panel-Änderungen stoppen, Server-Cronjobs stoppen, Mailzustellung am bisherigen MX anhalten, Datenbank- und Web-Inhalts-Writes stoppen. cutover verlangt deine Bestätigung (--legacy-frozen) und weist das Einfrieren dann an der Quelle nach (Snapshot und Änderungsprotokoll unverändert).
3.2 Cutover ausführen
$NI cutover --run "$RUN" --legacy-frozen # wiederholen, solange Exit 75Der Cutover führt das letzte Delta und die Prüfung aus. Bei IP-Übernahme wartet er anschließend bei address_takeover mit Exit 75 und gibt address_takeover.operator aus: die genauen check- und swap-Befehle, die Reihenfolge und die erwartete Ausfallzeit.
Lehnt ein Node während der Aktivierung eine Anlage ab (z. B. ein Shell-Konto, dessen Jailkit-Einrichtung scheitert), endet der Aufruf mit Exit 1 und dem Code des Nodes; error.failures listet jede abgelehnte Ressource mit eigenem Code. Behebe die Ursache und führe denselben cutover erneut aus – er legt die abgelehnten Ressourcen neu an, nichts doppelt. rollback ist ab Beginn einer Aktivierung nicht mehr möglich; der Weg ist dann dieser Wiederholungsversuch oder cutover --abort (siehe Entscheidungstabelle).
3.3 Primary IPs tauschen (nur bei Übernahme)
Pro Quellserver von deiner Workstation aus:
python3 tools/import/Invoke-NovaHetznerPrimaryIpSwap.py swap --legacy <legacy> --target <nova-node> \
--state ~/nova-import/swap-<server>.json --confirm swap:<legacy_id>:<target_id>Schalte den Quellserver danach in der Hetzner-Konsole ohne öffentliche IP wieder ein, lass seine Dienste gestoppt und führe den Cutover erneut aus, bis er mit 0 endet. Details unter Hetzner-Primary-IP-Übernahme.
3.4 DNS und MX umstellen (Neuzuordnung und DNS-Umzug)
Der abschließende Switch-Bericht listet die Aktionen: SET_DELEGATION_NS_AND_GLUE, SET_MX_AND_ADDRESS_RECORDS (entfällt, wenn alle Server übernommen wurden), LEGACY_MX_RELAYS_TO_NOVA, KEEP_LEGACY_FROZEN und COMMIT_OR_FALLBACK_BEFORE_WINDOW_ENDS. Das Weiterleiten verirrter Mails vom bisherigen MX an Nova richtest du auf dem bisherigen MX ein.
3.5 Erwartete Ausfallzeit
| Fall | Websites | Panel für Kunden | |
|---|---|---|---|
| Übernahme | vom Herunterfahren in 3.3 bis zur Aktivierung: der Neustart (typisch 2 bis 5 Minuten) plus Aktivierung des Bestands | kein Verlust: Absender wiederholen, der bisherige MX hält die Zustellung während des Einfrierens an | eingefroren ab 3.1, bis das Fenster öffnet |
| Neuzuordnung / DNS-Wechsel | keine für Lesezugriffe; Inhalts-Writes eingefroren ab 3.1; Besucher wechseln mit der TTL | während des Einfrierens am bisherigen MX gehalten, dann an Nova weitergeleitet | wie oben |
Die Werte sind Schätzungen – miss sie bei deiner Generalprobe.
4. Prüfungen nach dem Cutover
| Prüfung | Befehl | Erwartet |
|---|---|---|
| Websites auf behaltenen IPs | curl --resolve site.example.org:443:<ip> https://site.example.org/ | die Site, ausgeliefert vom Nova-Node |
| Bisherige Pfade | auf dem Web-Node: readlink /var/www/clients/client<N>/web<N> /var/www/<domain>; ls /var/www/clients/client<N>/web<N>/private/ | beide zeigen auf /var/www/nova-controlpanel/wst_<ref>; private/ ist umgezogen |
| Nameserver | dig @<nova ns> <zone> SOA, dig <zone> NS | Nova antwortet mit einer Seriennummer über der bisherigen; neu zugeordnete Einträge tragen die neue Adresse |
| PTR | dig -x <mail ip> | bei Übernahme unverändert; bei Neuzuordnung der Mail-Hostname |
| MX und SMTP | dig <domain> MX; SMTP-Sitzung zur MX-Adresse | Banner des Nova-Mail-Nodes |
| Ausgehende Absenderadresse | auf dem Mail-Node: postconf smtp_bind_address smtp_bind_address6 inet_interfaces | die bisherige Mail-Adresse (Übernahme) |
| SPF, DKIM, DMARC | Testmail an ein externes Postfach; Authentication-Results lesen | spf=pass, dkim=pass mit dem bisherigen Selector, dmarc=pass |
| DKIM-Eintrag | dig TXT <selector>._domainkey.<domain> | derselbe Schlüssel wie vorher |
| Postfach | IMAP-Login eines umgezogenen Benutzers; neue Mail kommt an | funktioniert |
| Logins | ein umgezogener Kunde und Reseller melden sich im Panel an | funktioniert; wer vorher einen zweiten Faktor nutzte, richtet MFA neu ein |
| Umzugsstatus | $NI status --run "$RUN" | Phase fallback_window, keine last_errors |
5. Fallback-Fenster und Entscheidung
Beobachte den Bestand während des Fensters. status warnt vor dem Ende; automatisch wird nichts committed.
Fallback (P3 zurück zur Quelle)
- Lass den bisherigen MX die Mail der umgezogenen Domains halten und nicht mehr an Nova weiterleiten.
$NI fallback --run "$RUN" --legacy-mx-holding: Nova friert ein, gibt die Mail-Absenderadresse frei, leitet Mail an den bisherigen MX weiter, führt das Rück-Delta aus (Web-Roots undprivate/, Maildirs, Datenbanken; die Links/var/www/clients/clientN/webNwerden entfernt) und schreibt Passwörter und DNS zurück. Danach wartet er beiaddress_release(Exit 75) mit demswap-back-Befehl.- Nur bei Übernahme:
python3 tools/import/Invoke-NovaHetznerPrimaryIpSwap.py swap-back --state ~/nova-import/swap-<server>.json --confirm swap-back:<legacy_id>:<target_id>. - Führe denselben
fallbackerneut aus, bis er mit 0 endet, stelle DNS/MX laut Bericht zurück und starte dann die Dienste der Quelle (START_LEGACY_SERVICES_AFTER_SWITCH). Nova leitet weiter, bis die TTLs abgelaufen sind.
Hinweis: Panel-Passwörter, die Nova als Argon2 gespeichert hat, lassen sich nicht zurückschreiben (
PASSWORD_RESET_ON_LEGACYim Bericht). Setze sie im bisherigen Panel zurück.
Commit (P4)
$NI commit --run "$RUN" --confirm-irreversibleDanach räumst du auf: Import-Capabilities und SSH-Schlüsseldateien von den Nodes entfernen; Source-Gate, Import-Konten und Fallback-Writer von den Quellservern entfernen; die Hetzner-Token-Datei löschen; die Quellserver außer Betrieb nehmen. Bei Übernahme gehören die bisherigen Primary IPs nun dem Nova-Node; dessen ursprüngliche Primary IPs bleiben unzugewiesen (und kostenpflichtig), bis du sie löschst.
6. Entscheidungstabelle für den Rückweg
| Situation | Phase | Entscheidung | Wie |
|---|---|---|---|
preflight oder plan lehnt ab | vor P1 | Quelle oder Profil korrigieren | neu planen mit neuer Lauf-ID |
import, verify oder delta scheitert wiederholt | P1 | bei der Quelle bleiben | rollback --run RUN (entfernt alles, was der Lauf auf Nova angelegt hat), korrigieren, neuen Lauf planen |
Nachweis des Einfrierens scheitert (NOVA_IMPORT_LEGACY_NOT_FROZEN, NOVA_IMPORT_RUN_SOURCE_CHANGED) | P2 | den Schreiber auf der Quelle finden | cutover --abort, Einfrieren aufheben, untersuchen |
| Letztes Delta oder Prüfung scheitert, kein Tausch erfolgt | P2 | abbrechen | cutover --run RUN --abort, Einfrieren aufheben; die Quelle liefert weiter aus |
| Tausch erfolgt, Aktivierung scheitert vor Öffnen des Fensters, Ursache schnell behebbar | P2 | wiederholen | Ursache auf dem Node beheben, denselben cutover erneut ausführen |
| Tausch erfolgt, Aktivierung scheitert, keine schnelle Lösung | P2 | abbrechen und zurücktauschen | cutover --abort gibt den Rücktausch aus; swap-back; auf dem Mail-Node php /opt/nova-controlpanel-node-agent/apps/node-agent/bin/configure-mail-source-address.php --clear, falls mail_source erfolgt war; Quelle starten. Später erneut einfrieren und cutover auf demselben Ziel |
| Prüfungen nach dem Cutover scheitern, keine schnelle Lösung | P3 | Fallback | Abschnitt 5, „Fallback“ |
| Probleme nach Ende des Fensters oder nach Commit | P4 | kein Rückweg | auf Nova vorwärts beheben oder aus eigenen Backups wiederherstellen |
| Alle Prüfungen bestanden, Fenster lange genug beobachtet | P3 | Commit | Abschnitt 5, „Commit“ |
rollback wird abgelehnt, sobald irgendein Cutover-Versuch eine Aktivierung begonnen hat – auch nach Abbruch oder Fallback (NOVA_IMPORT_ROLLBACK_AFTER_CUTOVER). Ab dann ist fallback der Rückweg.
Hetzner-Primary-IP-Übernahme
Liegen deine Quellserver in der Hetzner Cloud, kannst du ohne Adressänderung umziehen: A-Einträge, MX-Ziele, PTR, SPF und die Absender-Reputation bleiben an der Primary IPv4 und IPv6 des Quellservers. Beim Cutover wandern diese Primary IPs auf den Nova-Node, beim Fallback zurück.
Wichtig: Nova erhält dein Hetzner-Token nie. Du tauschst die IPs selbst (Hetzner-Konsole,
hcloudoder das Hilfsskript unten mit deinem eigenen Token); Nova prüft nur anhand der Adressmeldung des Nodes, ob das Ergebnis stimmt, bevor es etwas aktiviert.
Voraussetzungen (Tage vorher)
Das Importprofil plant jede Adresse pro Quellserver (source.servers[].addresses):
"addresses": {"hetzner": {"legacy_server": 4711, "target_server": 4712, "network": 1234567},
"plan": [{"address": "203.0.113.10", "plan": "takeover", "node_id": "node_..."},
{"address": "2001:db8:1::1", "plan": "takeover", "node_id": "node_..."},
{"address": "203.0.113.11", "plan": "remap:198.51.100.11"}]}takeover gilt für die Primary IPv4 (und die IPv6-Adresse, die der Server aus seinem /64 nutzt), remap: für jede andere Adresse. hetzner enthält die numerischen Hetzner-Server-IDs; der Cutover gibt damit die genauen Befehle aus. addresses.operator_checks im Plan-Bericht wiederholt die Prüfungen.
- Der übernehmende Mail-Node hat
mail.source-address.configure.v1inNOVA_AGENT_WRITE_CAPABILITIES. - Quellserver und Nova-Node liegen am selben Hetzner-Standort und im selben privaten Netz. Das private Netz trägt nach dem Tausch jede Übertragung: Trage im Profil als SSH-Host (
source.servers[].ssh.host) und als Datenbank-Host die private Adresse des Quellservers ein. - Primary IPv4 und IPv6 des Quellservers existieren, sind ihm zugewiesen und haben
auto_delete=false; ebenso die eigenen Primary IPs des Nova-Nodes (sie werden für den Fallback unzugewiesen aufbewahrt). Eine Primary IP lässt sich nur bei ausgeschaltetem Server (ent)zuweisen; pro Server eine IPv4 und eine IPv6. - PTR-Einträge sind auf den Primary IPs des Quellservers gesetzt (sie gehören zum Primary-IP-Objekt und wandern mit). Bei IPv6 konfiguriert cloud-init
<prefix>::1; hat der Mailserver von einer anderen Adresse des /64 gesendet (siehe PTR oderpostconf smtp_bind_address6), musst du diese Adresse nach dem Tausch auf dem Nova-Node ergänzen. - Das Hilfsskript braucht Python 3.9+ und eine Token-Datei, die nur du lesen kannst:
install -m 0600 /dev/null ~/.config/hcloud-nova-import.token # dann dein Token hineinkopieren
export HCLOUD_TOKEN_FILE=~/.config/hcloud-nova-import.token # der Pfad, nie das Token selbst
T=tools/import/Invoke-NovaHetznerPrimaryIpSwap.py
python3 $T check --legacy web1.example.org --target nova-web1 --network 1234567
python3 $T set-auto-delete-off --legacy web1.example.org --target nova-web1
python3 $T check --legacy web1.example.org --target nova-web1 --network 1234567 # muss bestehencheck nennt jede verletzte Voraussetzung (SERVER_LOCATION_MISMATCH, LEGACY_PRIMARY_IPV6_MISSING, …_AUTO_DELETE_ON, …_ASSIGNMENT_UNEXPECTED, …_LOCATION_MISMATCH, PRIVATE_NETWORK_NOT_SHARED) und zeigt Server, Primary IPs mit PTR und die Adressen im gemeinsamen privaten Netz. Hat ein Quellserver kein IPv6, ergänzt du bei jedem Befehl --ipv4-only.
Ablauf beim Cutover
Schritt 1: nova-import cutover --run RUN --legacy-frozen wie gewohnt: Einfrieren, letztes Delta, Prüfung. Danach wartet der Import vor jeder Aktivierung bei address_takeover (Exit 75) und nennt die genauen Befehle pro Quellserver, bis jede übernommene Adresse auf ihrem Nova-Node gemeldet wird.
Schritt 2: Tausch pro Quellserver (Bestätigung swap:<legacy_id>:<target_id> mit den IDs aus check; eine Zustandsdatei pro Paar, bis zum Commit aufbewahren):
python3 $T swap --legacy web1.example.org --target nova-web1 \
--state ~/nova-import/swap-web1.json --confirm swap:4711:4712Beim Tausch fahren beide Server geordnet herunter (nach --shutdown-timeout, Standard 300 s, hart), die IPs des Quellservers werden entzogen, die eigenen Primary IPs des Nodes entzogen und aufbewahrt, die bisherigen IPs dem Node zugewiesen und der Node eingeschaltet. Der Quellserver bleibt aus. Ein unterbrochener Tausch wird durch erneutes Ausführen desselben Befehls fortgesetzt; jeder Schritt liest zuerst den aktuellen Zustand und lehnt Unerwartetes ab.
Schritt 3: Schalte den Quellserver in der Hetzner-Konsole ohne öffentliche IP wieder ein: Quelldatenbank und SSH-Transferkonto bleiben über das private Netz erreichbar. Seine Dienste bleiben gestoppt.
Schritt 4: Führe nova-import cutover --run RUN --legacy-frozen erneut aus (solange Exit 75): Er prüft die Adressen auf den Nodes, aktiviert dann alles, entfernt Novas MX-Weiterleitung, bindet den ausgehenden SMTP-Verkehr des Mail-Nodes an die bisherige Mail-Adresse (mail_source) und öffnet das Fallback-Fenster. DNS-, MX- und NS-Einträge brauchen für übernommene Adressen keine Änderung.
Zum Prüfen und Reparieren der Absenderadresse gibt es auf dem Mail-Node configure-mail-source-address.php --ipv4 A --ipv6 B (--show).
Kontrolle
swapmeldetprimary_ips.legacy_ipv4/ipv6.assignee_id= der Node, die eigenen IPs des Nodes unzugewiesen, Quellserveroff, Noderunning.- Der Importschritt zeigt jede erwartete Adresse als
present. - Von außen:
curl --resolve site.example.org:443:203.0.113.10 https://site.example.org/,dig -x 203.0.113.10(PTR unverändert), SMTP-Sitzung zur MX-Adresse (Banner des Nova-Nodes) und eine Testmail an ein externes Postfach (SPF, DKIM, DMARCpass). - Auf dem Mail-Node:
postconf smtp_bind_address smtp_bind_address6 inet_interfaces.
Ablauf beim Fallback
Schritt 1: nova-import fallback --run RUN --legacy-mx-holding: Nova friert ein, gibt die Absenderadresse frei (mail_source_clear), leitet Mail über das private Netz an den bisherigen MX und spielt Rück-Delta und Rückschreiben auf den Quellserver (noch ohne öffentliche IP). Dann wartet er bei address_release (Exit 75) mit dem swap-back-Befehl.
Schritt 2: Rücktausch (Bestätigung swap-back:<legacy_id>:<target_id>):
python3 $T swap-back --state ~/nova-import/swap-web1.json --confirm swap-back:4711:4712Beim Rücktausch fahren beide Server herunter, die bisherigen IPs gehen zurück an den Quellserver, die ursprünglichen an den Node, beide starten.
Schritt 3: Führe denselben nova-import fallback erneut aus; er endet, sobald keine übernommene Adresse mehr auf dem Nova-Node liegt.
Schritt 4: Starte die Dienste der Quelle (START_LEGACY_SERVICES_AFTER_SWITCH) und prüfe wie oben. Ein späterer zweiter Cutover führt swap mit derselben Zustandsdatei erneut aus.
Abbruch und Commit
Ein cutover --abort nach dem Tausch gibt den Rücktausch aus: Führe swap-back (und configure-mail-source-address.php --clear, falls mail_source erfolgt war) aus, bevor die Quelle wieder ausliefert.
nova-import commit --confirm-irreversible schließt das Fallback-Fenster. Die bisherigen Primary IPs gehören nun dem Nova-Node (zugewiesen, auto_delete=false); den Quellserver kannst du löschen, ohne sie anzutasten. Lösche anschließend die Token-Datei.