Installation

Schritt für Schritt von vorbereiteten Hosts zu einer laufenden Nova-Installation – Steuerhost, Agent-Fabric, stufenweises Einschalten, Lizenz, weitere Nodes und erste Kunden.

Überblick

Dieses Kapitel installiert Nova Control Panel auf neuen Hosts, die du nach Voraussetzungen vorbereitet hast. Es folgt der Reihenfolge, die sich auf echten Hosts mit Ubuntu 24.04 und Debian 13 bewährt hat (eigener Panel-Port 8443).

Hinweis: Das signierte Release-Bundle stellen wir für den Release Candidate auf Anfrage bereit; öffentlich erscheint es mit Release 1.0 am 1. Dezember 2026. Probe das ganze Kapitel zuerst auf Wegwerf-Hosts deines Anbieters, bevor du einen Server installierst, auf den es ankommt.

Befehle laufen als root. Die Beispiele verwenden diese Namen – ersetze sie durch deine:

NameBeispielBedeutung
SRC/root/nova-srcInstallationsquellen des Releases (Eigentümer root)
IN/root/nova-inputsInstaller-Eingaben, Verzeichnis 0700, jede Datei 0600, sofern nicht anders angegeben
PKI/root/nova-fabric-pkiAgent-Fabric-Authority (nur auf dem Steuerhost)
PANELpanel.example.netPanel-Name, Zertifikatsname und Lease-Peer-Name
COORDcontrol.example.netZertifikatsname des Koordinators
FLEET10.0.0.10 (mehrere Hosts) oder 127.0.0.1 (ein Host)Fleet-Adresse des Steuerhosts
PLATFORMubuntu2404 oder debian13Plattform des Release-Bundles
KEYS/root/nova-trustRelease- und Lizenz-Schlüssellisten (keys/release/<n>.json, keys/license/<n>.json, jeweils mit ihrer .sig-Kette)

Ablauf

  1. Release-Bundle bereitstellen.
  2. Installer-Eingaben, Agent-Fabric-Authority und Vertrauens-Eingaben erzeugen.
  3. Installationsprofil schreiben (alles aus).
  4. Auf dem Steuerhost: stage, install, verify und accept.
  5. Agent-Fabric und den Node Agent des Steuerhosts einrichten.
  6. Ausführung einschalten und die Ebenen stufenweise aktivieren (eine Rekonfiguration je Stufe): Leser, dann MFA-Einrichtung und Step-up (TOTP des Owners einrichten), dann Schreiber.
  7. Mehrere Hosts: zuerst eine Lizenz installieren, dann jeden weiteren Node vorbereiten, aufnehmen und aktivieren.
  8. Server und PHP-Laufzeiten registrieren, dann Pläne und Kunden anlegen.
  9. Optionale Funktionen: DNS-Secondaries, weitere Web-Nodes, Firewall, Website-Backups, Workspace.

Eine Neuinstallation startet inert: Der Installer verweigert ein frisches Profil, das irgendein Schreib-, Zustell- oder Serving-Flag einschaltet. Funktionen schaltest du später per Rekonfiguration ein. Backup-Downloads sind bei einer Neuinstallation eingeschaltet (Profil v28 ohne native_backup_download): Sie funktionieren, sobald die Schreiber-Stufe (6.6) die internen Listener bedient, ohne weiteren Schritt (siehe Backups).

Topologie wählen

Die Zahl der Hosts bestimmst du (1 bis 64). Jeder Host erhält einen sortierten Rollensatz aus master, web, mail, database, dns-primary, dns-secondary (siehe Überblick). Zwei Formen decken die meisten Installationen ab:

FormHostsFleet-AdresseLizenz nötig
Ein Hostein Host mit database,dns-primary,mail,master,web127.0.0.1nein (Community erlaubt genau 1 Server)
Mehrere Hostsder Steuerhost (master plus weitere Rollen; in jedem bewährten Layout auch web, das er später nie verlieren kann), höchstens ein DNS-Primary, bis zu 8 DNS-Secondaries (nie auf dem Host des Primary), beliebig viele Web-, Mail- und Datenbank-Hostsdie private Adresse des Steuerhosts (Hetzner Cloud: seine Adresse im angehängten privaten Netzwerk)ja, für die volle Node-Zahl, vor dem zweiten node-register (Abschnitt 7.0)

1. Release-Bundle bereitstellen

Lege das signierte Release-Bundle für deine Plattform auf dem Steuerhost ab. Die Beispiele verwenden das kombinierte Archiv /root/cand/combined-$TAG.tar.gz und das darin verwendete Application-Archiv /root/cand/app-$TAG.tar.gz; $TAG steht für die Kennung des Releases.

sh
mkdir -m 0700 -p /root/cand /root/stage-parent
python3 "$SRC/tools/application-release/NovaCombinedCandidate.py" verify /root/cand/combined-$TAG.tar.gz
sha256sum /root/cand/app-$TAG.tar.gz /root/cand/combined-$TAG.tar.gz
  • Das versiegelte Paket-Bundle enthält keine Hardware-Firmware, keinen CPU-Microcode und kein Ghostscript. PDF-Vorschauen im Workspace rendert der Browser (pdf.js), deshalb braucht kein Host Ghostscript.
  • Der Workspace lässt sich nur einschalten, wenn das Release-Bundle das native Workspace-Bundle enthält. Produktionshosts kompilieren nie etwas. Siehe Workspace.
  • Das Archiv muss root gehören und darf nicht für Gruppe oder Welt beschreibbar sein. Dasselbe gilt für den Installer, den du ausführst ($SRC/src/installer/operations/install-nova-combined-runtime.py), und den Verifier daneben. Diese Installationsquellen sind die vertrauenswürdige Quelle dieses Releases. Bewahre sie auf, bis das nächste Upgrade abgenommen ist.

