# CDP AutoInstaller — Versionsprotokoll Aktuell öffentlich: **3.0.0** Aufruf: `curl -fsSL https://installer.ctpf.network/cdp/ubuntu26/nginx/one-click-installer | sudo bash` Dieses Protokoll ist die transparente Liste für Entwicklung, Fehlerbehebung und die spätere Installationsanweisung. Ältere Pakete bleiben unter `https://autoinstall.ctpf.network/releases/`. ## Linie 3.0 — nach vier Testlaeufen ### 3.0.0 — 2026-09-08 Vier Laeufe auf einem frischen Ubuntu 26.04, vier Abbrueche. Alle vier sind behoben, und zu jedem steht hier, woran es lag. **1. Postfix brach ab.** `myhostname` bekam die IP-Adresse des Servers, und Postfix lehnt eine reine Zahl ab. Ein frischer Server hat noch keinen Namen, und der Installer fragt auch keinen ab. Er bildet den Namen jetzt selbst aus der eigenen Adresse: aus 203.0.113.7 wird `203-0-113-7.ctpf.network`. Eine einzige Stufe, deshalb spaeter mit einem Wildcard vereinbar. Der Name steht auch im selbstsignierten Zertifikat. Den richtigen Hostnamen setzt der Betreiber danach im Panel. **2. Die Abschlusspruefung scheiterte an CDPGuard.** Der Dienst `cdpguard-telemetry` lief nicht. CDPGuard ist das lizenzpflichtige Modul und gehoert nicht in eine Grundinstallation: seine Dienste werden nicht mehr installiert, nicht gestartet und nicht geprueft. Der Schutz des Servers bleibt vollstaendig, er haengt an ufw und fail2ban und nicht an CDPGuard. Das Modul kommt spaeter ueber sein eigenes Paket. **3. Das Panel lieferte PHP-Dateien aus, statt sie auszufuehren.** Im nginx-Baustein stand `try_files $uri.php`. try_files reicht eine gefundene Datei unveraendert durch, ohne sie noch einmal durch die Regel fuer .php zu schicken — der Browser bekam die Anmeldeseite als Datei zum Herunterladen. Jetzt uebernimmt `rewrite`, die Anfrage laeuft erneut durch die Regeln und landet bei PHP-FPM. Nachgestellt und geprueft, bevor ausgeliefert wurde. **4. Apache landete auf dem Server.** `roundcube-core` empfiehlt apache2, und apt installiert Empfehlungen mit. Roundcube wird jetzt mit `--no-install-recommends` installiert, und die Abschlusspruefung bricht ab, wenn trotzdem ein apache2-Paket auf dem Server liegt. Alle uebrigen Paketzeilen des Installers wurden daraufhin durchgesehen: keine weitere zieht einen Webserver nach. **Ausserdem.** Die Abschlusspruefung nennt jetzt, was gefehlt hat, statt nur "Validierung fehlgeschlagen" zu melden. Die sichtbaren Meldungen des Ablaufs sind einsprachig englisch. Bezugsquelle ist installer.ctpf.network. ## Linie 2.0 — Auslieferung ueber installer.ctpf.network, Panel im C-Muster ### 2.0.0 — 2026-09-08 **Bezugsquelle.** Der Aufruf lautet jetzt curl -fsSL https://installer.ctpf.network/cdp/ubuntu26/nginx/one-click-installer | sudo bash Der Pfad benennt Produkt, System und Webserver-Unterbau. Eine Fassung fuer ein anderes System oder einen anderen Unterbau steht spaeter daneben, ohne dass an diesem Zweig etwas geaendert werden muss. autoinstall.ctpf.network bleibt unberuehrt bestehen. **Payload aus dem laufenden Panel.** Backend und Frontend stammen aus dem Stand, der auf dev.fra und lon laeuft. Im Backend waren gegenueber dem bisherigen Payload zehn Dateien gar nicht enthalten (unter anderem cdpguard-ip-enrichment, cdpguard-web-enforcement, session-revocation, tools-cron, tools-system-update, die Routen cdpguard-nginx-monitor und cdpguard-tracking sowie die Migrationen 008 und 009), 25 weitere wichen ab. **Kein Vue mehr.** Das bisherige Payload lieferte ein Vite/Vue-Frontend mit neun Dateien aus, das mit dem laufenden Panel nichts mehr zu tun hatte. Es ist entfernt. Ausgeliefert wird das PHP-Frontend, Bootstrap und Font Awesome liegen oertlich unter core/assets, kein fremder Host. **Frontend im reinen C-Muster.** Im Wurzelverzeichnis liegen nur noch index.php als Front Controller und robots.txt neben components, config, content, controller und core. Die 22 bisherigen Seitendateien aus dem Wurzelverzeichnis liegen jetzt unter content//index.php, _module.php unter components/layout/module.php, auth-check.php unter controller/auth/check.php. Die Adressen bleiben unveraendert: /dashboard, /tools, /domains, /domains/, /domains//dns. Die vier Teilstuecke unter content/cdpguard//index.php heissen jetzt panel.php, weil index.php unter content/ eine Seite bezeichnet. **nginx.** Der Verwaltungs-Vhost auf 8443 reicht nicht mehr an Node durch, sondern bindet den Baustein cdp-php-panel.conf ein: Docroot ist das Frontend, zuerst eine echte Datei, dann .php — das haelt /controller/auth/login und die Aufrufe unter /controller/api/ erreichbar —, sonst uebernimmt der Front Controller. Die beiden rewrite-Regeln fuer /domains/ entfallen, das macht jetzt der Front Controller. Node laeuft weiter auf 127.0.0.1:9443, wird aber nur noch serverseitig angesprochen. **PHP-FPM.** Neuer Pool cdp-panel mit eigenem Sockel /run/php/php8.5-fpm-cdp-panel.sock und eigenem Sitzungsverzeichnis /var/lib/php/sessions-cdp-panel, damit der phpsessionclean-Timer die Panel-Sitzungen nicht mit der Vorgabe anderer Pools loescht. **Rechte.** Das Frontend gehoert root, Verzeichnisse 755, Dateien 644; PHP-FPM liest als www-data. Das Backend bleibt bei dnsmaster. ## Linie 1.3 — Kundenserver statt Entwicklungsserver Ziel: alles, was auf dem Panel-Server von Hand entstand, laeuft im Installer von selbst und ohne Werte, die nur dort stimmen. ### 1.3.0 — 2026-08-25 *(noch nicht veroeffentlicht)* **Mailsystem.** Bisher legte der Installer Postfix, Dovecot und OpenDKIM nur an, ohne sie zu verbinden: es gab keinen Benutzer `vmail`, keine virtuellen Domains, keine Kennwortdatei und keinen Beipack fuer Dovecot. Ein Kunde legte ein Postfach an, sah eine Erfolgsmeldung und verlor die Post. Neu ist der vollstaendige Aufbau nach `MAILSTACK-AUFBAU.md`: Benutzer `vmail` mit fester uid und gid 5000, `/var/vmail`, die Kennwortdatei samt der Rechte auf dem **ganzen** Pfad (Dovecot braucht `+x` auf jedem Verzeichnis, sonst scheitert jede Anmeldung), der Dovecot-Beipack mit `mail_driver`/`mail_path`/`mail_inbox_path` auf `~/Maildir`, die Postfix-Grundwerte samt virtueller Familie und SASL ueber Dovecot, die vier Karten, sowie Einlieferung auf 587 und 465 ueber `postconf -M`/`-P` statt Anhaengen an `master.cf`. **OpenDKIM.** Der Installer erzeugte einen Schluessel fuer `localhost` und signierte damit jede ausgehende Mail. Der oeffentliche Teil steht in keiner Kundenzone, die Pruefung beim Empfaenger schlaegt fehl — das ist schlechter als gar keine Signatur, weil DMARC darauf aufsetzt. Neu wird nur das Geruest angelegt; die Schluessel entstehen je Domain. Reste frueherer Laeufe werden entfernt. Die Selbstpruefung sieht mit `ss` nach, worauf der Dienst wirklich hoert, statt `/etc/default/opendkim` zu glauben — die systemd-Einheit liest diese Datei nicht. **Zertifikate fuer Mail.** Neu ist `cdp-mail-sni-sync`: es liest den Zertifikatsbestand, schreibt daraus die SNI-Karte fuer Postfix und die `local_name`-Bloecke fuer Dovecot und laedt die Dienste nur bei Aenderung neu. Der Erneuerungs-Haken unter `renewal-hooks/deploy` ruft es auf. Ohne ihn bricht das System nach 90 Tagen leise: Nginx laedt nach, Postfix und Dovecot nicht. **HTTP/3 und `reuseport`.** Fehlten vollstaendig. Neu sind drei Bausteine unter `/etc/nginx/snippets/`. `reuseport` steht ausschliesslich im Baustein fuer den `default_server` auf 8443, weil die Angabe je Adresse und Port nur einmal vorkommen darf. In beiden Bausteinen steht der Hinweis, dass eine Freigabe fuer `443/tcp` HTTP/3 nicht abdeckt — QUIC laeuft ueber UDP. **Falsche Ankuendigung behoben.** `domain-ssl.js` band `snippets/ctpf-http3-extra.conf` ein, eine Datei, die es auf keinem Server gibt, und kuendigte gleichzeitig per `Alt-Svc` HTTP/3 an. Jeder neu erzeugte `mail.`- oder `webmail.`-Vhost haette den Neustart von nginx verhindert. Der Verweis zeigt jetzt auf `cdp-http3-443.conf`. **`nginxSite`.** Der Name des Panel-Vhosts entstand zur Laufzeit aus `os.hostname()`. Auf Servern, deren Hoster einen eigenen Maschinennamen vergibt — Leaseweb etwa `VM-` — zeigte er auf eine Datei, die es nicht gibt, und jede schreibende Aktion brach ab. Neu heisst der Vhost fest `cdp-panel` und enthaelt genau **einen** Server-Block; `replaceAllServerNames()` kann dort also nichts mitreissen. Der Verwaltungszugang auf 8443 bleibt getrennt in `cdp-management`, sein Catch-all bleibt unberuehrt. Die Werte stehen jetzt in `config.json`, statt abgeleitet zu werden. **Sperre gegen Punkt-Dateien.** Die erzeugten Vhosts lieferten `/.git/config` mit **200** aus, weil die Anfrage im SPA-Rueckfall auf `index.html` landete. Ein versehentlich abgelegtes `.git` waere damit vollstaendig abrufbar gewesen. Der Block `CDP_WS_SECURITY` steht jetzt in allen Erzeugern, im TLS-Serverblock vor `location /` und hinter `location ^~ /.well-known/acme-challenge/`. Die Reihenfolge ist wichtig: die ACME-Location ist eine Praefix-Location und hat Vorrang vor regulaeren Ausdruecken, die Zertifikatserneuerung bleibt also unberuehrt. **DNS-Betriebsart.** `/etc/ctpf` wurde nie angelegt, deshalb brach auf einem Kundenserver jede Zonenaktion sofort ab. Neu legt der Installer das Verzeichnis und eine kommentierte `connect-domain.env` an. `CDP_DNS_MODE` kennt `ctpfdns` (DNS-Dienst des Anbieters), `own` (eigener PowerDNS) und `none` (Zonen liegen woanders). Ohne Eintrag gilt `none`, und das Panel meldet das verstaendlich, statt gegen einen fremden Server zu laufen. **Fremde Werte entfernt.** Die Zonenvorlage trug die Entwicklungs-IP in vier A-Eintraegen, feste Nameserver, eine fremde SOA und fremde Meldeadressen in CAA und DMARC. Alles laeuft jetzt ueber Platzhalter, die aus der Konfiguration gefuellt werden; nicht aufloesbare Eintraege werden uebersprungen, statt kaputt geschrieben zu werden. Die PowerDNS-Bruecke faellt nicht mehr auf eine fremde Adresse zurueck und ermittelt die eigene IPv4 selbst. **Firewall.** Fehlte vollstaendig. Neu ist `lib/firewall.sh` nach dem auf dem Panel-Server erprobten Regelwerk: `ufw` mit `deny incoming`, aktiv und neustartfest, die zehn oeffentlichen TCP-Dienste und **getrennt davon** 443/udp und 8443/udp, weil eine Freigabe fuer `443/tcp` HTTP/3 nicht abdeckt. Dazu fail2ban mit sechs Ueberwachungen: `sshd` (streng), `postfix` (bewusst zahm, weil fremde Mailserver sich nie anmelden und eine Sperre still verlorene Post bedeutet), `dovecot`, `nginx-http-auth`, `nginx-botsearch` und ein eigener Filter auf das Sicherheitsprotokoll des Panels, der Kundenseiten ausdruecklich ausnimmt. Die Ausnahmeliste entsteht aus genau einer Quelle und umfasst die eigenen Adressen des Servers, sonst sperrt das Panel sich beim Aufruf seiner selbst aus. **Port 22 — die Stelle, an der ein Installer den groessten Schaden anrichtet.** `CDP_ADMIN_SSH_SOURCES` ist serverabhaengig. Ist der Wert leer, greift die Beschraenkung **nicht** und Port 22 bleibt offen; ein Installer, der den Zugang zumacht, ohne zu wissen woher der Betreiber kommt, sperrt den Kunden aus seinem frischen Server aus. Zusaetzlich prueft der Installer, ob die laufende SSH-Sitzung von einer der angegebenen Adressen kommt — tut sie es nicht, bleibt Port 22 ebenfalls offen, samt Hinweis. Lieber ein zu weit offener Port als ein unerreichbarer Server. Eingrenzen geschieht danach von Hand mit `cdp-fw-restrict-ssh`, das dieselbe Pruefung noch einmal anstellt. **Kein Totmannschalter.** Es gibt mit Absicht keinen Mechanismus, der die Beschraenkung auf Port 22 selbsttaetig wieder aufhebt. So etwas war gebaut, erprobt und wurde auf Weisung des Betreibers vollstaendig entfernt. Das ist eine getroffene Entscheidung, kein Versaeumnis; der Vermerk steht im Kopf von `lib/firewall.sh` und in der erzeugten `firewall.conf`, damit niemand es „nachbessert". **Erreichbarkeitstests.** Duerfen nicht auf dem geprueften Server laufen: Verkehr an die eigene Adresse geht ueber `lo` und wird durchgewinkt, der Test besteht dann immer. Der Installer sagt das am Ende ausdruecklich. **Sicherungsdateien.** Im Payload lagen zwei `.bak`-Kopien von Quelldateien, die an Kunden ausgeliefert worden waeren — dasselbe Muster, das auf dem Panel-Server zwei Lecks verursacht hat, wo `.bak`-Dateien mit HTTP 200 ausgeliefert wurden. Sie sind aus dem Baum entfernt, und die Vorpruefung bricht ab, sobald eine Sicherungsdatei im Paket liegt. Das ist ein Abbruch und kein Hinweis, weil in diesem Fall das Paket fehlerhaft ist und nicht der Kundenserver. **Abgleich mit dem Panel-Server.** Siebzehn Backend-Dateien auf den dort abgenommenen Stand gebracht, darunter die Bereichspruefung in `routes/dns.js`, die Zaehlung in `dashboard-data.js`, der gemeinsame Filter in `domain-hierarchy.js` und die Herkunftsliste in `index.js`. **phpMyAdmin.** Das Backend erwartet die Anwendung unter `/opt/controldeskpanel/cdp-apps/phpmyadmin`, der Installer legte sie unter `/var/www/cdp-apps/phpmyadmin` ab. Pfade angeglichen. **Prueffsumme.** `MANIFEST.sha256` deckte nur einen Teil des Baums ab, war seit mehreren Fassungen ungueltig und wurde von niemandem geprueft. Neu deckt sie den ganzen Baum ab, und die Vorpruefung sieht sie an. **Webmail.** Der Roundcube-Vhost lauschte auf `server_name webmail localhost` und ausschliesslich auf Port 80. Er konnte damit fuer keine Kundendomain je zustaendig werden — auf dem Panel-Server ist er zwar angelegt, aber nicht freigeschaltet, und alle acht Namen `webmail.` liefern dort die Platzhalterseite der jeweiligen Website aus. Zertifikat und DNS-Eintrag kuendigen also einen Dienst an, den es nicht gibt. Neu hoert der Vhost auf `webmail.*`, leitet von 80 auf 443 weiter und bietet TLS, HTTP/3, HSTS und `Alt-Svc`. `install_roundcube()` setzt Ablagepfad und PHP-Socket ein, legt die Datei mit Modus 0644 an und schaltet sie frei. **Webmail, das Henne-Ei-Problem.** Beim ersten Lauf gibt es noch kein Zertifikat von Let's Encrypt, und ein Vhost, der auf eine fehlende Datei verweist, laesst nginx nicht starten. Der Block nutzt deshalb zunaechst das selbstsignierte Zertifikat aus `/etc/controldeskpanel/tls/`, wie der Verwaltungszugang auf 8443. Stellt das Panel spaeter fuer eine Domain ein Zertifikat aus, schreibt `domain-ssl.js` einen eigenen Vhost mit vollstaendigem `server_name`; ein exakter Name gewinnt in nginx gegen den Platzhalter, der Grundvhost tritt dann von selbst zurueck. Damit der Baustein `cdp-http3-443.conf` schon dasteht, bevor `install_nginx` laeuft, ist er als `ensure_http3_snippets()` aus `lib/nginx.sh` herausgeloest. **Webmail, Sperren.** Punkt-Dateien und Sicherungsdateien sind auch dort gesperrt, dazu `config/`, `temp/`, `logs/`, `bin/`, `SQL/` und `installer/`. Roundcube haelt seine Datenbank-Zugangsdaten im Klartext unter `config/`; bei einer Anwendung wiegt eine offene Ablage schwerer als bei einer Platzhalterseite. **Zweiter toter Verweis in `domain-ssl.js`.** Der erzeugte Webmail-Vhost band `snippets/fastcgi-php.conf` ein. Diese Datei ist eine Beigabe der Debian-nginx-Pakete; der Installer nutzt nginx von nginx.org, dort gibt es sie nicht. Auch dieser Verweis haette beim naechsten `nginx -t` zugeschlagen. Ersetzt durch `fastcgi_params` mit ausgeschriebenem `SCRIPT_FILENAME`, wie in `cdp-phpmyadmin.conf`. **Webmail, Anmeldung gegen die lokalen Dienste.** Roundcube sprach IMAP und SMTP unverschluesselt ueber `localhost` an. Neu liegt unter `templates/roundcube/cdp-mail.inc.php` der Zusatz, der `ssl://mail.%d:993` und `tls://mail.%d:587` setzt und die Pruefung des Gegenuebers eingeschaltet laesst. `%d` ist der HTTP-Name ohne die erste Marke, aus `webmail.beispiel.de` wird also `mail.beispiel.de` — genau der Name, fuer den Dovecot und Postfix per SNI das Zertifikat der Domain vorzeigen. **Webmail, PHP 8.5.** Roundcube 1.6.11 deklariert `array_first()` selbst, PHP 8.5 bringt die Funktion mit, und jede Anfrage endet mit HTTP 500. Der Installer haette auf einem frischen Server ein totes Webmail hinterlassen. Neu fasst `ensure_roundcube_php_guard()` die Deklaration in `function_exists` ein, so wie es stromaufwaerts geloest wurde. Der Schritt prueft vorher, ob PHP die Funktion ueberhaupt mitbringt, und ist wiederholbar anwendbar. Eine Aktualisierung von `roundcube-core` nimmt die Aenderung zurueck; das ist in `MAILSTACK-AUFBAU.md` vermerkt. **`domain-ssl.js` vollstaendig durchgesehen.** Nach dem dritten toten Verweis war klar, dass es ein Muster ist. Entfernt sind jetzt auch `include /etc/letsencrypt/options-ssl-nginx.conf` und `ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem` — beide Dateien entstehen nur, wenn certbot mit dem nginx-Beipack laeuft, und der Installer stellt ueber `--webroot` aus. Beide haetten den erzeugten Mail- und Webmail-Vhost beim naechsten `nginx -t` scheitern lassen, und zwar erst **nachdem** die Dateien schon freigeschaltet waren. **`domain-ssl.js`, ACME-Wurzel.** Der erzeugte Mail-Vhost bediente `/.well-known/acme-challenge/` aus `/var/www/mail.`, der Webmail-Vhost aus dem Roundcube-Verzeichnis. In der Erneuerungsdatei von certbot steht fuer beide Namen der Webroot des Apex. Die Erneuerung waere nach rund sechzig Tagen ins Leere gelaufen und erst mit dem Ablauf des Zertifikats aufgefallen. Beide Stellen zeigen jetzt auf `/var/www/`. **`domain-ssl.js`, Dovecot.** `upsertDovecotLocalName()` legte `99-cdp-ssl-sni.conf` an, ohne nachzusehen, ob der Name schon anderswo definiert ist. Auf einem eingerichteten Server verwaltet `cdp-mail-sni-sync` die `local_name`-Bloecke in `98-cdp-virtual.conf` — es waere eine Doppeldefinition entstanden und Dovecot haette nicht mehr geladen. Neu wird nichts geschrieben, wenn eine andere Datei den Namen bereits fuehrt. **Webmail-Vhost, erzeugt wie von Hand.** `writeWebmailVhost()` und `writeMailVhost()` erzeugen jetzt dieselbe Gestalt wie die Vorlage: Port-80- Block mit Weiterleitung, TLS-Block mit HTTP/3, HSTS, `Alt-Svc`, Punkt-Datei- und Sicherungsdatei-Sperre sowie die Sperre auf `config/`, `temp/`, `logs/`, `bin/`, `SQL/` und `installer/`. Nachgemessen auf dem Panel-Server: das Erzeugnis besteht `nginx -t`. **Auslieferungsumfang.** `CHANGELOG.md`, `ERRORS.md` und `changelog.html` sind Entwicklungsunterlagen: der Installationsablauf liest sie nicht, auf dem Kundenserver landen sie nirgends, und sie nennen aus historischen Gruenden fremde Produktnamen. Sie bleiben im Quellbaum, gehoeren aber nicht ins Archiv. Neu ist `RELEASE-EXCLUDE` mit der Liste und dem Packbefehl. `MANIFEST.sha256` fuehrt jetzt genau die 207 Dateien, die ausgeliefert werden — nicht mehr den Quellbaum. Ein Probelauf hat das Archiv gepackt, ausgepackt und geprueft: Integritaetspruefung ohne Abweichung, Vorpruefung auf Sicherungsdateien bestanden. Wer die Liste erweitert, muss das Manifest neu berechnen. **Testdaten.** `payload/backend/test/domain-files-security.test.js` pruefte die Abschottung der Domainwurzeln gegen zwei **echte** Domains des Betreibers. Der Test bestand ausschliesslich deshalb, weil deren Vhosts auf dem Entwicklungsserver eingerichtet sind: `listDomains()` liest die tatsaechlich vorhandenen Vhosts und `domains-meta.json`, und fuer eine unbekannte Domain antwortet der Endpunkt mit 404, bevor die Sicherheitspruefung ueberhaupt greift. Auf jeder anderen Maschine lief der Test also ins Leere, ohne das anzuzeigen. Er legt sich jetzt seine eigene Umgebung an — eine Konfiguration in einem Wegwerfverzeichnis, auf die `CDP_CONFIG` zeigt, mit zwei fuer Beispiele reservierten Namen und eigenen Wurzeln — und raeumt sie wieder ab. Zweimal hintereinander ausgefuehrt: beide Male gruen, ohne Rueckstaende. **Offen und veroeffentlichungshindernd: die Panel-Oberflaeche.** Das Paket liefert weiterhin die Vue-Einzelseiten-Anwendung aus, nicht das PHP-C-Muster. `install_payload` kopiert `payload/frontend` mitsamt gebautem Buendel nach `/opt/controldeskpanel/frontend`, und `cdp-management.conf.template` reicht `location /` an den Node-Dienst durch, der das Buendel ausliefert. Ein PHP- Frontend liegt im Payload nicht — null Dateien. Der Baustein, mit dem der Panel-Server die PHP-Oberflaeche ausliefert, ist im Quellbaum unbekannt. Einzelheiten, Abstand und der Weg dorthin stehen in `INSTALLER-LUECKEN.md` unter P0. Bis dahin darf 1.3.0 nicht veroeffentlicht werden. **Pruefungen, die nichts geprueft haben.** `verify_manifest` zaehlte nur Zeilen, die auf `: FAILED` enden. Eine Datei, die im Manifest steht und im Archiv fehlt, erzeugt aber `: FAILED open or read` — das Muster griff nicht, der Zaehler blieb bei null, und ein unvollstaendiges Archiv wurde mit "MANIFEST.sha256 OK" durchgewinkt. Jetzt brechen fehlende **und** veraenderte Dateien ab, mit getrennter Zaehlung und den ersten zwanzig Fundstellen im Klartext; zusaetzlich faellt ein gekuerztes Manifest ueber den Abgleich der Anzahl auf. Nachgewiesen an einem gepackten Probearchiv: unberuehrt laeuft durch, eine geloeschte Datei bricht mit Code 40 ab, eine verfaelschte ebenso, beide zusammen ebenso, eine zusaetzliche Datei erzeugt einen Hinweis ohne Abbruch. Dieselbe Krankheit an drei weiteren Stellen, alle behoben: die Vorpruefung auf Sicherungsdateien meldete "keine gefunden", wenn `payload/` gar nicht da war (`find` schreibt nach stderr, das wurde verworfen, die leere Ausgabe sah aus wie ein bestandener Test) — sie bricht jetzt ab, wenn die zu pruefenden Verzeichnisse fehlen. Die Portpruefung meldete "Ports frei", wenn `ss` nicht vorhanden ist — sie sagt jetzt, dass sie nichts pruefen konnte. Und die Suche nach Zugangsdaten im Dienstprotokoll bestand, ohne eine einzige Zeile gelesen zu haben; sie zaehlt jetzt erst die Zeilen und meldet, wenn es keine gab. **Eine Zusage, die die Abnahme nicht einloesen kann.** Der Abruf der Panel-Adresse in `validate_install` lief unter der Ueberschrift "Oeffentlich", findet aber auf dem geprueften Server selbst statt: Verkehr an die eigene Adresse geht ueber `lo` und wird am Paketfilter vorbeigefuehrt. Die Zeile heisst jetzt "vom Server selbst erreichbar" und sagt ausdruecklich dazu, dass sie nichts ueber die Erreichbarkeit von aussen aussagt. Ist kein Hostname gesetzt, wurde der Abruf frueher stillschweigend uebersprungen — das steht jetzt als Hinweis da. **Sprache der Ausgabetexte.** `lib/tools-panel.js` trug einunddreissig fest eingebaute deutsche Texte, die unabhaengig von der gewaehlten Sprache hinausgingen: sieben geworfene Fehler, der Rest sichtbare Hinweise. Bei einem zweisprachig ausgelieferten Panel bekommt ein englischsprachiger Kunde damit deutsche Meldungen. Alle einunddreissig sind auf Englisch umgestellt, passend zu den uebrigen Meldungen des Backends, die zu rund siebzig Prozent englisch sind. Deutsche **Kommentare** bleiben, die gehen an niemanden hinaus. Damit ist die Datei sauber, das Gesamtbild aber nicht: im Backend stehen weiterhin 163 deutsche Ausgabetexte in fuenfzehn Dateien, die meisten in `routes/domains.js` (44), `lib/tools-db.js` (21) und `routes/tools.js` (20). Eine Umstellung auf reines Englisch waere nur die halbe Antwort — sie macht das Backend einsprachig statt zweisprachig. Der richtige Weg steht in `INSTALLER-LUECKEN.md`; er ist eine Entscheidung ueber die Bauweise und wurde bewusst nicht gebaut. --- --- ## Linie 1.2 — Ubuntu 26.04, ein Durchgang Ziel: leerer Ubuntu-26.04-Server, ein Befehl, danach Panel unter https://:8443/. ### 1.2.33 — 2026-08-24 **Bug:** Dashboard und Domainliste zeigen nach der Installation Panel-IP, Hostname, localhost, webmail und den Leaseweb-Maschinenname als Domains. Der Hostname gehoert zum CDP, nicht in die Domainliste. Der Kunde denkt, das seien seine Sites. **Behebung:** Domainzaehler und Domainliste zeigen nur Kunden-Domains. Installer-vHosts (`cdp-management`, `cdp-webmail`, `cdp-acme-80`) und Systemnamen (IP, localhost, webmail, Panel-Hostname, Maschinen-Primary) bleiben unsichtbar. Der Kasten unter `========` sagt das auf Englisch: Domains bleibt leer, bis eine Kundensite angelegt wird. SSL/Datenbanken/Cron nach der Installation sind der Installer-Stack. Live-Panel auf .230 unverändert. ### 1.2.32 — 2026-08-24 **Bug:** Der Kasten unter `========` war zweisprachig (Englisch + Deutsch). Der Kunde braucht ein fertiges English-Only-Access-Block. Passwoerter muessen dort stehen. **Behebung:** Derselbe Kasten nur noch Englisch: URL, User, Password, 2FA, License, phpMyAdmin, MariaDB password, plus Installer-Stack-Hinweis. Deutsch in diesem Block entfernt. Live-Panel auf .230 unverändert. ### 1.2.31 — 2026-08-24 **Bug:** Nach der Installation zeigt das Dashboard Domains, SSL, Datenbanken und Cronjobs. Der Kunde denkt, das seien seine Sites. Unter `========` stand nur der Zugang, keine Anweisung. **Behebung:** Derselbe Kasten, Englisch zuerst: die Zahlen sind der Installer-Stack (Panel-IP, Webmail, selbstsigniertes Zertifikat, ControlDeskPanel + Roundcube, System-Cron). Kunden-Domains kommen spaeter. Live-Panel auf .230 unverändert. ### 1.2.30 — 2026-08-24 **Bug:** CDP-Zugang und Anweisungen nach der Installation erscheinen nur auf Deutsch. Die erste Distribution muss zuerst Englisch zeigen. **Behebung:** Konsole zuerst English (`CDP access`, Start installation?), danach Deutsch (`CDP Zugang`, Installation starten?). Live-Panel auf .230 unverändert. ### 1.2.29 — 2026-08-24 **Bug:** Nach PHP OK stirbt `npm ci` mit `ECONNRESET` / `errno -104`. `registry.npmjs.org` wird zuerst über IPv6 aufgelöst. Cloudflare reißt die Verbindung mitten im Download. Nachweis: park.fra `178.162.245.208`. **Behebung:** Node/npm holen die Registry zuerst über IPv4 (`NODE_OPTIONS=--dns-result-order=ipv4first`). Gilt für Payload-`npm ci` und Bootstrap-npm. Live-Panel auf .230 unverändert. ### 1.2.28 — 2026-08-24 **Änderung:** Sprachauswahl sitzt in der Anmelden-Karte neben Sign in. Ubuntu-Zeile bleibt weg. Live-Panel auf .230 unverändert. ### 1.2.27 — 2026-08-24 **Änderung:** Login kompakter. Ubuntu-Zeile und Sprachauswahl entfernt. Scrollbalken im CTPF-Grün, falls die Seite trotzdem höher ist. Live-Panel auf .230 unverändert. ### 1.2.26 — 2026-08-24 **Änderung:** RAM-Tor 8 GB → 6 GB. Das ist der kleinste Leaseweb-VPS. Die Prüfung nimmt 5500 MB an, damit MemTotal unter 6144 nach Hypervisor-Reserve nicht rot wird. Live-Panel auf .230 unverändert. ### 1.2.25 — 2026-08-24 **Änderung:** Login ohne Kopf- und Fußleiste. Sprachauswahl unter der Ubuntu-Zeile. Copyright unter der Anmelden-Karte. Eine Ansicht ohne Scrollen. Live-Panel auf .230 unverändert. ### 1.2.24 — 2026-08-24 **Bug:** CDPGuard-Seite zeigt NOT_READY / ERROR, obwohl Dienst, nftables und Recovery in Ordnung sind. Die Readiness-Ampel wertet Shadow/Detect-only wie einen Defekt. **Behebung:** Solange nur die Enforcement-Sperre greift (Shadow, Detect-only, Canary aus), zeigt die Übersicht SHADOW / OK. Echte Ausfälle (Firewall, Datenbank, Recovery) bleiben ERROR. Live-Panel auf .230 unverändert. ### 1.2.23 — 2026-08-24 **Bug:** Login-Logo sitzt als schwarzes Rechteck auf dem Navy-Hintergrund. Die PNG-Platte hat keinen Alpha-Kanal. **Behebung:** Login nutzt das transparente Foundation-Logo. Live-Panel auf .230 unverändert. ### 1.2.22 — 2026-08-24 **Bug:** Wizard bleibt in Schritt 2, obwohl Let’s Debug grün ist. Node `resolve4` fragt die Provider-Resolver. Die kennen den neuen Namen oft noch nicht (`ENOTFOUND`). Let’s Encrypt fragt öffentliches DNS. **Behebung:** Wizard prüft A-Records über 1.1.1.1 / 8.8.8.8. Live-Panel auf .230 unverändert. ### 1.2.21 — 2026-08-24 **Bug:** Let’s Debug / Certbot HTTP-01 → `403 Forbidden`. `/var/www` und `/var/www/acme/.well-known` waren `700`. nginx (User `nginx`) kommt nicht durch. PTR ist unbeteiligt. **Behebung:** Gesamte ACME-Kette `755`. Wizard setzt die Rechte vor Certbot erneut. Live-Panel auf .230 unverändert. ### 1.2.20 — 2026-08-24 **Bug:** Neue Installation übernimmt interne Todo-Aufgaben aus der Entwicklung (.230 / lokal), inkl. interner Texte (smarfie, Dashboard-Farben). NOGO. **Behebung:** Todo startet leer. Kein Seed. Live-Todos auf .230 unangetastet. ### 1.2.19 — 2026-08-24 **Bug:** Login-Sprache English, nach Hostname-Speichern alles Deutsch. Die Tools-Seite lud fest `locale=de`. Servereinstellungen waren fest auf Deutsch. **Behebung:** Tools folgen der Login-Sprache. Servereinstellungen EN/DE. Sprache wird nach dem Login gehalten. Live-Panel auf .230 unverändert. ### 1.2.18 — 2026-08-24 **Bug:** Nach dem Login stehen die Versionsnummern unter *available* / *verfügbar*. Dummy denkt, alles müsse nochmal installiert werden. Die Zahlen sind installiert, die Überschrift sitzt nur daneben. Dieselbe Zahl nochmal unter *available* wirkt wie eine To-do-Liste. **Behebung:** Echte Tabellenköpfe über den Spalten. Installierte Version bleibt links. Rechts nur noch eine neuere Version, Beschriftung *update* / *Update*. Live-Panel auf .230 unverändert. ### 1.2.17 — 2026-08-24 **Bug:** Rot `nginx.service is not active, cannot reload.` plus SysV-`enable nginx`, obwohl der Dienst danach sauber startet. **Behebung:** Ist nginx noch nicht aktiv → `start`. Nur wenn er schon läuft → `reload`. `enable` still. ### 1.2.16 — 2026-08-24 **Bug:** Nach dem Skeleton: `The "--no-dev" option does not exist.` `composer require` kennt `--no-dev` nicht. **Behebung:** `composer require --update-no-dev --update-with-all-dependencies laravel/framework:13.26.1`. Liegt das Skeleton schon da (Fehlversuch 1.2.15), wird nur das Framework nachgezogen. ### 1.2.15 — 2026-08-24 **Bug:** `Could not find package laravel/laravel with version 13.26.1`. 13.26.1 ist **laravel/framework**. Das Skeleton `laravel/laravel` endet bei **13.10.0**. **Behebung:** `create-project laravel/laravel 13.10.0`, danach `composer require laravel/framework:13.26.1`. Halbfertiges `/opt/cdp-apps/laravel` vom Fehlversuch wird entfernt. ### 1.2.14 — 2026-08-24 **Bug:** Nach `Composer successfully installed` blinkt nur der Cursor. `composer --version` / `create-project` warten auf TTY (Telemetrie, Superuser, Update-Check). Bootstrap-npm war stumm. **Behebung:** `COMPOSER_NO_INTERACTION=1`, `COMPOSER_ALLOW_SUPERUSER=1`, `--no-interaction`. Fortschritt für Bootstrap und Laravel sichtbar. ### 1.2.13 — 2026-08-24 **Bug:** Docker-Repo `NO_PUBKEY 7EA0A9C3F273FCD8` — `/etc/apt/keyrings/docker.gpg` unlesbar oder falscher Dateityp (wie nginx in 1.2.5). Bricht nach Certbot beim nächsten `apt-get update`. **Behebung:** Schlüssel immer als lesbare `.asc` (644) neu schreiben, **vor** dem ersten `apt-get update`. Altes `docker.gpg` entfernen. **Funktion:** Sprache der ersten Distribution: **English** zuerst (Standard), **Deutsch** als zweite Wahl. Auswahl als Liste (Plesk-Stil), weitere Sprachen später nur anhängen. Live-Panel auf .230 unverändert. ### 1.2.12 — 2026-08-24 **Funktion:** Sprachauswahl **Deutsch / English** auf Login, Passwort vergessen und Lizenz. Standard der ersten Distribution: **Deutsch**. Live-Panel auf .230 unverändert. ### 1.2.11 — 2026-08-24 **Funktion:** Öffentliche Auth-Seiten vollständig im CTAS-Aufbau: Kopfzeile 80px, Hero mit Logo, Karte, immer sichtbares 2FA-Feld, Fußzeile. Gilt für Login, Passwort vergessen und Lizenz. Farben von ctpf.network. Titel: **Login auf CTPF Server**. Live-Panel auf .230 unverändert. ### 1.2.10 — 2026-08-24 **Funktion:** Login nach der Installation im CTAS-Aufbau (mittig, Karte, Icon-Felder). Farben von ctpf.network (`#131b25`, `#1c2434`, Akzent `#3bd671`). Titel: **Login auf CTPF Server**. Keine WehrDich-Farben. Live-Panel auf .230 unverändert. ### 1.2.9 — 2026-08-24 **Bug:** `mv: '/etc/opendkim/keys/default.private' and '.../default.private' are the same file` **Behebung:** `opendkim-genkey` legt die Datei schon im Zielordner an. Überflüssiges `mv` auf sich selbst entfernt. Ziel: leerer Ubuntu-26.04-Server, ein Befehl, danach Panel unter `https://:8443/`. ### 1.2.8 — 2026-08-24 **Bug:** `npm audit` mit zwei **moderate** Meldungen (`dockerode`, `uuid`) hat die Installation abgebrochen. **Behebung:** Moderate und High werden nur noch gemeldet. Die Installation läuft weiter. Nur **critical** stoppt. ### 1.2.7 — 2026-08-24 **Bug:** `Unable to locate package php8.5-opcache`. **Behebung:** Auf Ubuntu 26.04 gibt es dieses Paket nicht. Zend OPcache steckt in `php8.5-cli` / `php8.5-fpm`. Paket aus der Liste genommen. Geprüft: PHP 8.5.4. ### 1.2.6 — 2026-08-24 **Bug:** Nach dem Fehlversuch 1.2.4 blieb ein kaputter nginx.org-Eintrag (alte `.gpg`) liegen. Der nächste Lauf starb schon bei `apt-get update`, bevor der neue Schlüssel gesetzt wurde. Symptom wirkte wie „nginx 1.31.4 fehlt“ — das stimmte nicht. 1.31.4 liegt bei nginx.org für Resolute. **Behebung:** Schlüssel und Repo werden **vor** dem ersten `apt-get update` neu geschrieben. ### 1.2.5 — 2026-08-24 **Bug:** `NO_PUBKEY 2FD21310B49F6B46`. Die Datei `/etc/apt/keyrings/nginx-archive-keyring.gpg` war für `apt` nicht lesbar bzw. falsches Dateiformat. **Behebung:** Schlüssel als lesbare `.asc` (Rechte 644), immer neu geschrieben. ### 1.2.4 — 2026-08-24 **Funktion:** Nach der Installation zeigt das Dashboard eine Schritt-für-Schritt-Hilfe (einfaches Deutsch/Englisch). Immer nur der aktuelle Schritt: 1. Hostname setzen 2. DNS A auf die Server-IP 3. Zertifikat holen (`https://name:8443/`) Schritt 2 erscheint erst, wenn Schritt 1 erledigt ist. ### 1.2.3 — 2026-08-24 **Funktion:** Vor der Installationsfrage eine Kundenliste: was der Server braucht, dann jede Prüfung grün/rot, dann Urteil. Sprache Englisch, so dass jemand ohne Linux-Kenntnis versteht, warum es geht oder nicht. Geprüft u. a.: root, Ubuntu 26.04, 4 CPU, 8 GB RAM, 40 GB frei. ### 1.2.2 — 2026-08-24 **Funktion:** OS-Tor zuerst. Ubuntu 26.04 = grün *An installation on this server is possible.* Anderes System (z. B. 24.04) = rot *An installation on this server is not possible.* Keine Änderung am Server. ### 1.2.1 — 2026-08-24 **Bug:** `curl | bash` endete nach „SHA-256 OK“. Die Frage *Installation starten?* las von der Pipe (kein Tastatur), Antwort war leer = Abbruch. Zusätzlich löschte der Bootstrap das Entpack-Verzeichnis beim `exec`. **Behebung:** Fragen lesen von `/dev/tty`. Paket bleibt liegen. Die Rückfrage *Installation starten?* bleibt. ### 1.2.0 — 2026-08-24 Erste 1.2-Linie. Ein Durchgang auf frischem Ubuntu 26.04: - nginx **1.31.4** (nginx.org), PHP **8.5** FPM Distro (8.5.4; 8.5.9 gibt es im Repo nicht) - MariaDB, phpMyAdmin, Postfix, OpenDKIM, Dovecot, Roundcube - Certbot, Docker, Composer, Laravel **13.26.1**, Bootstrap - 14-Tage-Installationslizenz, **2FA aus** - Selbstsigniertes TLS auf Port 8443 - CDPGuard, grüne Statusliste, Zugangsdaten einmalig kopierbar Hostname und Let’s Encrypt erst nach dem Login im Panel. --- ## Linie 1.1 — Vorgänger Öffentlich archiviert, nicht mehr der One-Click-Standard: 1.1.0 … 1.1.13 (2026-08-21) --- ## Feste Anforderungen (Stand 1.2.26) | Anforderung | Wert | |---|---| | Betriebssystem | nur Ubuntu **26.04** (24.04 reicht nicht) | | CPU | mindestens 4 Kerne | | RAM | mindestens 6 GB | | Freier Speicher | mindestens 40 GB | | Rechte | root / `sudo bash` | | nginx | 1.31.4 (nginx.org) | | PHP | 8.5.4 (Ubuntu-Paket, OPcache eingebaut) | | Laravel | 13.26.1 | --- ## Öffentliche Dateien - One-Click: https://autoinstall.ctpf.network/one-click-installer - Dieses Protokoll: https://autoinstall.ctpf.network/changelog - Markdown: https://autoinstall.ctpf.network/releases/CHANGELOG.md - Pakete: https://autoinstall.ctpf.network/releases/cdp-autoinstaller-1.2.33.tgz ### domain-ssl.js: die drei Reste aus der Durchsicht (2026-08-26) - **certbot laeuft ueber `--webroot` statt `--nginx`.** `issueDomainSslPackage()` rief certbot mit `--nginx` auf, waehrend der Zertifikatsbestand mit `--webroot` ausgestellt ist. Ein einziger Panel-Lauf haette die Erneuerungsart einer bestehenden Domain still umgeschrieben, und `--nginx` setzt `options-ssl-nginx.conf` und `ssl-dhparams.pem` voraus — Dateien, die es ohne das nginx-Beipack nicht gibt. Jetzt bekommt jeder Name sein eigenes `-w`: Apex, `www.`, `mail.` und `webmail.` teilen sich den Webroot des Apex, eine echte Unterdomain ihren eigenen, wenn er existiert. Dazu `--key-type ecdsa`. - **PHP-Socket wird abgeleitet.** `phpFpmSocket()` sucht in `/run/php` nach `php-fpm.sock` und waehlt die hoechste Fassung ueber einen Zahlenvergleich — ein Zeichenvergleich legte `8.10` vor `8.5`. Rueckfall ist der unversionierte Socket. Vorher stand `php8.5` fest im erzeugten Vhost. - **`mail.` liefert keine Webseite mehr aus.** Der Name wird fuer IMAP und SMTP gebraucht. `writeMailVhost()` legte bisher `/var/www/mail.` mit einer Platzhalterseite an und wechselte damit beim ersten Lauf, was unter dem Namen ausgeliefert wird. Jetzt: kein Dokumentenwurzelweg, kein PHP, keine Datei, auf Port 443 ein `return 404`. Der Port-80-Block bleibt fuer ACME, weil die Anfrage sonst im Auffangblock landet, der aus einem anderen Verzeichnis ausliefert; der Port-443-Block bleibt, damit der Name sein eigenes Zertifikat vorzeigt statt das einer fremden Domain. ### Mailkennwoerter: Hinweis fuer `lib/mail.sh` Die Kennwortdatei unter `/root` ist tabulatorgetrennt, die Benutzerdatei `/var/lib/controldeskpanel/mail/users` doppelpunktgetrennt. Wer beide anfasst, verrutscht leicht. Regel: ein Klartextkennwort laeuft nie durch eine Ausgabe und nie ueber einen Aufrufparameter — `doveadm pw -p ` steht in der Prozessliste. Gehasht wird ueber die Standardeingabe mit `openssl passwd -6 -stdin`. Ein Reload ist nicht noetig: Dovecot liest die `passwd-file` bei jeder Anmeldung neu, sobald sich die Aenderungszeit unterscheidet. ### Fremde Herkunft aus dem Tools-Katalog entfernt (2026-08-26) Der Katalog von Tools & Einstellungen stammte textlich aus dem Vorbild eines fremden Panels. Sichtbar war das nicht, weil `adaptText()` den fremden Produktnamen zur Laufzeit durch die eigene Marke ersetzte — im Quellbaum stand er trotzdem, bis in die Dateinamen hinein. Eine Neuinstallation haette alles wiederhergestellt, was auf dem Live-System bereits entfernt war. Uebernommen aus dem bereinigten Stand: - Die beiden Katalogdateien trugen den fremden Produktnamen im Dateinamen. Sie heissen jetzt `data/tools-{de,en}.json`; die alten sind entfernt. 270 Schluessel je Sprache wurden auf 223 gekuerzt, die uebrigen gehoerten zu Funktionen, die es hier nicht gibt. - `adaptText()` ist ersatzlos weg. Eine Funktion, die zur Laufzeit fremde Namen ueberschreibt, verdeckt nur den naechsten Fund. - `getToolDefinition()` beantwortet nur noch Kennungen aus `SECTIONS` oder `TOOL_META`. Vorher genuegte ein Treffer in der Textdatei, womit jede fremde Kennung ueber `/api/tools/item/` abrufbar war. Der Katalog ist jetzt eine Erlaubnisliste, keine Sperrliste. - Umbenannte Bereiche: die drei Bereiche, die nach fremden Erweiterungen hiessen, heissen jetzt `firewallProtection`, `administrativeAccess` und `performanceTuning`; der Bezeichner der SOA-Vorgabe heisst `DEFAULT_SOA`. - Neu: `lib/tools-access.js` fuer den administrativen Zugang. Liest `ufw status numbered` und den Port aus `sshd_config`, rein lesend. - Entfernt: der Verweis auf ein fremdes Community-Forum in einer Antwort der Schnittstelle, und der Kommentar mit dem fremden Produktnamen, der beim Speichern in die `php.ini` geschrieben wurde. - Panel-Adresse aus einer Quelle: `customizePanelAccessInfo()`, `serviceNodesInfo()` und `remoteApi` in `routes/tools.js` bauen sie jetzt ueber `getPanelEndpoint()` und `panelBaseUrl()`, statt aus dem Kurznamen des Rechners und einem fest getippten Port. - Sprachvorgabe wieder Englisch, Reihenfolge `['en', 'de']`, an allen drei Stellen in `tools-panel.js`. Bewusst abweichend vom Live-Stand: die Fehlermeldungen mit einem Ternaer aus deutschem und englischem Text sind auf **Englisch** reduziert, nicht auf Deutsch. Ein zweisprachig ausgeliefertes Panel mit englischer Vorgabe darf keine fest eingebauten deutschen Meldungen tragen. Bewusst **nicht** uebernommen: die Sitzungsbuchfuehrung in `tools-panel.js` (`sessionRef`, `withSessions`, `rk`/`jti`, `forgetPanelSessionByJti`) und `routes/auth.js`. Sie haengen an `lib/session-revocation.js`, das es in diesem Baum nicht gibt, und die Arbeit daran ist noch nicht abgeschlossen. Der Quellbaum behaelt hier seinen bisherigen Stand. ### Weitere fremde Namen im Payload Ein Suchlauf ueber alle Dateien hat ausserhalb des Katalogs gefunden: - `lib/domain-web-server.js`: der Kopfkommentar nannte das fremde Vorbild. - `lib/dns-store.js`: Kopfkommentar mit fremdem Produktnamen und einem fremden Domainnamen als Beispielzone, dazu ein zweiter Kommentar. - `routes/domains.js`: ein fremder Domainname als fest eingetragener Protokollpfad in der Verkehrsschaetzung. Der Eintrag ist entfernt; die Schleife faellt auf den allgemeinen Pfad zurueck. - `frontend/src/composables/useI18n.js`: Kommentar. - `frontend/src/views/ToolDetailView.vue`: die **sichtbare** Ueberschrift des SOA-Bereichs nannte das fremde Vorbild. Dieselbe Zeichenkette steckte im gebauten Buendel und ist dort mitgeaendert worden. Nicht angefasst, weil es Wertungen braucht: - `CHANGELOG.md`, `ERRORS.md` und `changelog.html` nennen den fremden Produktnamen dreimal in Prosa, als historischen Vergleich. Sie liegen im Wurzelverzeichnis, nicht im Payload, und werden vom Installationsablauf nicht auf den Kundenserver kopiert — sie reisen aber im Archiv mit. - Im gebauten Buendel steht zweimal ein alter Eigenname als Rueckfallwert des Scope. Das ist ein Vorgabewert, keine Beschriftung; ein blindes Aendern wuerde Verhalten aendern. ### Das Frontend im Payload laesst sich nicht aus seiner Quelle nachbauen Beim Suchlauf aufgefallen und wichtiger als die Fundstellen selbst: `payload/frontend/src` enthaelt 10 Dateien mit 5 Ansichten, das ausgelieferte Buendel dagegen 22 Ansichten. Die Quellen zu `DomainsView`, `FirewallView`, `EmailView`, `DatabaseView` und weiteren fehlen. Ein `npm run build` in diesem Baum erzeugte also kein gleichwertiges, sondern ein verstuemmeltes Panel. Zwei Folgen: Zeichenketten in den fehlenden Ansichten lassen sich nur im Buendel selbst aendern, und vor einer Veroeffentlichung gehoert geklaert, welcher Quellstand das ausgelieferte Buendel erzeugt hat.