2. Eingaben

2.1 Agent-Fabric-Authority (Steuerhost)

Die internen Lease-Listener im Profil brauchen die Client-CAs der Agent-Fabric je Zweck. Lege deshalb zuerst die Authority an:

sh
sh "$SRC/src/installer/operations/nova-agent-fabric.sh" authority-init "$PKI" "$COORD" "$FLEET"
for p in user-access web mail database dns; do cp "$PKI/lease-$p-ca.pem" "$IN/lease-$p-ca.pem"; done
  • COORDINATOR_ADDRESS ($FLEET) muss 127.0.0.1 oder eine RFC-1918-Adresse dieses Hosts sein. Der Koordinator bindet $FLEET:19443.
  • Die CAs gelten 3650 Tage, Blattzertifikate standardmäßig 825 Tage (optionales viertes Argument). Erneuerung: Zertifikate.
  • Bewahre $PKI nur auf dem Steuerhost auf. Es enthält den Schlüssel der Agent-CA.

2.2 Geheimnisse und Zugangsdaten

Erzeuge die Geheimnis- und Konfigurationseingaben mit dem Eingabe-Werkzeug. Es schreibt sie genau in den Formaten, die der Installer prüft, behält bereits vorhandene Dateien und gibt nie Geheimnisse aus:

sh
php "$SRC/src/api/bin/nova-installer-inputs.php" init "$IN" \
    --mail-from noreply@example.net --smtp-host smtp.example.net \
    [--smtp-port 587] [--smtp-tls starttls|implicit] [--smtp-helo $PANEL] \
    [--smtp-username USER --smtp-password-file FILE] [--owner-username admin]
php "$SRC/src/api/bin/nova-installer-inputs.php" verify "$IN" [--gateway-root-key /root/nova-workspace-pki/gateway-root-key]

Es erzeugt die Datenbank- und Owner-Passwörter, owner-input.json, jeden 32-Byte-Schlüssel, die MFA- und Support-Keyrings, den VAPID-Schlüssel und beide Mail-Konfigurationen, dazu profile-inputs.json mit jedem Pfad und einer neuen public_id_key_id, die du ins Profil übernimmst.

Wichtig: Führe init --overwrite nie für ein installiertes System aus.

Den Rest erzeugst du selbst:

EingabeWie erzeugenProfilfeld
TLS-Zertifikat und Schlüssel des Panelsein Zertifikat für $PANEL (für Produktion eine öffentliche CA; die Kette muss von Browsern als vertrauenswürdig erkannt werden)tls.*
PKI der Operations-Bridgeeine private CA; ein Client-Zertifikat mit CN api_<8-64 chars of A-Z a-z 0-9 _ -> und extendedKeyUsage=clientAuth; ein Server-Zertifikat mit subjectAltName=IP:127.0.0.1 und serverAuth. Lösche den CA-Schlüssel danach.operations.*, --bridge-server-certificate, --bridge-server-key
Zugangsdaten des Workspace Gatewayphp "$SRC/src/api/application/bin/nova-workspace-fabric.php" authority-init /root/nova-workspace-pki (gibt die vier Werte workspace_gateway.*_source_file aus)workspace_gateway.*
Fleet-Topologiesiehe 2.3native_dns.topology_source_file

Hinweise:

  • Das Panel-Zertifikat, lease-*-ca.pem und die Gateway-Zertifikate dürfen 0644 sein. Alles andere bleibt 0600 root.
  • secrets.dns_encryption_key_source_file versiegelt jedes TSIG-Geheimnis. Diese Datei wird von einer späteren Installation nie ersetzt. Bewahre sie auf.
  • Der ausgehende Mail-Transport verlangt verifiziertes TLS gegen den System-Trust-Store. Richte den SMTP-Host auf ein Relay, dessen Zertifikat der Host als vertrauenswürdig kennt.
  • Der Owner, den die Installation anlegt, muss TOTP einrichten, bevor er eine Aktion mit Step-up ausführt (Abschnitt 6.4).
  • Der Schlüssel der Workspace-CA (workspace-ca.key) ist die einzige Kopie. Verschiebe das PKI-Verzeichnis nach der Aufnahme in einen Offline-Speicher (siehe Workspace).

2.3 Fleet-Topologie

Ein Eintrag je Host. Node-IDs und Server-IDs wählst du selbst, sie sind aber dauerhaft.

json
{"nodes":[
  {"dns_engine":null,"node_id":"node_control_example_net_0001","roles":["database","mail","master","web"],"server_id":1},
  {"dns_engine":"bind","node_id":"node_dns1_example_net_000000002","roles":["dns-primary"],"server_id":2},
  {"dns_engine":"bind","node_id":"node_dns2_example_net_000000003","roles":["dns-secondary"],"server_id":3}
],"schema_version":3}
  • Ein Host: ein Node mit ["database","dns-primary","mail","master","web"] und "dns_engine":"bind".
  • roles sortiert, dns_engine nur auf DNS-Nodes (sonst null).
  • Node-IDs bestehen aus node_ plus 22 bis 59 Zeichen aus A-Z a-z 0-9 _ -. Jedes Werkzeug, das einen Node anlegt oder aufnimmt, verweigert alles andere.
  • Server-Referenzen (später mit nova-node-bootstrap.php verwendet) bestehen aus srv_ plus 8 bis 59 derselben Zeichen, zum Beispiel srv_control01.

2.4 Vertrauens-Eingaben für Releases und Lizenzen

Der kombinierte Installer kann während der Neuinstallation zwei Schlüssellisten festlegen (pinnen). Beide werden geprüft, bevor sich etwas ändert, und erst nach einer verifizierten Installation festgelegt. Kopiere jede Kette (1.json bis <n>.json mit ihren .sig-Dateien) unter Beibehaltung der Verzeichnisstruktur nach $KEYS:

OptionLegt festNötig für
--release-keys $KEYS/keys/release/<n>.jsondie Release-Schlüsselliste (/etc/nova-controlpanel/release-keys/release.json) und schreibt /etc/nova-controlpanel/update/config.jsonnova-update (Updates)
--update-channel stable|beta|devden einen Kanal, dem diese Installation folgt (Standard stable; braucht --release-keys)nova-update check
--dev-keys $KEYS/keys/dev/<n>.jsondie Dev-Schlüsselliste; nötig für, und nur für, --update-channel devden Dev-Kanal
--license-keys $KEYS/keys/license/<n>.jsondie Lizenz-Schlüsselliste (/etc/nova-controlpanel/license-keys/license.json)die Installation einer Lizenz (Lizenz)

Ohne --license-keys läuft die Installation als Community-Edition: genau 1 Server. Du kannst die Lizenz-Schlüsselliste später mit nova-update license trust $KEYS/keys/license/<n>.json festlegen und die Release-Schlüsselliste mit nova-update trust --role release $KEYS/keys/release/<n>.json.

Jede Installation – mit oder ohne diese Optionen – erhält vom kombinierten Installer ihre Installations-Identität (/etc/nova-controlpanel/installation.json, ncpi_...); Upgrades und Rollbacks behalten sie.

Für eine Flotte ist die Reihenfolge: Steuerhost installieren, seine Installations-ID auslesen, eine an diese ID gebundene Lizenz für die geplante Node-Zahl bestellen, installieren, dann die weiteren Hosts aufnehmen (Abschnitt 7.0).

3. Installationsprofil

Schreibe $IN/profile-install.json (0600). Verwende das aktuelle Profil v28 mit jeder Ebene aus und jedem internen Listener unvorbereitet. Die Struktur (Pfade gekürzt):

json
{
  "schema_version": 28,
  "candidate": {"source_commit": "<full commit>", "archive_sha256": "<sha256 of app-TAG.tar.gz>"},
  "database": {"dsn": "mysql:unix_socket=/run/mysqld/mysqld.sock;dbname=nova;charset=utf8mb4",
               "username": "novaapp", "password_source_file": "/root/nova-inputs/db-password"},
  "listen": {"port": 8443, "server_name": "panel.example.net"},
  "trusted_origin": "https://panel.example.net:8443",
  "tls": {"certificate_source_file": "...", "private_key_source_file": "..."},
  "operations": {"base_url": "https://127.0.0.1:9443", "timeout_ms": 3000,
                 "ca_source_file": "...", "certificate_source_file": "...", "private_key_source_file": "..."},
  "secrets": { "...": "one *_source_file per key, see 2.2" },
  "fleet_network": {"listen_address": "10.0.0.10"},
  "control_plane_web": {"instance": "nova", "sni_router": {"enabled": false}},
  "workspace_gateway": {"enabled": false, "database_name": "nova", "listen_port": 8091, "...": "four *_source_file"},
  "native_workspace": {"enabled": false, "job_cancellation_enabled": false},
  "native_database": {"enabled": false, "writes_enabled": false},
  "native_identity_administration": {"enabled": false, "writes_enabled": false, "public_id_key_id": "pak_..."},
  "native_tenants": {"enabled": false, "writes_enabled": false, "role_grants": {"client": ["core.read","sites.read"], "reseller": ["core.read","clients.read","sites.read"]}},
  "native_identity_recovery": {"enabled": false, "mail_configuration_source_file": "..."},
  "native_identity_mfa": {"enabled": false, "enrollment_enabled": false, "required_password_change_enabled": false},
  "native_content_support": {"enabled": false, "writes_enabled": false, "delivery_enabled": false, "mail_configuration_source_file": "..."},
  "native_dns": {"enabled": false, "writes_enabled": false, "topology_source_file": "/root/nova-inputs/topology.json"},
  "native_dns_secondary": {"enabled": false, "writes_enabled": false},
  "native_platform_administration": {"topology_writes_enabled": false},
  "native_user_access": {"enabled": false, "writes_enabled": false},
  "native_mail": {"enabled": false, "domain_writes_enabled": false},
  "native_web": {"enabled": false, "website_backup_enabled": false, "writes_enabled": false},
  "native_notifications": {"enabled": false, "writes_enabled": false},
  "native_capability_elevation": {"enabled": false},
  "native_mailbox_self": {"enabled": false},
  "native_service_blueprints": {"enabled": false, "writes_enabled": false},
  "native_user_access_internal": {"prepared": false, "serving_enabled": false, "listen_port": 8092, "client_ca_source_file": "/root/nova-inputs/lease-user-access-ca.pem", "client_ca_sha256": "<sha256 of that file>"},
  "native_web_internal":         {"prepared": false, "serving_enabled": false, "listen_port": 8093, "...": "lease-web-ca.pem"},
  "native_mail_internal":        {"prepared": false, "serving_enabled": false, "listen_port": 8094, "...": "lease-mail-ca.pem"},
  "native_database_internal":    {"prepared": false, "serving_enabled": false, "listen_port": 8095, "...": "lease-database-ca.pem"},
  "native_dns_internal":         {"prepared": false, "serving_enabled": false, "listen_port": 8096, "...": "lease-dns-ca.pem"},
  "native_workspace_upload": {"enabled": false, "max_file_bytes": 1073741824, "spool_capacity_bytes": 4294967296}
}

Das genaue Schema ist contracts/installation/nova-application-install-profile-v28.schema.json. native_workspace_upload ist hier aus und wird später eingeschaltet (siehe Workspace).

Lass den optionalen Abschnitt native_backup_download weg: Eine Neuinstallation schaltet dann Backup-Downloads mit 20 GiB Spool und ohne Bandbreitengrenze ein. Gib ihn nur an, wenn du etwas anderes willst, zum Beispiel {"enabled": false, "spool_capacity_bytes": 21474836480, "bytes_per_second": null}, um Downloads ausgeschaltet zu lassen (siehe Backups).

Regeln, die man leicht übersieht:

  • trusted_origin ist genau https://SERVER_NAME plus :PORT, wenn der Port nicht 443 ist. Er kann sich später nie ändern, ebenso wenig database.
  • Port-Weg des Panels (für die gesamte Lebensdauer der Installation festgelegt):
  • Eigener Port (Standard): listen.port: 8443, control_plane_web.sni_router.enabled: false, trusted_origin: https://$PANEL:8443. Das Panel läuft in apache2@nova; Kunden-Websites behalten 80/443 in apache2. Der Port darf nicht 80, 443, 9443 oder 10443 sein.
  • SNI-Router: listen.port: 443, sni_router.enabled: true, trusted_origin: https://$PANEL. HAProxy belegt :443 und verteilt nach TLS-Namen; das versiegelte Bundle enthält haproxy, und der Installer schaltet es mit dem Router ein (kein manueller Paketschritt). Lass die Kunden-Websites auf der Wildcard-Adresse.
  • fleet_network.listen_address: 127.0.0.1 auf einem einzelnen Host, sonst die private Adresse des Steuerhosts. Prüfe sie vorher mit nova-fleet-network.py detect --address $FLEET. Jeder interne mTLS-Listener und das Workspace Gateway binden nur an diese Adresse; verify und accept verweigern einen internen Port, der woanders lauscht.
  • Jeder Listener-Port unterscheidet sich von den anderen, vom Panel-Port und vom Gateway-Port.
  • Setze candidate.source_commit auf den vollständigen Commit des Releases und candidate.archive_sha256 auf die SHA-256-Summe des Application-Archivs (app-TAG.tar.gz), nicht des kombinierten Archivs.
  • role_grants legt fest, welche Capabilities Kunden und Reseller erhalten. Den empfohlenen Satz findest du in Abschnitt 6.3.

4. Den Steuerhost installieren

sh
COMB=/root/cand/combined-$TAG.tar.gz; SHA=$(sha256sum "$COMB" | cut -d' ' -f1)
P=$IN/profile-install.json; S=/root/stage-parent/stage-$TAG
I="python3 $SRC/src/installer/operations/install-nova-combined-runtime.py"

python3 "$SRC/tools/application-release/NovaCombinedCandidate.py" stage "$COMB" "$SHA" "$P" "$S"
$I install "$COMB" "$SHA" "$P" "$S" --package-mode bundled --owner-input "$IN/owner-input.json" \
    --bridge-server-certificate "$IN/ops-server.crt" --bridge-server-key "$IN/ops-server.key" \
    [--license-keys $KEYS/keys/license/<n>.json] \
    [--release-keys $KEYS/keys/release/<n>.json [--update-channel stable|beta|dev] [--dev-keys $KEYS/keys/dev/<n>.json]]
$I verify "$COMB" "$SHA" "$P" "$S"
$I accept "$COMB" "$SHA" "$P" "$S"

Erwartete letzte Zeilen:

text
PASS: combined Nova candidate staged: <sha>
...
installation id ncpi_<26 characters> (created); request licenses for this id, see nova-update license status
PASS: combined Nova runtime installed and verified; acceptance and live gates remain open
PASS: combined Nova runtime verified
PASS: combined Nova runtime accepted; component rollback checkpoints retired

Mit --release-keys und --license-keys gibt der Installer vor der PASS-Zeile zusätzlich release keys ...: sequence <n> (...), nova-update configured: channel <c>, no source yet (nova-update configure --source-url) und license keys ...: sequence <n> (...) aus.

Was passiert: Die Paketschicht installiert das versiegelte Bundle, dann übernimmt die Host-Schicht die Rollen des Steuer-Nodes, danach folgen die Operations-Bridge, der Node Agent, die frische Datenbank, das Owner-Konto und die Application. Das Panel läuft in apache2@nova auf dem Panel-Port. Die Laufzeitkonfiguration einer frischen v28-Installation enthält native_backup_download.enabled: true, sofern das Profil nichts anderes angibt.

  • Eine fehlgeschlagene Stufe rollt die ganze Transaktion automatisch zurück. Datenbank und Owner bleiben erhalten, und auf diesem Host lässt sich danach nur dasselbe Release-Bundle erneut installieren. Musst du nach einer fehlgeschlagenen Neuinstallation ein anderes Bundle verwenden, beginne auf einem neuen Host. Ausnahme: Schlug die Installation fehl, bevor ihre erste Stufe abgeschlossen war (nichts behalten), archiviere das leere Journal mit install-nova-combined-runtime.py archive-empty und installiere das andere Bundle (siehe Wiederherstellung).
  • Bewahre $IN, das Profil und das Stage-Verzeichnis auf. Jede spätere Rekonfiguration, jedes Upgrade und jeder Rollback verweist per Pfad und Digest darauf.

5. Agent-Fabric und der Node Agent des Steuerhosts

Die kombinierte Installation hat den Node Agent auf dem Steuerhost installiert. Gib ihm jetzt eine Identität und starte den Koordinator:

sh
F="sh $SRC/src/installer/operations/nova-agent-fabric.sh"
OPSDB=/var/lib/nova-controlpanel/operations/operations.sqlite
NODE=node_control_example_net_0001   # from the topology
$F coordinator-export "$PKI" /etc/nova-controlpanel/operations/agent-coordinator nova-controlpanel-operations
$F coordinator-configure "$PKI" /etc/nova-controlpanel/operations/agent-coordinator /etc/nova-controlpanel/operations/agent-coordinator.env
$F node-request /root/fabric-node "$NODE" database,mail,master,web
$F node-sign "$PKI" /root/fabric-node/requests /root/fabric-signed
$F node-install /root/fabric-node /root/fabric-signed /etc/nova-controlpanel-node-agent tls://$FLEET:19443 "$COORD" 1 "$IN/panel.crt" \
    --owner=nova-node-agent:nova-node-agent --lease-peer-name="$PANEL" \
    user-access=https://$FLEET:8092 web=https://$FLEET:8093 mail=https://$FLEET:8094 database=https://$FLEET:8095
OPERATIONS_DATABASE=$OPSDB $F node-register "$PKI" /root/fabric-signed /opt/nova-controlpanel/operations 1
php /opt/nova-controlpanel/application/current/src/api/bin/nova-node-bootstrap.php bootstrap \
    /etc/nova-controlpanel/application-runtime.json "$NODE" srv_control01 1
  • coordinator-configure aktiviert den Koordinator für den Systemstart, startet ihn und ist nur erfolgreich, wenn er auf $FLEET:19443 lauscht ("activation":"activated").
  • Rollen und Server-ID müssen zur Topologie passen. Ein einzelner Host verwendet database,dns-primary,mail,master,web und zusätzlich dns=https://$FLEET:8096.
  • nova-node-bootstrap.php nimmt hier keine Capability-Liste. Es legt den Node-Eintrag der Application an (next_node); der Workspace braucht ihn später.
  • Bewährt hat sich, $PANEL und $COORD in /etc/hosts jedes Hosts auf die Fleet-Adresse abzubilden.
  • node-install schreibt für jeden Node mit master, web, mail oder database die Zeile NOVA_AGENT_DEFAULT_WRITE_CAPABILITIES=backup.artifact.export.v1 in runtime.env: Backup-Downloads sind die einzige standardmäßig eingeschaltete Schreib-Capability. Entferne die Zeile (oder lass sie leer), wenn ein Node seine Backups nicht exportieren soll.
  • Der Steuerhost ist Node 1 der Lizenzzählung. Die Community-Edition erlaubt genau diesen einen Server; node-register und nova-node-bootstrap.php verweigern einen zweiten Node, bis eine Lizenz installiert ist (Abschnitt 7.0).

6. Ausführung einschalten, dann die Ebenen aktivieren

Jeder der folgenden Schritte, der das Profil ändert, ist eine Rekonfiguration:

sh
# copy the ACTIVE profile (never edit it), change the copy, then reconfigure and accept
ACTIVE=$(python3 -c "import json;print(json.load(open('/var/lib/nova-controlpanel/installer/combined/transaction.json'))['profile'])")
cp -p "$ACTIVE" $IN/profile-STEP.json      # edit the copy, keep 0600 root
$I reconfigure "$COMB" "$SHA" $IN/profile-STEP.json "$S"
$I accept      "$COMB" "$SHA" $IN/profile-STEP.json "$S"

Eine Rekonfiguration muss das aktive Release-Bundle, das aktive Stage-Verzeichnis und eine neue Profildatei verwenden. Sie ändert nur die Application. Ein Fehler rollt sie auf das aktive Profil zurück.

Wichtig: Bearbeite nie das aktive Profil selbst, sondern immer eine Kopie.

6.1 Ausführungskette (keine Profiländerung)

Der Operations-Installer hat bereits OPERATIONS_EXECUTOR_PROFILE=next-native nach /etc/nova-controlpanel/operations/runtime.env geschrieben (verify und accept scheitern ohne diese Zeile; eine Datei, die ein anderes Profil nennt, wird abgelehnt). Starte Worker und Dispatcher und schalte die nativen Befehle ein:

sh
install -d -o nova-controlpanel-operations -g nova-controlpanel-operations -m 0750 /var/lib/nova-controlpanel/operations/events
systemctl daemon-reload
systemctl enable --now nova-controlpanel-operations-worker.timer nova-controlpanel-operations-dispatcher.timer
B=$SRC/src/installer/operations/install-nova-operations-http-bridge.sh
bash "$B" native-commands / on && bash "$B" accept /

Das Verzeichnis events ist der Ereignis-Spool des Dispatchers; er wird an dieser Stelle angelegt.

6.2 Web-Quota und Schreib-Capabilities des Nodes (Steuerhost)

Hat der Steuerhost die Rolle web, richte zuerst sein Quota-Volume ein:

sh
QD=/opt/nova-controlpanel-node-agent/deploy
bash $QD/nova-web-node-quota.sh setup /dev/disk/by-id/<your-volume> /var/www/nova-controlpanel
bash $QD/nova-web-node-quota.sh verify

Trage dann die Schreib-Capabilities dieses Nodes in /etc/nova-controlpanel-node-agent/runtime.env ein und starte den Agent-Timer:

sh
cat >> /etc/nova-controlpanel-node-agent/runtime.env <<'EOF'
NOVA_AGENT_WRITE_CAPABILITIES=platform.php-runtime.apply.v1,platform.server.apply.v1,platform.address.apply.v1,platform.config.apply.v1,platform.directive.apply.v1,web.execute.v1,web.php.apply.v1,web.php.rollback.v1,mail.execute.v1,database.execute.v2,access.ftp-account.apply.v1,access.shell-account.apply.v1,access.webdav-account.apply.v1,scheduling.website-cron.apply.v1
NOVA_AGENT_PLATFORM_PUBLISHER=systemd-socket-v1
EOF
systemctl enable --now nova-controlpanel-node-agent.timer
systemctl start nova-controlpanel-node-agent.service
  • Ein einzelner Host mit dns-primary ergänzt dns.zone.apply.v1,dns.keyring.apply.v1.
  • Shell-Benutzer in einem jailkit-Chroot brauchen zusätzlich access.jailkit.apply.v1.
  • Website-Cron-Jobs mit chrooted brauchen keine jailkit-Vorbereitung: Die mitgelieferte /etc/jailkit/jk_init.ini von Ubuntu 24.04 und Debian 13 hat keine Abschnitte env, php_common oder php*, deshalb hängt der Node Agent eigene Definitionen der fehlenden Abschnitte (php und php8_2 bis php8_5) an seine private Kopie /var/lib/nova-controlpanel-agent/user-access-state/website-cron-jk-init.ini an. Die Systemdatei wird nie geändert; ein dort bereits definierter Abschnitt (zum Beispiel vom bisherigen Hosting-Panel auf einem Altserver) wird so verwendet, wie er ist.
  • Ein Jail erhält nie den Alternativen-Symlink /usr/bin/php: Ein Chroot-Job einer Website ohne PHP-Modus führt die Standard-Serie des Nodes als versioniertes Binary aus (/usr/bin/php8.3 auf Ubuntu 24.04, /usr/bin/php8.4 auf Debian 13). Ein Node ohne unterstützte Standard-Serie oder ohne dieses Binary verweigert den Job mit NOVA_WEBSITE_CRON_PHP_DEFAULT_SERIES_UNAVAILABLE: Installiere das CLI-Paket der Serie oder gib der Website einen PHP-Modus.
  • Das sind die local-explicit-Schreib-Capabilities: Der Operations-Store hält sie bei der Aufnahme für die Rollen des Nodes fest (ein abgenommenes Update ergänzt neue, siehe Updates), aber der Node führt eine davon nur aus, wenn sie hier aufgelistet ist.
  • Optional: host-security.fail2ban.v1 erlaubt Administratoren, fail2ban-Sperren im Panel anzuzeigen und aufzuheben (siehe Sicherheit).
  • Die Liste ist genau das, was der Node ausführen darf. Eine Ressource, deren Capability fehlt, endet auf dem Node im Zustand error (AGENT_RUNTIME_CAPABILITY_UNAVAILABLE).
  • Capability-Sätze je Rolle stehen in der Beispieldatei nova-node-agent-runtime.env.example.

6.3 Leser und MFA-Leser (Rekonfiguration)

Setze in der Profilkopie:

  • enabled: true für native_database, native_identity_administration, native_tenants, native_dns, native_service_blueprints, native_user_access, native_mail, native_web, native_notifications und native_identity_mfa;
  • prepared: true für alle fünf native_*_internal-Listener;
  • native_tenants.role_grants auf die Capabilities, die Kunden und Reseller brauchen.

Empfohlener Satz für Kunden (client): content.read, core.read, database.create, database.delete, database.read, database.update, dns.create, dns.delete, dns.effect, dns.read, dns.update, help.read, mail.create, mail.delete, mail.effect, mail.read, mail.update, sites.create, sites.delete, sites.effect, sites.read, sites.update. Reseller erhalten denselben Satz plus clients.create, clients.delete, clients.read, clients.update (sortiert).

Noch kein Schreib-Flag: Der Installer verweigert jedes Profil, das einen Schreibvorgang einschaltet, bevor MFA-Einrichtung und Step-up aktiv sind (Abschnitt 6.4).

6.4 MFA-Einrichtung und Step-up (Rekonfiguration), dann TOTP einrichten

Setze native_identity_mfa.enrollment_enabled: true und native_capability_elevation.enabled: true (die Einrichtung braucht den abgenommenen MFA-Leser aus 6.3). Nach accept:

  1. Melde dich als Owner an, öffne Einstellungen → Sicherheit, richte den Authenticator (TOTP) ein und bewahre die zehn Wiederherstellungscodes offline auf.
  2. Bestätige an derselben Stelle die Wiederherstellungsadresse des Owners.
  3. Jeder spätere Administrator macht dasselbe, bevor er eine Aktion mit Step-up nutzt.

Der Installer lässt ein Profil mit irgendeinem nativen Schreibvorgang (*.writes_enabled, native_mail.domain_writes_enabled, native_platform_administration.topology_writes_enabled, native_web.website_backup_enabled) nur zu, wenn native_identity_mfa.enabled, native_identity_mfa.enrollment_enabled und native_capability_elevation.enabled alle eingeschaltet sind. Authenticator und Codes verloren: siehe Sicherheit.

6.5 Operations freischalten (keine Profiländerung)

Eine Neuinstallation hat keinen Alt-Executor, deshalb schaltest du jede Capability mit Rollout-Sperre einmal frei:

sh
OPERATIONS_DATABASE=$OPSDB php /opt/nova-controlpanel/operations/bin/fresh-installation-enable.php \
    platform-administration.execute 1 "Disable platform-administration.execute and restore the pre-enablement Operations store backup."
# the same for user-access.execute, and dns.zone.apply once a DNS primary node is enrolled and activated
systemctl enable --now nova-controlpanel-operations-database-engine-inventory.timer
  • Ein aktiver Node Agent muss bereits jede Schreib-Capability dieser Domäne besitzen. Bei mehreren Hosts schaltest du dns.zone.apply und dns.secondary.apply frei, nachdem die DNS-Nodes aufgenommen und aktiviert sind (Abschnitt 7).
  • Die Store-Dateien bleiben im Besitz des Operations-Dienstes; ein chown ist nicht nötig.
  • Der Inventar-Timer schreibt innerhalb von etwa einer Minute /etc/nova-controlpanel/native-database-engines.json. Ohne ihn beantwortet jede Datenbank-Anlage die Anfrage mit NATIVE_DATABASE_SERVICE_UNAVAILABLE.
  • Ein DNS-Primary auf diesem Host: Führe vor der ersten Zone /opt/nova-controlpanel-node-agent/deploy/activate-nova-bind-dynamic-zones.sh activate aus.

6.6 Schreiber (Rekonfiguration)

  • writes_enabled: true für native_database, native_identity_administration, native_tenants, native_service_blueprints, native_user_access, native_web, native_notifications;
  • native_mail.domain_writes_enabled: true;
  • native_platform_administration.topology_writes_enabled: true;
  • serving_enabled: true für alle fünf native_*_internal-Listener (mit der Voreinstellung aus Abschnitt 3 funktionieren damit auch die Backup-Downloads);
  • native_identity_recovery.enabled: true.

DNS-Schreibvorgänge kommen später (Abschnitt 7.4), weil sie die DNS-Nodes brauchen. Auf einem einzelnen Host kannst du native_dns.writes_enabled: true schon hier ergänzen.

6.7 Support-Inhalte und Postfach-Selbstverwaltung (drei Rekonfigurationen)

  1. native_content_support.enabled und native_mailbox_self.enabled;
  2. native_content_support.delivery_enabled;
  3. native_content_support.writes_enabled.

7. Weitere Hosts

Führe diese Schritte für jeden Host der Topologie außer dem Steuerhost aus.

7.0 Zuerst die Lizenz installieren

Unter der Community-Edition wird ein zweiter Node abgelehnt, bevor irgendetwas geschieht:

SchrittAblehnung ohne Lizenz für die Node-Zahl
nova-agent-fabric.sh node-registerAGENT_ENROLLMENT_LICENSE_NODE_LIMIT
nova-node-bootstrap.php bootstrapNOVA_LICENSE_NODE_LIMIT
native-topology-change.php plan (eine wachsende Topologie)NOVA_LICENSE_NODE_LIMIT: N node(s) would exceed the licensed limit of M ...

Auf dem Steuerhost, als root:

sh
nova-update license show-id                      # ncpi_...; send it with the license order
nova-update license trust $KEYS/keys/license/<n>.json   # only if --license-keys was not given at installation
nova-update license install /root/<customer>-<year>.license.json
nova-update license status                       # LICENSE ACTIVE: edition subscription, nodes 1 of <max_nodes>

Das Panel bietet dasselbe unter Einstellungen › Lizenz (der Upload braucht system.license.manage und den Step-up mit Passwort + TOTP). Lege max_nodes für die gesamte geplante Flotte aus, DNS-Secondaries eingeschlossen. Einen Node ersetzen (einen hinzufügen, einen entfernen), Rollenänderungen, Zertifikatsrotation und Widerruf werden nie abgelehnt. Die Lizenzierung stoppt nie etwas, das bereits läuft (siehe Lizenz).

Hinweis: Die Lizenzierung einer Installation mit mehreren Servern ist im Release Candidate neu. Probe sie zuerst auf Testservern.

7.1 Den Node vorbereiten

Auf dem Node, mit den Installationsquellen desselben Releases in $SRC:

sh
mkdir -p /var/lib/nova-controlpanel/installer && chmod 0711 /var/lib/nova-controlpanel /var/lib/nova-controlpanel/installer
python3 $SRC/src/installer/host/nova-host-bootstrap.py --contract $SRC/contracts/installation/nova-host-platform-v1.json \
    --mode install --roles dns --exclusive --receipt /var/lib/nova-controlpanel/installer/host-install.json    # roles: dns | web | mail | database
umask 022; sh $SRC/src/operations/deploy/install-nova-node-agent.sh $SRC/src/operations /

--roles nennt jede Rolle des Nodes (durch Kommas getrennt). Mit --exclusive deaktiviert und stoppt die Host-Schicht die Distributionsdienste, die keine Rolle aktiviert, zum Beispiel named auf einem Node ohne DNS oder das pure-ftpd der Distribution vor der FTP-Aktivierung. Der kombinierte Installer macht dasselbe auf dem Steuerhost.

Ein Web-Node richtet jetzt sein Quota-Volume ein (nova-web-node-quota.sh setup DEVICE, danach verify).

7.2 Den Node aufnehmen

Private Schlüssel verlassen den Node nie. Nur die Anfrage und die signierten Zertifikate werden übertragen.

WoBefehl
Nodesh $SRC/src/installer/operations/nova-agent-fabric.sh node-request /root/fabric-node NODE_ID ROLES (z. B. dns-primary)
kopieren/root/fabric-node/requests vom Node auf den Steuerhost
Steuerhostnova-agent-fabric.sh node-sign $PKI REQUEST_DIR SIGNED_DIR
kopierenSIGNED_DIR und das öffentliche Panel-Zertifikat auf den Node
Nodenova-agent-fabric.sh node-install /root/fabric-node SIGNED_DIR /etc/nova-controlpanel-node-agent tls://$FLEET:19443 $COORD SERVER_ID /root/panel.crt --owner=nova-node-agent:nova-node-agent --lease-peer-name=$PANEL PURPOSE=https://$FLEET:PORT ...
SteuerhostOPERATIONS_DATABASE=$OPSDB nova-agent-fabric.sh node-register $PKI SIGNED_DIR /opt/nova-controlpanel/operations SERVER_ID (gibt den Store selbst an den Operations-Dienst zurück)
Steuerhostphp /opt/nova-controlpanel/application/current/src/api/bin/nova-node-bootstrap.php bootstrap /etc/nova-controlpanel/application-runtime.json NODE_ID SERVER_REF SERVER_ID

Lease-Zwecke je Rolle:

RolleLease-Zwecke
DNSdns=...:8096
Webuser-access=...:8092 web=...:8093
Mailmail=...:8094
Datenbankdatabase=...:8095

Node-Admission. Der Koordinator und die internen mTLS-Listener der Application (Leases auf 8092–8096, Backup-Exporte) lassen einen Node nur zu, wenn er im Operations-Store registriert, aktiv und nicht aufgegeben ist; ein Zertifikat, das nur zu einer Fleet-CA führt, reicht nicht. Der Koordinator verlangt zusätzlich genau den Fingerabdruck des Agent-Zertifikats, den node-register (oder eine spätere Erneuerung) festgehalten hat. Die Lease-Listener sehen Lease-Zertifikate je Zweck, nie das Agent-Zertifikat, und entscheiden deshalb allein anhand des Nodes. Jede Anfrage fragt die Registry ab, ein Widerruf oder eine Aufgabe wirkt also ab der nächsten Anfrage (siehe Tagesbetrieb). Eine Ablehnung ist 403 (AUTHORIZATION_DENIED für Leases, NODE_IDENTITY_REQUIRED für Exporte) und wird als internal.node-admission.refused auditiert.

7.3 Den Node aktivieren

Auf einem DNS-Node:

sh
sh $SRC/src/operations/deploy/activate-nova-bind-dynamic-zones.sh activate
# primary:   NOVA_AGENT_WRITE_CAPABILITIES=dns.zone.apply.v1,dns.keyring.apply.v1,platform.server.apply.v1,platform.address.apply.v1,platform.config.apply.v1
# secondary: NOVA_AGENT_WRITE_CAPABILITIES=dns.secondary.apply.v1,dns.keyring.apply.v1,platform.server.apply.v1,platform.address.apply.v1,platform.config.apply.v1
systemctl daemon-reload
systemctl enable --now nova-controlpanel-dns-engine.socket nova-controlpanel-node-agent.timer
systemctl start nova-controlpanel-node-agent.service

Die passende Zeile NOVA_AGENT_WRITE_CAPABILITIES (Primary oder Secondary) trägst du in /etc/nova-controlpanel-node-agent/runtime.env ein.

Ein Web-Node erhält die Web-Capabilities aus Abschnitt 6.2 und führt install-nova-node-agent.sh nach dem Setzen der Capabilities noch einmal aus (sein Preflight prüft das Quota-Volume), danach finalize-nova-node-agent-update.sh / --discard-rollback.

7.4 DNS: Schreibvorgänge einschalten und Nameserver registrieren

Auf dem Steuerhost, wenn die DNS-Nodes aktiv sind:

  1. fresh-installation-enable.php dns.zone.apply 1 "<plan>" und fresh-installation-enable.php dns.secondary.apply 1 "<plan>".
  2. Rekonfiguration: native_dns_secondary.enabled: true.
  3. Rekonfiguration: native_dns.writes_enabled: true und native_dns_secondary.writes_enabled: true.
  4. Registriere als Owner jeden DNS-Node als Platform-Server nur mit dem DNS-Dienst (POST /api/next/v1/servers mit node_id, dns_server: true) und warte, bis er active ist.
  5. Veröffentliche den Endpunkt jedes DNS-Nodes im Panel (Systemverwaltung → DNS-Server & TSIG, /nova/infrastructure/dns-fleet) oder mit PUT /api/next/v1/dns-node-endpoints/{node_id} und {"nameserver_fqdn":"ns1.example.net.","node_id":"...","transfer_ipv4":"10.0.0.20","transfer_ipv6":null}. Der Name endet mit einem Punkt. Die Transfer-Adresse ist die private Adresse.
  6. Erlaube die Secondaries in den Plänen der Kunden (dns.secondary-nodes) und lege den Primary fest (dns.primary-nodes).

Nova legt dann je Primary/Secondary-Paar einen TSIG-Schlüssel an und repliziert die Primary-Zonen auf die erlaubten Secondaries. Dieselbe Panel-Seite zeigt jeden DNS-Node, seinen Endpunkt, die TSIG-Schlüsselpaare und den Keyring-Zustand und startet eine Schlüsselrotation.

8. Server, PHP-Laufzeiten, Pläne und Kunden

Als Owner im Panel (oder über die API):

  1. Lege für jeden Node, der Kundendienste trägt, einen Platform-Server mit den Diensten an, die er trägt (web_server, file_server, mail_server, db_server, dns_server). Warte, bis er active ist.
  2. Füge die PHP-Laufzeit jedes Webservers hinzu (/server-php-versions: PHP 8.3 auf Ubuntu mit php8.3-fpm, /etc/php/8.3/fpm, /etc/php/8.3/fpm/pool.d, /run/php, /usr/bin/php8.3; auf Debian entsprechend 8.4).
  3. Sobald die Laufzeit aktiv ist, veröffentliche den Web-PHP-Katalog:
sh
php /opt/nova-controlpanel/application/current/src/api/bin/nova-web-php-runtime-catalog.php reconcile /etc/nova-controlpanel/application-runtime.json <source_commit> <archive_sha256>

Die Werte für <source_commit> und <archive_sha256> stehen in /var/lib/nova-controlpanel/installer/application/active.json.

  1. Lege Kundenvorlagen (Pläne) mit Limits und Platzierungen an, danach Reseller und Kunden. Siehe Rollen und Panel.

9. Optionale Funktionen

FunktionWo
Zusätzlicher Web-NodeAnleitungen
Firewall-VerwaltungAnleitungen
Website-Backups und Backup-DownloadsBackups
Workspace (Dateimanager, Uploads)Workspace
FTPactivate-nova-pureftpd-auth.sh activate und activate-nova-pureftpd-tls.sh activate auf jedem Web-Node
SNI-Router auf 443Abschnitt 3 und Überblick
fail2ban-Jails, Admin-Netze, Entsperren im PanelSicherheit
Zertifikatsüberwachung und -erneuerungZertifikate
Spätere TopologieänderungenAnleitungen
Signierte Updates (nova-update, Release-Server, Kanal)Updates
Web-Statistik (Beta) neben AWStatsTagesbetrieb