Neu
Der Healthcheck nach dem Rollout lässt sich je Domain abschalten. Nach jedem Rollout, der eine Domain berührt, ruft der Node sie einmal lokal auf; antwortet sie nicht binnen zehn Sekunden, gilt die neue Konfiguration als fehlerhaft und wird für diese Domain zurückgenommen.
Bei einer Anwendung, die beim ersten Aufruf lange braucht, oder auf einem langsam gewordenen Server ist das Ausbleiben aber kein Urteil über die Konfiguration: die Domain wurde dann bei jeder Änderung zurückgesetzt — auch bei der, die gerade ihre Wartung einschalten sollte. Im Bereich Allgemein einer Domain steht dafür jetzt der Schalter Nach dem Rollout nicht abrufen.
Der Preis steht im Panel daneben: eine wirklich fehlerhafte Konfiguration bleibt dann stehen und fällt erst dem Besucher auf. Im Protokoll der Aufgabe steht deshalb eine Zeile, dass die Domain ohne Prüfung ausgerollt wurde.
www gehört jetzt zur Domain. Bisher zeigte
www.example.comzwar auf den Node — die eigene Zone legt den Eintrag von jeher mit an —, beantwortet wurde er dort aber vom Auffangserver: Zertifikatswarnung im Browser, Fehlerseite dahinter. Wer das ändern wollte, musste den Namen von Hand als Alias anlegen und danach das Zertifikat neu ausstellen.Jede Domain führt
wwwjetzt von selbst mit: der Name leitet dauerhaft (301) auf die Domain um und geht bei der Ausstellung als weiterer Name ins Zertifikat von Let's Encrypt. Im Bereich Aliase steht der Schalter www mitführen — eingeschaltet, auch bei bestehenden Domains — und darunter der Name als Zeile mit dem Vermerk automatisch.Zeigt
wwwnicht auf diesen Node, bleibt der Name aus der Anfrage: sonst hätte Let's Encrypt die ganze Ausstellung abgewiesen und die Domain stünde ohne Zertifikat da. Die Meldung nach der Ausstellung sagt dann, welcher Name ausgelassen wurde.Nach dem Update bedient der Node den Namen sofort, das Zertifikat kennt ihn aber erst nach der nächsten Ausstellung. Bis dahin meldet der Browser
wwwals unsicher — genau wie vorher. Der Bereich Zertifikat nennt die Lücke und den Weg dahin; von selbst wird nichts ausgestellt, weil jede Ausstellung gegen die Mengengrenzen von Let's Encrypt zählt.Protokolle werden gedreht und nach einer Frist entfernt. Bisher wuchsen sie unbegrenzt: die Zugriffs- und Fehlerprotokolle jeder Domain, die PHP-Fehler, die Ausgabe von Node.js-Anwendungen, das Protokoll der Selbstaktualisierung — nichts davon wurde je gedreht oder aufgeräumt. Eine volle Platte nimmt aber den ganzen Node mit, nicht nur die Domain, die sie vollgeschrieben hat.
Im neuen Bereich Protokolle eines Nodes stehen die Fristen: wie lange aufbewahrt wird (ab Werk 30 Tage), ab welcher Größe schon vorher gedreht wird, wie lange das Journal reicht, wie lange die von WildFly selbst gedrehten Dateien bleiben und wie lange die Ausgabe der Läufe unter Aufgaben in der Datenbank steht. Darunter steht, was die Protokolle heute belegen — je Subscription, für Kastra selbst, für WildFly und für das Journal.
Nachgesehen wird stündlich, nicht nur einmal am Tag: eine Domain in einer Fehlerschleife füllt die Platte sonst, bevor der tägliche Lauf hinsieht.
- WildFly-Protokolle werden aufgeräumt. WildFly dreht sein
server.logselbst, hat aber noch nie eine der gedrehten Dateien entfernt — nach einem Jahr lagen dort 365 Stück. Sie verschwinden jetzt nach der eingestellten Frist; die laufende Datei bleibt unangetastet. - Verzeichnisse gelöschter Domains verschwinden. Wurde eine Domain entfernt, blieb ihr Protokollverzeichnis im Heimatverzeichnis liegen und war im Dateimanager zu sehen. Es wird jetzt entfernt — aber nur, wenn ausschließlich Protokolle darin liegen und seit der Frist nichts mehr geschrieben wurde. Eine eigene Datei darin schützt das ganze Verzeichnis.
- Der Knopf „Jetzt aufräumen" führt diesen Lauf sofort aus statt nachts und zeigt danach, welche Datei entfernt wurde.
- Das Audit-Log kann eine Frist bekommen. Auf der Seite Audit-Log steht jetzt, wie lange Einträge aufgehoben werden. Ab Werk unbegrenzt — daran ändert sich für bestehende Installationen nichts.
- Eine Sitzung stellt höchstens acht Anfragen gleichzeitig. Bisher konnte ein Kunde beliebig viele Dateimanager-, Protokoll- oder Punktdatei-Aufrufe parallel anstoßen — jeder davon wartet bis zu fünf Minuten auf den Node und belegt so lange eine Verbindung. Ab der achten gleichzeitigen Anfrage antwortet das Panel jetzt mit „Zu viele gleichzeitige Anfragen dieser Sitzung"; gewöhnliches Arbeiten mit mehreren geöffneten Bereichen oder Tabs bleibt davon unberührt. Administratoren sind ausgenommen.
Wartungsmodus je Domain und Subscription. Wer an einer Seite arbeitet, hatte bisher nur zwei Wege, sie so lange vom Netz zu nehmen: die Domain abschalten oder die Subscription sperren. Beide nehmen den Vhost ganz aus der Konfiguration — der Besucher bekommt 404 für eine Adresse, die es sehr wohl gibt, und die Sperre nimmt zugleich Dateimanager, Terminal und phpMyAdmin weg, also genau die Werkzeuge, mit denen gerade gearbeitet wird.
Im neuen Bereich Wartung antwortet die Domain stattdessen mit 503 („gibt es, gerade nicht erreichbar") — die richtige Auskunft auch für Suchmaschinen, denn eine Adresse, die 404 antwortet, fällt aus dem Index. Dateien, Terminal, Datenbanken, FTP und Mail bleiben dabei offen.
Den Bereich gibt es an der Domain — dort gilt er samt Subdomains — und an der Subscription, wo er für alle ihre Domains gilt. Die Ebenen addieren sich: eine einzelne Domain kann sich von der Wartung ihrer Subscription nicht ausnehmen. Kommt die Wartung von woanders, sagt die Seite, woher, und im Kopf der Domain steht die Marke Wartungsmodus – liefert 503. Dieselbe Marke steht im Kopf der Subscription und an jeder Zeile der Domainliste — ein Wartungsmodus, den man vergisst, ist ein Ausfall, und niemand sucht ihn auf jeder Detailseite einzeln.
Ausnahmen je Adresse und Netz: wer dort eingetragen ist, sieht die Seite ganz normal und kann prüfen, ob die Arbeit fertig ist, bevor der Modus wieder aus ist. Ein Knopf trägt die eigene Adresse ein. Den Inhalt der Seite liefert die hinterlegte Fehlerseite für 503;
/.well-known/bleibt erreichbar, damit eine Wartung kein Zertifikat ablaufen lässt.Uploads laufen weiter, wenn man die Seite verlässt — und lassen sich anhalten und abbrechen. Bisher hing das Hochladen an der geöffneten Seite: wer während einer großen Datei woandershin klickte, verlor die Anzeige. Die Übertragung lief unsichtbar weiter, ohne Fortschritt und ohne Möglichkeit, sie zu beenden; solange sie lief, war der Dateimanager außerdem gesperrt.
Neben der Pille für die Hintergrundaufgaben unten rechts steht jetzt eine zweite für Uploads. Sie zeigt den Anteil in Prozent als Ring und lässt sich aufklappen: je Upload der Dateiname, der Fortschritt, die Übertragungsgeschwindigkeit, die geschätzte Restzeit — und zwei Knöpfe zum Anhalten und Abbrechen. Angehaltene Uploads machen dort weiter, wo sie stehengeblieben sind. Ist alles durch, steht die Zeile noch kurz mit einem Haken da und räumt sich dann selbst weg. Im Dateimanager stehen dieselben Zeilen über der Liste, und die Liste bleibt währenddessen bedienbar.
Ein Upload, der nicht fertig wird, räumt jetzt hinter sich auf. Ein Upload in Teilen entsteht in einem Spool-Verzeichnis und wandert erst mit dem letzten Teil an seinen Platz. Wurde er abgebrochen oder scheiterte er, blieb der angefangene Rest bisher für immer liegen und zählte gegen die Quota der Subscription — versteckt unter
tmp/.kastra-uploads/, wo niemand danach sucht. Abbruch und Fehler löschen ihn jetzt.Punktdateien: Sperre je Domain regelbar. Der Webserver hat Pfade mit einem Punkt am Anfang (
.git,.env,.htaccess) immer abgewiesen — ohne Einstellung, ohne Hinweis. Anwendungen, die einen solchen Pfad selbst benutzen, kamen damit nicht zurecht: ownCloud und Nextcloud scheiterten an jeder größeren Datei, weil ein Upload in Teilen mit einemMOVEauf.fileabschließt — die Teile gingen durch, der letzte Aufruf bekam 403.Im Bereich Webserver einer Domain steht jetzt der Abschnitt Punktdateien: die Sperre bleibt die Vorgabe, einzelne Namen lassen sich ausnehmen, und ganz abschalten geht auch. Darunter zeigt Zuletzt abgewiesen auf Knopfdruck, was die Sperre im Fehlerprotokoll dieser Domain abgewiesen hat, je Name zusammengefasst — mit einem Knopf, der den Namen in die Ausnahmen übernimmt. Vorher war dieser Fall nur zu finden, wenn jemand das Protokoll las und wusste, dass
access forbidden by rulenicht von der WAF kommt.Eigene Fehlerseiten je Statuscode. Den neuen Bereich Fehlerseiten gibt es an der Subscription (als Vorgabe für alle ihre Domains) und an der Domain (als Ausnahme für genau diese). Hinterlegen lassen sich Seiten für 400, 401, 403, 404, 405, 413, 500, 502, 503 und 504 — als HTML direkt im Panel, mit Vorschau. Bisher zeigte der Webserver dort seine eingebaute Seite mit seinem Namen darunter; gerade 502 und 504 fing auch kein Framework ab, weil die Anwendung in diesem Moment gar nicht läuft.
Vererbt wird über drei Ebenen — Subscription, Domain, Subdomain —, und die nähere gewinnt: eine Subdomain nimmt die Seite ihrer Domain, solange sie keine eigene hat. Und immer je Statuscode: wer auf der Subdomain eine eigene 400 hinterlegt, ändert damit nichts an deren 404. Neben jedem Code steht, welche Ebene ihn gerade beantwortet — bei einer geerbten Seite mit dem Namen der Domain, von der sie kommt.
Wo die Anwendung selbst antwortet, bleibt ihre Seite stehen (E-153). Ein Framework mit eigener 404 und eine
.htaccessmitErrorDocumentgelten unverändert weiter — die Seite aus dem Panel greift nur für die Codes, die sie nicht abdecken. Im Modus nginx+Apache heißt das: eine vorhandene.htaccessbehält die Oberhand, ohne dass jemand etwas umstellen muss.- Die Übersicht zeigt DNS-Probleme. Weichen veröffentlichte Einträge von dem ab, was Kastra zusagt, steht auf der Übersicht die Zahl der Beanstandungen und je betroffener Zone eine Zeile; der Klick auf die Zone führt zur Befundtafel der Domain. Bisher fiel das nur dem auf, der den Bereich DNS jeder Domain einzeln öffnete. Gezeigt wird der Stand der nächtlichen Prüfung; ein Resolver, der schwieg, zählt nicht als Beanstandung.
- Die Übersicht zeigt den Zustand der wichtigsten Dienste. Web, Mail-Versand, Mail-Abruf, DNS und die Verbindung der Agenten stehen als eine Zeile mit dem Ergebnis der aktiven Prüfungen — bei mehreren Nodes mit der Zahl, wie viele den Dienst gerade erbringen. Der Klick führt auf die Statusseite. Wer die Nodeliste nicht sehen darf, sieht das Gesamtbild mit der Zahl der Prüfungen.
- Der Record-Editor meldet, was an den Einträgen nicht zusammenpasst. Über der Liste steht eine Karte, die betroffenen Zeilen sind farbig hinterlegt, und geprüft wird schon beim Tippen. Rot heißt: der Nameserver nimmt die Zone so nicht an, das Speichern wird abgewiesen — zweimal dieselbe Zeile, oder ein CNAME neben einem anderen Eintrag unter demselben Namen. Gelb ist ein Hinweis: mehrere A- oder AAAA-Einträge unter einem Namen sind gültiges DNS und werden gespeichert, sind bei einer gehosteten Domain aber selten gewollt. Zeigt eine der Adressen ins Leere, ist die Domain nur für einen Teil der Besucher erreichbar — und weil der Browser danach die nächste probiert, wirkt sie langsam statt kaputt. Bei MX, NS, TXT, SRV und CAA ist mehrfach der Normalfall; dort meldet Kastra nichts.
- Einzelne Einträge lassen sich Kastra zur Pflege übergeben. Bisher ging das nur für die ganze Zone auf einmal. Jetzt steht bei einem Eintrag, der dem Soll-Zustand genau entspricht, in der Liste neben von Hand die Schaltfläche Kastra pflegen lassen — für den Fall, dass man den Adresseintrag abgeben, den Rest aber selbst behalten will. Im DNS ändert sich dabei nichts; es ändert sich nur, wer den Eintrag künftig nachzieht.
- FTPS bekommt ein eigenes, gültiges Zertifikat (E-151). Bisher zeigte pure-ftpd das Zertifikat des Panels vor — es lautet auf den Namen des Panels, und jedes FTP-Programm warnte deshalb beim Verbinden. Unter Nodes → Übersicht steht beim FTP-Schalter jetzt Zertifikat für FTPS: Namen eintragen, Von Let's Encrypt holen, fertig. Weitere Namen kommen als SAN ins selbe Zertifikat, erneuert wird selbstständig 30 Tage vor Ablauf, und Zurück auf das Panel-Zertifikat nimmt es wieder zurück. Es gibt genau eines für den ganzen Dienst: FTP kennt keine Auswahl je Domain, deshalb gehört jeder Name, unter dem Kunden verbinden sollen, in dieses eine hinein. In Betrieb geht jede Fassung mit dem nächsten Rollout, und der startet pure-ftpd neu — laufende Übertragungen brechen dabei ab.
- **Der Bereich FTP zeigt jetzt, was am Zugang geschehen ist** (E-150). Unter der Zugangsliste steht das Protokoll des FTP-Dienstes — an einer Subscription für alle ihre Zugänge, an einer Domain für deren eigene: Verbindung, Verschlüsselung, An- und Abmeldung, hoch- und heruntergeladene Dateien, Umbenennen und Löschen, jeweils mit Zeitpunkt und Gegenstelle. Das ist der Weg, eine abgewiesene Anmeldung zu verstehen — jedes FTP-Programm meldet sie gleich, egal ob das Passwort falsch war, der Zugang gesperrt ist oder das Programm gar nicht erst ankam. Filter schränkt auf Zeilen ein, Zeilen bestimmt, wie weit zurück gelesen wird. Sitzungen anderer Subscriptions sind nicht dabei; gefiltert wird auf dem Node, sie kommen gar nicht erst über die Leitung.
- Ein Node hat jetzt eine veröffentlichte Adresse (Plan 028, E-149). Unter Nodes → Übersicht steht je Node eine IPv4 und eine IPv6, und genau diese beiden werden als
AundAAAAin die Zone jeder Domain geschrieben, die auf ihm liegt. Leer heißt automatisch: Kastra nimmt die erste öffentlich erreichbare der gemeldeten Adressen. Einzutragen ist hier nur etwas, wenn der Node mehrere öffentliche Adressen hat oder hinter NAT steht — dort wird auch angenommen, was er gar nicht gemeldet hat, denn seine eigene öffentliche Adresse sieht er nie. Was der Node gemeldet hat, steht darunter zum Anklicken. - Eine Domain lässt sich für WildFly freigeben (E-148). Der Bereich Allgemein einer Domain hat für Administratoren den Schalter WildFly darf im Verzeichnis lesen und schreiben: der Dienstbenutzer
wildflybekommt Lese- und Schreibrecht auf das Verzeichnis der Domain, rekursiv und auch auf alles, was dort noch entsteht. Für Java-Anwendungen, die in das Domainverzeichnis schreiben oder daraus lesen — bisher ging das nur über eine Shell auf dem Node, mit Rechten, die der nächste Rollout wieder überschrieb. Was WildFly dort anlegt, bleibt für den Kunden über SFTP und für den Webserver erreichbar. Der Zugriff gilt für genau diese Domain: die Ordner ihrer Subdomains bleiben außen vor und werden einzeln freigegeben, und der Weg dorthin wird nur so weit geöffnet, dass WildFly hindurchkommt — lesen darf er auf den Zwischenstufen nichts. Es gibt aber eine WildFly-Instanz je Node, und jede Anwendung darin kommt an das freigegebene Verzeichnis heran — deshalb setzt den Schalter nur ein Administrator. Ausschalten nimmt den Zugriff wieder zurück. Fehlt dem Node das Paketacl, spielt der Agent es beim ersten Anwenden ein. - Ein Administrator kann einem Datenbankbenutzer erlauben, einen fremden DEFINER zu setzen (E-147). Ein Abzug mit einer gespeicherten Prozedur, einer Sicht oder einem Trigger trägt den DEFINER des Servers, auf dem er entstand; lautet der nicht auf das verbundene Konto, weist MariaDB das Einspielen mit #1227 — you need (at least one of) the SET USER privilege(s) ab. Unter Datenbanken → Benutzer → Rechte steht dafür jetzt das Kästchen Fremden DEFINER erlauben (SET USER). Das Recht gilt für den ganzen Datenbankserver des Nodes und nicht nur für diese Datenbank — wer es hat, kann eine Routine mit
DEFINER=root@localhostanlegen, die mit den Rechten von root läuft. Es vergibt deshalb nur die Rolle ADMIN, es steht je Benutzer einzeln, und jede Vergabe steht im Audit-Log. Der einfachere Weg bleibt, die DEFINER-Klausel aus dem Abzug zu streichen; das Handbuch zeigt beides. Solange ein Benutzer der Datenbank das Recht trägt, bekommt es auch jede phpMyAdmin-Sitzung, die danach geöffnet wird — dort meldet nicht der Zugang des Kunden an, sondern ein eigenes kurzlebiges Konto, und ohne diesen Weg bliebe das Recht im Client wirkungslos. - Eine Datenbank lässt sich aus einer Sicherung zurückspielen (Plan 027). Datenbank einspielen an einem Snapshot holt den Abzug aus dem Stand und spielt ihn in die laufende Datenbank — bisher kam er nur als
.sql-Datei zurück und ließ sich ausschließlich mit einer Shell auf dem Node einspielen. Der Dialog verlangt, dass der Name der Datenbank abgetippt wird: der Vorgang überschreibt, was seit dem Snapshot geschrieben wurde. Der Abzug liegt während des Einspielens in einem Verzeichnis, das nur root lesen kann, und ist danach wieder weg; jedes Einspielen steht im Audit-Log. - Beim Wiederherstellen steht vorher, wohin. Der Dialog fragt jetzt: in ein neues Verzeichnis (Vorgabe, rührt nichts an) oder an den ursprünglichen Ort (überschreibt). Bisher ging es immer daneben, erfahren hat man das erst aus der Erfolgsmeldung — und das Handbuch behauptete das Gegenteil. Die Liste der vorhandenen Sicherungen wird außerdem beim Öffnen geholt und liegt nicht mehr hinter Sicherungen laden.
- Zwei neue Aktionen im Bereich Sicherung: Vollständig neu einlesen startet einen Lauf, der jede Datei neu liest, statt sich auf Größe und Zeitstempel zu verlassen — der einzige Weg, eine still veränderte Datei zu bemerken. Sicherung prüfen und Daten wirklich lesen prüfen das Repository, letzteres liest dabei jeden abgelegten Block und findet Bit-Rot.
Die
standalone.xmlvon WildFly lässt sich im Panel bearbeiten (Plan 025). Der Bereich WildFly unter Laufzeiten hat eine Karte Konfiguration: Bearbeiten holt die Datei vom Node in einen Editor mit XML-Einfärbung, Strg+S speichert. Bisher führte jeder Eingriff, den die Verwaltungskonsole nicht abdeckt — ein<subsystem>aus einer Anleitung, eine Einstellung an einem Listener —, über SSH: ohne Sicherung, ohne Nachweis, und ein Tippfehler darin fiel erst auf, als der Server nicht mehr hochkam.Geschrieben wird nur, was wohlgeformtes XML mit
<server>als Wurzelelement ist; alles andere erreicht die Platte nicht. Vor jedem Speichern legt der Node die bisherige Datei unter/var/lib/kastra/wildfly/konfigab (die zwanzig jüngsten bleiben liegen), und jeder Stand bleibt als Fassung erhalten — mit Benutzer, Zeitpunkt und einer eigenen Anmerkung. Beide Listen stehen unter dem Editor, jeweils mit In den Editor und Zurückschreiben.Auch das, was die Verwaltungskonsole schreibt, steht in der Liste: legt dort jemand eine Datenquelle an, hält Kastra den vorgefundenen Stand beim nächsten Lesen als Fassung vom Node fest. Und wer speichert, während sich die Datei zwischenzeitlich geändert hat, überschreibt sie nicht aus Versehen — die Seite meldet es und fragt nach.
Wirksam wird die Datei beim nächsten Start des Servers: WildFly liest sie einmal. Kastra startet ihn dafür nicht von sich aus neu; der Knopf steht darüber.
- Eine laufende Sicherung zeigt, wie weit sie ist (Plan 026). Im Bereich Sicherung einer Subscription steht über dem Verlauf ein Balken mit 12.400 von 40.000 Dateien · 2,1 GiB von 8,4 GiB und der Datei, an der gerade gearbeitet wird; die Node-weite Liste Sicherungsprotokoll zeigt denselben Stand in der Spalte Neu / Stand. Bisher stand dort bis zum Ende nur „läuft seit …" — bei einem Lauf über mehrere Stunden war nicht zu unterscheiden, ob er vorankommt oder hängt. Der Balken rechnet nach Datenmenge, nicht nach Dateien; in den ersten Sekunden fehlt das „von", solange restic die Gesamtzahl noch zählt. Beide Seiten fragen den Stand von selbst nach, solange ein Lauf läuft.
- Die Sicherung nimmt die Datenbanken mit (Plan 024). Vor jedem Lauf zieht Kastra die Datenbanken der Subscription nach
.kastra-sicherungim Heimatverzeichnis; sie landen damit im Snapshot und das Verzeichnis wird danach wieder weggeräumt. Bisher enthielt eine Sicherung nur die Dateien — eine wiederhergestellte WordPress- oder Redmine-Installation hatte ihre Dateien und eine leere Datenbank, und der Lauf meldete trotzdem geglückt. Der Haken Datenbanken mitsichern steht im Bereich Sicherung und ist ab Werk gesetzt. Schlägt ein Abzug fehl, scheitert der Lauf — ein Snapshot, der aussieht wie eine vollständige Sicherung und keine ist, wäre schlimmer als gar keiner. - Der Zugang zum Repository lässt sich abrufen. Der Knopf Zugang zum Repository zeigt Adresse und Kennwort, mit denen sich die Sicherung ohne Kastra öffnen lässt — genau das, was im Ernstfall gebraucht wird, wenn die Control Plane nicht mehr läuft. Bisher gab es dafür keinen Weg: das Kennwort lag ausschließlich verschlüsselt in der Datenbank. Nur für Administratoren, und jeder Abruf steht im Audit-Log. Der vollständige Weg von Hand steht im Handbuch unter Wiederherstellen ohne Panel.
- Der Datenbankabzug ist nicht mehr für den Kunden lesbar. Er entsteht in dessen Heimatverzeichnis und wurde von der Shell mit 0644 angelegt — lesbar für jeden Prozess unter seinem Benutzer, also auch für eine übernommene PHP-Anwendung. Abzug und Verzeichnis gehören jetzt root mit 0600 bzw. 0700. Betrifft auch den Umzug, der denselben Abzug benutzt.
- Der Mount-Helfer eines Sicherungsziels lässt sich aus dem Panel einspielen. Bei CIFS und NFS braucht der Kernel zusätzlich
/sbin/mount.cifsbzw./sbin/mount.nfs4— fehlt er, ist alles vorhanden und plausibel und trotzdem wirkungslos: restic installiert, Ziel eingetragen, und der Verbindungstest scheitert mitunknown filesystem type. Die Zeile Sicherung im Bestand steht dann auf nur von innen erreichbar und nennt Programm und Paket; Einrichten spielt es ein. Bisher nannte die Fehlermeldung das Paket zwar, aber es gab keine Stelle im Panel, an der man es einspielen konnte. Eingespielt wird nur, was der eingerichtete Typ wirklich braucht:nfs-commonziehtrpcbindnach, und das ist ein offener Port auf einem Node, der nie NFS spricht. - Composer je Domain. Eine PHP-Domain hat den Bereich Composer: die
composer.jsonsteht dort im Editor, lässt sich ändern und speichern, und daneben stehen die Knöpfe install und update. Bis jetzt endete jede Bereitstellung im Panel vor dem letzten Schritt — wer ein Repository holte, bekam ein Verzeichnis ohnevendor/, und der Weg zu einemcomposer installführte über Terminal oder SSH. Ausgeführt wird als Benutzer der Subscription und mit der PHP-Fassung dieser Domain; die unveränderte Ausgabe steht im Protokoll der Aufgabe. Ungültiges JSON wird nicht geschrieben, und vor jedem Speichern legt Kastra die bisherige Fassung alscomposer.json.bakdaneben. Gesucht wird die Datei erst im Arbeitsverzeichnis, dann im Dokumentenverzeichnis; wer sie woanders hat, trägt das Verzeichnis am Bereich ein. - Composer steht als Komponente im Bestand eines Nodes. Der Bereich Komponenten zeigt, ob Composer eingerichtet ist; der Knopf Einrichten holt
composer.pharin einer festen Fassung, prüft die Prüfsumme und legt es nach/usr/local/bin/composer. Ohne das meldet der Bereich Composer einer Domain, dass sich nichts ausführen lässt — statt es beim ersten Versuch zu tun. - Das Sicherungsziel lässt sich ändern. Neben Verbindung prüfen steht Bearbeiten und öffnet dasselbe Formular mit den gespeicherten Werten. Bisher ging nur anlegen und entfernen — wer die SMB-Fassung nachtragen oder den Ablagepfad korrigieren wollte, musste das Ziel wegwerfen und alles neu eintippen, Schlüssel und WireGuard-Konfiguration eingeschlossen. Passwort und Schlüssel bleiben dabei leer und unverändert; nur was eingetragen wird, ersetzt den gespeicherten Wert. Den Tunnel trägt das Kästchen Tunnel entfernen aus. Nach dem Speichern steht das Ziel wieder auf ungeprüft — der letzte Verbindungstest beschreibt die alten Werte — und ein Rollout läuft sofort. Beim Typwechsel fallen die Felder des alten Typs weg, damit kein Schlüssel in der Datenbank liegen bleibt, den niemand mehr braucht.
- Eine Domain darf aus PHP heraus ein Programm starten, wenn es sein muss. Im Bereich PHP steht der Schalter Prozessstart erlauben: er nimmt
proc_openundpopenausdisable_functions, alles andere bleibt gesperrt. Gebraucht wird das von Anwendungen, die PDFs über einen mitgelieferten Browser erzeugen (Snappdf, Browsershot) oder ImageMagick über die Kommandozeile aufrufen; sie scheiterten bisher mit „The Process class relies on proc_open, which is not available on your PHP installation" — eine Meldung, die nach einer kaputten PHP-Installation aussieht und keine ist. Ändern darf den Schalter ein Administrator, sehen jeder, der die Domain sieht. Aus ist die Vorgabe und bleibt es für bestehende Domains. - WireGuard steht als Komponente im Bestand eines Nodes. Der Bereich Komponenten zeigt, ob die WireGuard-Werkzeuge da sind, ob ein Tunnel hinterlegt ist, ob er steht und wann die Gegenstelle zuletzt geantwortet hat — der Knopf Einrichten spielt
wireguard-toolsein und prüft das Kernmodul. Bisher fehlte WireGuard im Bestand ganz: ein Sicherungsziel hinter einem Tunnel scheiterte auf einem Node ohne das Paket mitUnit wg-quick@kastra-backup.service not found, und im Panel gab es keine Stelle, an der das zu sehen oder zu beheben war. - Ein Sicherungsziel kann ein Unterverzeichnis in der Freigabe benutzen. Bei CIFS, NFS und lokalen Zielen gibt es das Feld Ablagepfad in der Freigabe: die Repositories liegen dann unter
/backup/<pfad>/sub-<n>statt unmittelbar unter/backup. Gebraucht wird das, sobald sich mehrere Nodes eine Freigabe teilen — vorher wäresub-3des einen Nodes dasselbe Verzeichnis wiesub-3des anderen. Der Verbindungstest legt das Verzeichnis an und schreibt seine Probe dort statt im Einhängepunkt. - Jeder Sicherungslauf hat ein Protokoll. Hinter einem Lauf steht der Knopf Protokoll und zeigt die unveränderte Ausgabe von restic — Warnungen, übersprungene Dateien, die Zusammenfassung und welche Snapshots die Aufbewahrung weggeräumt hat. Es steht auch beim geglückten Lauf da: eine Sicherung, die Dateien übersprungen hat, ist etwas anderes als eine ohne Befund. Bisher blieb vom Lauf nur die Kennzahl.
- **Ein Node hat den Bereich Sicherungsprotokoll.** Er listet die Läufe aller Subscriptions dieses Nodes, neueste zuerst, mit demselben Protokoll dahinter. Die Frage „ist heute Nacht auf diesem Server etwas schiefgegangen" hiess vorher, jede Subscription einzeln zu öffnen.
- Die
Dockerfileeiner Container-Domain lässt sich im Panel bearbeiten. Baut ein Dienst sein Image selbst (build:stattimage:), erscheint im Bereich Container unter dem Compose-Editor ein zweiter Editor für die zugehörige Datei — mit Vorlage, wenn es sie noch nicht gibt. Sie gehört weiterhin dem Kunden und wird beim Rollout nicht überschrieben; ein Repository darf sie also mitbringen. Bisher musste man wissen, dass es sie geben muss, und sie über den Dateimanager anlegen. - Das Protokollfenster zeigt bei Container-Domains den Dienst selbst. Die neue Art Container-Dienst ist das Journal der systemd-Unit, also die Ausgabe von
podman-compose. Sie steht auch dann bereit, wenn kein Container läuft — und genau dann wird sie gebraucht: kommt es wegen einer fehlendenDockerfileoder eines unbekannten Images gar nicht erst zu einem Container, stand in der Schalterleiste bisher nur nginx. - Der Dateimanager nimmt Dateien per Ziehen entgegen. Wer Dateien oder ganze Ordner aus dem Dateimanager seines Rechners in die Liste zieht, lädt sie hoch; die Fläche zeigt beim Ziehen an, in welches Verzeichnis. Fällt der Zug auf einen Ordner der Liste, auf Eine Ebene höher oder auf eine Brotkrume, landet er dort statt im offenen Verzeichnis. Ein Ordner wird mit seinen Unterordnern angelegt — auch, wenn er leer ist. Bisher ging Hochladen nur über den Knopf, und ein danebengegangener Zug öffnete die Datei im Browser statt sie abzulegen.
- Strg+S speichert im Dateieditor. Bisher liess sich eine Datei nur über den Knopf sichern, und das Kürzel bot stattdessen an, die Panelseite zu speichern. Es wirkt im Editor wie auf den Knöpfen des Dialogs; bei einer nur ausschnittsweise geladenen Datei bleibt es wie der Knopf gesperrt.
- Eine Datenbank lässt sich für die Container ihrer Site öffnen. Neben der Erreichbarkeit steht der Schalter Container dieser Site. Er legt den Zugang zusätzlich für das Container-Netz des Nodes an — den Weg, den
host.containers.internalnimmt — und lässt sich mit „nur über localhost" kombinieren: der Container kommt herein, das Internet nicht. Das Netz liest Kastra von Podman ab, statt10.88.0.0/16anzunehmen; solange auf dem Node kein Container gelaufen ist, bleibt der Schalter gesperrt und sagt warum. Beim Anlegen einer Datenbank sind die Zugriffsquellen gleich mitzugeben, denn alle Host-Fassungen des Benutzers entstehen mit demselben Passwort. - Ein Statusblock zeigt, was auf dem Node wirklich gilt, und ein Verbindungstest geht denselben Weg wie die Anwendung. Der Test unterscheidet die Ursachen, statt „geht nicht" zu melden: kein Listener, kein passender Zugang (dann nennt er den Namen, unter dem MariaDB die Verbindung gesehen hat), oder nur das falsche Passwort. Ohne Passwort ist der Test trotzdem aussagekräftig — wird die Verbindung angenommen und nur die Anmeldung abgelehnt, stimmen Listener und Zugang.
- Die Hosts eines Datenbankbenutzers sind änderbar, und ein Passwort lässt sich selbst setzen. Bisher standen die Hosts beim Anlegen fest, und das Passwort ließ sich nur würfeln. Neue Hosts behalten dabei die bisherige Anmeldung; entfernte werden auf dem Node abgeräumt. Ein selbst gesetztes Passwort (mindestens 12 Zeichen) gilt für alle Hosts des Benutzers — gebraucht bei jeder Übernahme, bei der es schon in einer
wp-config.phpsteht. - Eine Datenbank lässt sich an den Container einer Domain hängen. Im Bereich Container steht dafür ein eigener Block: Datenbank wählen, Dienst aus der Compose-Datei, eine Vorlage für die Variablennamen (Standard, Redmine oder WordPress) und einen Präfix — die entstehenden Namen stehen live daneben. Kastra hängt den Unix-Socket von MariaDB ein und schreibt die Zugangsdaten als Umgebungsvariablen in eine zweite Datei neben deine Compose-Datei; die bleibt unverändert. Mehrere Datenbanken an einem Dienst brauchen trotzdem nur einen Volume-Eintrag: es ist derselbe Socket. Für den Container auf demselben Node ist das der einfachere Weg als der Zugriff über das Netz — kein offener Port, keine Firewallregel.
- Ein Statusblock sagt, warum der Container nicht an die Datenbank kommt. Er prüft den Socket, den Zugang des Systembenutzers dorthin, ob die Datei eingespielt ist und die Unit sie aufruft, ob der Datenbankbenutzer für
localhostgilt, und ob die Passwortvariable in der.envsteht. Nötig ist das, weil MariaDB bei einem Rechteproblem „Can't connect to local server through socket" meldet — das sieht nach einer abgestürzten Datenbank aus. - **Eine neue Seite Betrieb › Auslastung sagt, ob die Leistung noch reicht.** Sie zeigt, wie stark die Anlage in den letzten 7, 30 oder 90 Tagen beansprucht wurde — CPU, Last je Kern, Arbeitsspeicher, Swap, Wartezeit auf die Platte, vom Wirt entzogene Rechenzeit, Plattenplatz und Anfragen — und gibt dazu eine Einschätzung in ganzen Sätzen. Zu jeder Kennzahl über der Schwelle steht der Rat, der zu ihr gehört: hohe Wartezeit auf die Platte heißt schnellere Platte und nicht mehr Kerne, hohes steal heißt anderer Wirt und nicht größerer Node. Dazu Hochrechnungen, wann die Platte voll ist und wann die CPU-Spitze 80 % erreicht. Bisher war nur der aktuelle Wert zu sehen — und der sagt über einen Monat nichts.
- Bei mehreren Nodes rechnet die Auslastung den Verbund mit. Die Summe wird nach Kernzahl gewichtet und nicht als Mittel der Prozentzahlen; liegen mehr als 30 Punkte zwischen dem stärksten und dem schwächsten Node, sagt die Seite, dass zuerst zu verteilen und nicht zu kaufen ist. Und sie nennt die Ausfallreserve: was die übrigen Nodes tragen müssten, wenn der größte ausfällt. Über 100 % trägt der Verbund den Ausfall nicht — ein Grund für mehr Leistung, der mit der Auslastung im Alltag nichts zu tun hat.
- Die Übersicht zeigt die Auslastung in Kurzform. Einschätzung, Ausfallreserve und die drei knappsten Kennzahlen, mit einem Verweis auf die vollständige Auswertung. „Am knappsten" heißt: am nächsten an der eigenen Schwelle — 70 % Platte und 70 % CPU sind nicht gleich dringend.
- **Eine Domain hat jetzt einen Bereich Webserver. Dort stehen die Werte, an denen Anwendungen im Alltag hängenbleiben: Größe einer Anfrage (
client_max_body_size), Wartezeit auf die Anfrage und auf die Anwendung dahinter, wie lange eine Verbindung offen bleibt, gzip, die Sicherheits-Header, die Verzeichnisauflistung und ein Verfallsdatum für Bilder, CSS und Schriften. Ein Formular für beide** Dienste: steht Apache hinter nginx, setzt er dieselben Werte an seinen eigenen Direktiven um (LimitRequestBody,Timeout,ProxyTimeout,KeepAliveTimeout,Options Indexes) — welche das sind, steht unter jedem Feld. Bisher stand das alles fest im Agent, und wer etwas anderes brauchte, schrieb es in die Zusatzkonfiguration, wo eine falsche Zeile den Rollout des ganzen Nodes anhält. - Die Größe einer Anfrage bleibt automatisch, solange das Feld leer ist: dann folgt sie weiterhin der Uploadgröße aus dem Bereich PHP. Steht dort ein kleinerer Wert, sagt die Seite es — genau diese Kombination weist den Upload mit 413 ab, bevor PHP die Datei überhaupt sieht, und im Fehlerprotokoll der Anwendung steht dazu nichts.
- Die Wartezeit auf die Anwendung ist einstellbar. Sie stand fest auf 300 Sekunden; ein Import oder ein Rechenlauf, der länger braucht, endete mit 504, und von aussen liess sich daran nichts drehen. Zulässig sind 5 bis 3600 Sekunden. Bei einer Node.js-Domain galt sie bisher überhaupt nicht — dort stand keine Zeile, also die Vorgabe von nginx: sechzig Sekunden.
- **Der Abschnitt Zuletzt gesperrt sagt, warum eine Adresse gesperrt wurde.** Bisher zeigte die Seite Firewall allein die laufenden Sperren — wer nach einer Aussperrung nachsah, fand dort nichts mehr, weil die Sperre inzwischen abgelaufen war. Der neue Abschnitt zeigt auch die abgelaufenen, mit dem Szenario im Klartext, der Zahl der Ereignisse, der Dauer und dem Zeitpunkt, wahlweise über 24 Stunden, 7 oder 30 Tage.
- „Nie mehr sperren" an einem Eintrag erledigt beides auf einmal: die Adresse kommt auf die Whitelist, und eine noch laufende Sperre wird aufgehoben. Der Knopf steht an den laufenden Sperren wie im Verlauf. Bisher waren das zwei Schritte an zwei Stellen — und die Whitelist allein hob die bestehende Sperre nicht auf.
- Jede Sperre nennt die Domain, wegen der sie entstand — und was dort passiert ist. Neben dem Grund steht die betroffene Domain, anklickbar; ein Knopf Bericht klappt die Zeilen auf, die zum Alarm geführt haben: Zeitpunkt, Methode, Pfad, Statuscode, Programmkennung. Erst damit ist zu beurteilen, ob die Sperre richtig war — vierzig Aufrufe von
/v2/…blobs/uploads/sind eindocker push, vierzig Aufrufe von/wp-login.phpsind es nicht. Zugeordnet wird über die Protokolldatei; eine Sperre von Hand oder ein SSH-Szenario hat keine Domain, und dann bleibt die Stelle leer. - **Eine Domain hat einen Bereich Sperren.** Dieselben Einträge, eingegrenzt auf diese eine Domain, mit Zeitraum, Bericht und Entsperren — statt auf einer Node-Liste nach den Zeilen zu suchen, die einen angehen. Der Bereich steht nur Administratoren offen: eine Sperre gilt für den ganzen Node, und wer sie hier aufhebt, lässt die Adresse auf allen Domains wieder herein.
- Eine Domain lässt sich von den IP-Sperren ausnehmen. Der Schalter Keine IP-Sperren aus dieser Domain steht bei der Domain unter Allgemein. Ist er an, entsteht aus ihrem Zugriffsprotokoll keine Sperre mehr. Gedacht für Domains, deren normaler Verkehr wie ein Angriff aussieht: ein
docker pushauf eine eigene Registry etwa besteht aus vielen Aufrufen nicht-statischer Adressen und lief regelmässig in die Crawl-Erkennung — mitten im Hochladen, und die Sperre traf dann alle Ports des ganzen Nodes. Die Ausnahme gilt dem Protokoll dieser Domain, nicht der Adresse: fällt dieselbe Adresse an einer anderen Domain, an SSH oder am Mailserver auf, wird sie weiterhin gesperrt. - Der DNS-Befund erkennt, wenn zwei Zonen im Umlauf sind. Bisher verglich er nur die Nameserver-Namen: stehen beim Registrar dieselben wie bei Kastra, galt die Delegation als in Ordnung — auch dann, wenn diese Namen auf zwei verschiedene Maschinen zeigen und die eine noch die Zone des vorigen Anbieters ausliefert. Kastra fragt jetzt jeden autoritativen Server einzeln nach seiner Seriennummer, über IPv4 und IPv6. Weichen sie voneinander ab, steht in der Tafel zwei Zonen im Umlauf, dazu je Nameserver die Adresse und die Seriennummer, die er meldet — und der Befund verdrängt wie ein Delegationsfehler alle übrigen Zeilen. Das ist der Fall, in dem Jetzt prüfen bei jedem Klick ein anderes Ergebnis zeigte, ohne dass eine einzelne Zeile falsch gewesen wäre: welchen Wert eine Abfrage sieht, entschied sich daran, welchen Server der Resolver gerade erwischt hatte. Häufigste Ursache ist ein Nameserver-Name, der noch auf die Maschine des vorigen Anbieters auflöst — oft nur über IPv6, während IPv4 längst stimmt.
- Ein DNS-Node kann auf mehreren Adressen antworten. Unter Nodes → Node → Übersicht steht bei einem Node mit der Rolle
dnsjetzt Adressen des Nameservers: angehakt wird, worauf PowerDNS lauschen soll. Zur Wahl steht, was der Node gemeldet hat — eine Adresse, die auf keiner seiner Schnittstellen liegt, wird abgewiesen, denn belegen kann er sie nicht.127.0.0.1und::1kommen immer dazu. Keine ausgewählt heißt wie bisher: der Node nimmt die Adressen seiner Standardroute. Vorher ging genau das und sonst nichts — ein Node mit zwei IPv4 und zwei IPv6 beantwortete auf der Hälfte seiner Adressen keine Anfrage, ohne dass irgendwo eine Warnung stand. Wildcard-Zertifikate ohne den Schlüssel des ganzen Servers. Eine Domain hat einen neuen Bereich ACME-Delegation. Dort entsteht ein Zugang, der genau eines darf: einen einzigen TXT-Eintrag setzen — den, den Let's Encrypt für ein Wildcard-Zertifikat sehen will. Keine anderen Zonen, keine A-, MX- oder NS-Einträge, kein Auflisten. Bisher gab es dafür nur den API-Schlüssel von PowerDNS, und der gilt für den ganzen Server.
Wer sein Zertifikat selbst ausstellt — ein Router, eine Firewall, ein Mailserver im eigenen Haus —, trägt die Zugangsdaten in seinen ACME-Client ein und legt einmal einen CNAME an. Danach nie wieder: erneuert wird beliebig oft, ohne dass jemand etwas eintragen müsste.
Kastra spricht dafür das Protokoll von acme-dns. Das heißt: acme.sh (
dns_acmedns), lego, Traefik, Caddy und certbot können es ohne Zusatz. Das Panel legt die Zugangsdaten in genau der Form vor, die diese Programme als Datei erwarten, dazu je einen fertigen Ausschnitt für acme.sh und Caddy.Liegt die Zone der Domain in Kastra, ist es ein Klick: der CNAME wird auf Wunsch selbst eingetragen. Ein Knopf Prüfen löst ihn danach öffentlich auf und sagt, ob er steht.
Optional lässt sich der Zugang auf einzelne Adressen oder Netze beschränken — dazu rät das Panel auch, denn wer die Zugangsdaten hat, kann sich Zertifikate für diese Domain ausstellen lassen. Abschalten wirkt sofort, ohne dass der Kunde seinen CNAME anfassen muss.
Einzurichten ist das einmal vom Betreiber: eine Zone wählen (etwa
acme.example.net), sie beim Registrar auf die Nameserver dieser Installation delegieren und unterKASTRA_ACME_DNS_ZONEin/etc/kastra/control-plane.enveintragen. Angelegt wird sie danach von Kastra selbst. Ohne diesen Eintrag ändert sich nichts, und der Bereich sagt, was fehlt.Eine Domain lässt sich von Suchmaschinen fernhalten. Im Bereich Webserver stehen zwei neue Schalter: Nicht in den Index aufnehmen (noindex) und Verlinkten Seiten nicht folgen (nofollow). Der Webserver gibt daraus jeder Antwort dieser Domain die Kopfzeile
X-Robots-Tagmit — einer PDF-Datei und einem Bild genauso wie einer HTML-Seite, und auch einer Fehlerseite.Bisher ging das nur über die Anwendung selbst. Ein
<meta>im HTML tragen weder PDF noch Bild, und einerobots.txtverbietet nur das Abholen: eine Testdomain, die schon im Index steht, bleibt damit drin, weil die Suchmaschine nie erfährt, dass sie verschwinden soll.Beide Schalter sind ab Werk aus — jede bestehende Domain bleibt auffindbar wie bisher, und der Vhost ändert sich durch das Update nicht. Beide zusammen ergeben eine Kopfzeile mit beiden Werten, nicht zwei.
Ein zweiter Nameserver kann die Zonen jetzt abholen. Wer neben Kastra einen eigenen Secondary betreibt — das bestehende BIND, ein Anycast-Anbieter, der Nameserver eines Partners —, bekam die Zone höchstens einmal: PowerDNS war ohne Master-Unterstützung eingerichtet und hat deshalb nie ein NOTIFY gesendet, und ein Transfer von außen wurde abgewiesen.
pdnsutil show-zonezeigte dauerhaftLast SOA serial number we notified: 0. Ein Secondary, der die Zone einmal hatte, hielt damit bis zum Ablauf vonexpireeine veraltete Fassung — sieben Tage, in denen ein Teil der Welt die alten Einträge bekam.Unter
KASTRA_DNS_SECONDARIESin/etc/kastra/control-plane.envstehen jetzt die Adressen, durch Komma getrennt, IPv4 und IPv6 gemischt. Jede eigene Zone erlaubt diesen Adressen den Transfer und benachrichtigt sie bei jeder Änderung; beim Eintragen geht sofort ein NOTIFY hinaus, damit der neue Secondary nicht erst auf seinen Refresh warten muss. Die Liste gehört zuKASTRA_DNS_NAMESERVER: dort steht der Name des zweiten Nameservers, der als NS in jede Zone kommt, hier seine Adresse.Fremde Zonen auf demselben Node bleiben unberührt — Transfer und NOTIFY stehen je Zone und nicht serverweit. Wer die Liste wieder leert, entzieht die Erlaubnis auch wirklich.
Das Update startet PowerDNS auf jedem DNS-Node einmal neu, weil die beiden Schalter nur beim Start gelesen werden; für die Dauer des Starts beantwortet der Node keine Anfragen. Danach geschieht das nicht wieder: steht alles in der Konfiguration, wird sie nicht angefasst.
- Eine Zone, die Kastra selbst von einem fremden Master holen soll, kommt jetzt an. Eine Zone der Art Slave mit eingetragenen Mastern entstand in PowerDNS und blieb leer — ohne Slave-Unterstützung wurde sie nie übertragen, und weder im Panel noch im Protokoll stand etwas davon. Mit derselben Änderung holt der Node sie.
Geändert
- Meldungen, Aufgaben und Protokolle schreiben ä, ö, ü und ß. Fehlermeldungen und Hinweise vom Node, die Beschreibung einer Aufgabe („Cronjob geändert“), Audit-Einträge, die Einschätzung unter Auslastung, die Umzugsprüfung, das Protokoll einer Komponenteneinrichtung und die Spalte Quelle der Firewall („überall“) standen bisher als
ae,oe,ueundssim Panel. Einträge aus der Zeit vor dem Update bleiben, wie sie gespeichert wurden. Alarmmeldungen sagen, was los ist. Bisher trug eine Mail vor allem Kennungen: Art, Schlüssel, Dringlichkeit und einen UTC-Zeitstempel. Eine Entwarnung wie „Node X entspricht wieder dem Soll-Zustand“ verriet weder, was vorher nicht stimmte, noch wie lange.
Ein Alarm nennt jetzt die Art im Klartext, die Uhrzeit in der Zeitzone des Panel-Hosts, die Einzelheiten, was das bedeutet und was zu tun ist, dazu einen Link auf die passende Stelle im Panel. Eine Entwarnung nennt den ursprünglichen Alarm samt Einzelheiten, wann er kam und wie lange er bestand. Webhooks bekommen zusätzlich die Felder
title,url,sinceunddurationSeconds; die bisherigen Felder bleiben unverändert.- Fehlerseiten werden gesammelt und mit einem Klick ausgerollt. Bisher rollte jede Seite beim Speichern im Editor sofort aus, und man wartete je Statuscode auf einen eigenen Rollout. Jetzt heißt der Knopf im Editor Übernehmen: die Seite steht danach als ungespeichert in der Liste, ebenso ein vorgemerktes Entfernen. Speichern unter der Liste schreibt alles zusammen und stößt einen einzigen Rollout an; Verwerfen oder Zurücknehmen je Zeile nimmt Entwürfe zurück. Gilt an Subscription, Domain und Subdomain.
Das Menü zeigt nur noch, was ein Node auch bedient. Domains, Container, Datenbanken, Mail und DNS standen bisher immer in der Seitenleiste — auch in einer Installation ohne einen einzigen Node. Wer darauf klickte, landete auf einer leeren Liste, deren Knopf Anlegen mit einem Fehler endete.
Ein Punkt erscheint jetzt, sobald mindestens ein Node die passende Rolle trägt:
webfür Domains, Container und Laufzeiten,dbfür Datenbanken,mailfür Mail,dnsfür DNS. Auslastung verlangt einen Node überhaupt. Es zählt die vergebene Rolle, nicht die Verbindung — ein Node, dessen Agent gerade schweigt, bleibt der Node, der Mail macht. Wer unter Nodes eine Rolle vergibt, sieht den Punkt sofort, ohne die Seite neu zu laden.Dasselbe in der Bereichsleiste: ein Node ohne
mailhat keinen Bereich Mailserver, einer ohnebackupweder Sicherungsziel noch Sicherungsprotokoll; bei einer Domain entfallen DNS, ACME-Delegation, Mail und Datenbanken, wenn ihr Node das nicht bedient; bei einer Subscription entfällt Sicherung ohne Backup-Node und Virenscanner, solange er auf ihrem Node aus ist. Umzug erscheint erst ab dem zweiten Webnode.Nodes, Subscriptions, Status, Aufgaben und Einstellungen bleiben immer stehen, ebenso Firewall und Virenscanner, sobald ein Node da ist — sie sind der einzige Ort, an dem sich diese beiden Dienste einschalten lassen. Die Adressen selbst bleiben erreichbar: ein Lesezeichen auf einen ausgeblendeten Punkt führt weiter zu der Seite.
- Das Journal bekommt eine Zeitgrenze. Bisher galt nur die Größengrenze der Distribution: das Journal reichte mal 90 Tage zurück und mal drei, je nachdem, wie viel geschrieben wurde. Ab Werk sind es jetzt 30 Tage — genau die Spanne, die die SSH-Übersicht abfragt. Wer das nicht will, trägt im Bereich Protokolle des Nodes eine
0ein; dann bleibt die Einstellung des Betriebssystems unberührt. - Die SSH-Übersicht sagt jetzt, über welchen Zeitraum sie zählt. Sie fragte das Journal fest über 30 Tage ab und beschriftete ihre Spalte auch so. Wer die Journalfrist kürzer stellt, bekam damit ein Versprechen, das der Node nicht hält: ein Schlüssel, der vor drei Wochen benutzt wurde, stand bei einer Frist von einer Woche als nie verwendet da. Die Abfrage nimmt die Frist jetzt als Obergrenze, die Spalte heißt entsprechend 7 Tage statt 30 Tage, und darüber steht ein Satz, woran das liegt. Eine längere Journalfrist verlängert die Auskunft nicht — gefragt wird nie über 30 Tage hinaus.
- **Alte Läufe unter Aufgaben werden entfernt. Ihre vollständige Ausgabe stand bisher unbegrenzt in der Datenbank. Ab Werk sind es 90 Tage, und die Frist greift beim ersten Lauf rückwirkend**: wer heute ein Jahr an Läufen hat, hat sie in der Nacht nach dem Update nicht mehr. Die Frist steht im Bereich Protokolle des Nodes;
0bewahrt unbegrenzt auf. - **Der Bereich Protokolle einer Domain sagt, wie lange aufbewahrt wird.** Wer sucht und nichts findet, musste bisher raten, ob es die Zeile nie gab oder ob sie weg ist.
Dateien werden überall im selben Editor-Dialog bearbeitet. Bisher hing der Editor bei der
standalone.xml, dercomposer.json, der Compose-Datei und den Dockerfiles zwischen den Karten der Seite: er teilte sich die Höhe mit allem darüber, und bei derstandalone.xmlstanden unter ihm noch zwei Tabellen. Jetzt öffnet überall ein Bearbeiten-Knopf denselben Dialog, den der Dateimanager schon benutzt — mit Strg+S, der Marke ungesichert und einer Rückfrage, bevor ungespeicherte Änderungen verlorengehen.Für die Compose-Datei ist Prüfen mit in den Dialog gewandert; die Befunde stehen jetzt bei der Zeile, auf die sie sich beziehen, statt hinter dem Editor. Bei der
standalone.xmlersetzt eine Rückfrage das Kästchen fremde Änderung überschreiben: es lag hinter dem Dialog, und wer es ankreuzen wollte, hätte den Editor samt Änderung schließen müssen.Der Anmeldename eines FTP-Zugangs endet jetzt auf den Ort, an dem er hängt. Wer auf der Domain
shop.example.comden Namenwebeinträgt, meldet sich künftig alsweb@shop.example.coman; ein Zugang, der unter der Subscription angelegt wird, endet auf@sub-<Nummer>. Der Anhang steht hinter dem Eingabefeld und in der Liste. Grund ist der FTP-Server: er kennt einen Namensraum für den ganzen Node, und Namen wieweb,ftpoderbackupvergibt fast jeder. Bisher bekam der zweite, der einen davon nehmen wollte, eine Fehlermeldung über einen Zugang, der einem fremden Kunden gehört und in seinem Panel nirgends steht.Das gilt auch für die Zugänge, die es schon gibt — sie bekommen ihren Anhang beim Aktualisieren. Wer FTP benutzt, muss den Benutzernamen in seinem Programm danach einmal neu eintragen; Passwort, Wurzelverzeichnis und Dateien bleiben unverändert. Kündigen Sie das Ihren Kunden an, bevor Sie aktualisieren.
- **Die Tafel Kommt das draußen an? klappt sich zu, wenn alles stimmt.** Übrig bleibt die Kopfzeile mit alles kommt draußen an, dem Zeitpunkt der letzten Prüfung und Jetzt prüfen — die Tabelle darunter erklärte dann nur noch zeilenweise, dass nichts zu tun ist, und schob den Record-Editor aus dem Bild. Sobald ein Eintrag nicht ankommt, klappt die Tafel von selbst auf; ein Klick auf die Kopfzeile öffnet und schließt sie jederzeit von Hand. Gilt im Bereich DNS wie im Bereich Mail.
- Eine Domain zeigt nur noch auf eine Adresse je Familie (Plan 028). Bisher bekam jede Adresse, die ein Node gemeldet hatte, ihren eigenen
A-Eintrag — auch die aus einem internen Netz wie10.0.0.0/8, die von außen niemand erreicht. MehrereAunter einem Namen sind keine Aufzählung, sondern Lastverteilung: der Resolver nimmt einen davon, und traf er die interne Adresse, wartete der Browser erst den Fehlversuch ab. Die Domain wirkte dadurch langsam, nicht kaputt. Bestehende Zonen räumt die Control Plane beim nächsten Start selbst auf und rollt die betroffenen Zonen aus; von Hand angelegte und abgeschaltete Einträge bleiben unangetastet. Wer mehrere Adressen veröffentlichen will, legt die zusätzlichen Einträge im Record-Editor von Hand an. - Der Fortschritt einer laufenden Sicherung sagt, was er zählt. Statt einer Zahl ohne Bezug steht jetzt „12.400 von 40.000 Dateien · 2,1 GiB von 8,4 GiB durchgesehen — 26 %", darunter der Pfad relativ zum Heimatverzeichnis und der Satz, dass nur Geändertes geschrieben wird. Der Balken lief beim zweiten Lauf schnell hoch und blieb dann stehen; das sah nach einem Fehler aus und ist keiner — gezählt wird, was durchgesehen ist. Solange restic noch zählt, steht das auch so da.
- Der Rollout sagt, wie viel eine gelöschte Subscription noch belegt. Wird eine Subscription gelöscht, sperrt der Node ihren Benutzer und lässt sein Heimatverzeichnis liegen — damit sich eine versehentlich gelöschte Subscription zurückholen lässt. Nur endete dieses Aufheben nie, und niemand sagte es: auf der Testanlage lagen 1 264 solcher Verzeichnisse mit 53 GiB, und die erste Auskunft darüber war die Fehlermeldung eines Umzugs, der auf dem Ziel-Node keinen Platz mehr fand. Das Protokoll der Aufgabe nennt jetzt, wie viele es sind und wie viel unter
/var/wwwnoch frei ist. Weggeräumt wird weiterhin nichts — was von einem Kunden übrig ist, löscht kein Rollout von selbst. - Das Panel schreibt überall echte Umlaute. An rund vierhundert Stellen stand noch die Umschrift aus dem Quelltext: Uebersicht statt Übersicht, laeuft statt läuft, Gekuerzt statt Gekürzt, Fuss statt Fuß. Betroffen waren Beschriftungen, Hinweistexte und das Handbuch im Panel. Bezeichner bleiben unverändert — Routenpfade, Icon-Namen und Werte, die über die Schnittstelle gehen, sind weiterhin ASCII; keine Adresse im Browser ändert sich.
- Anlegen, Umbenennen und Rechte ändern fragen im Dialog. Bisher erschien dafür jeweils ein Feld als Karte unter der Liste — bei einer langen Liste ausserhalb des sichtbaren Ausschnitts, und der Fokus sprang nicht dorthin. Der Dialog nimmt den Fokus mit,
Eingabebestätigt,Escbricht ab. Beim Umbenennen ist nur der Teil vor der Endung ausgewählt; ein Name mit Schrägstrich und eine Rechteangabe, die keine Oktalzahl ist, werden gleich abgewiesen statt erst vom Node. - Das Zertifikat der Control Plane kann auf weitere Adressen lauten. Ein Node prüft den Namen, unter dem er die Control Plane erreicht; von Haus aus lautet ihr Zertifikat auf den Panel-Hostnamen und die Loopback-Adressen. Wer Nodes über eine andere Adresse anmeldet, trägt sie in
KASTRA_CERT_NAMES(/etc/kastra/control-plane.env) ein — die Control Plane stellt das Serverblatt beim nächsten Start neu aus. Die CA bleibt dabei stehen, angemeldete Nodes behalten ihre Zertifikate. Ohne den Eintrag endete der Handshake mit „certificate is valid for 127.0.0.1, ::1". - Neu starten baut ein selbst gebautes Image mit — und ein gescheiterter Bau fällt auf. Die Unit baut in einem eigenen Schritt vor dem Start. Eine geänderte
Dockerfilewirkt damit ab dem nächsten Start; vorher konnte ein vorhandenes Image unbesehen weiterlaufen. Scheitert der Bau, gilt die Domain als gestört, und der Bereich Protokolle zeigt unter Container-Dienst die Ausgabe des Baus. Bisher lief der Start trotzdem weiter, die Domain stand als „läuft" da und lieferte nichts aus. Ein Bau darf dabei bis zu einer Stunde dauern. Domains ohnebuild:bekommen keinen Bauschritt; unveränderte Schichten kommen aus dem Cache. - Ein
build:-Kontext außerhalb des Verzeichnisses der Subscription wird abgewiesen — beim Prüfen wie beim Speichern, mit Zeilennummer. Der Kontext ist das Verzeichnis, aus dem das Image gebaut wird; alles darin kann hineinwandern, und damit gilt für ihn dieselbe Grenze wie für einen Mount. Ein Kontext, der auf ein Repository zeigt (https://…), fällt nicht darunter. - Tabellen sind lesbar geworden. Die Spalten hatten kein Polster und die Kopfzeile stand zentriert über linksbündigen Werten — im Bereich Container einer Domain sass die Überschrift Port neben ihrem eigenen Wert statt darüber. Jede Tabelle des Panels hat jetzt Abstand zwischen den Spalten, eine linksbündige Kopfzeile und eine Linie zwischen den Zeilen.
- Karten und Knopfzeilen stehen nicht mehr aneinander. In siebzehn Bereichen berührten sich zwei Karten ohne jeden Abstand, unter anderem bei Datenbanken, WAF und Alarmierung; in acht Karten klebte die Knopfzeile an der Tabelle darüber und am Editor darunter. Dasselbe galt für die Knopfzeile auf der Seite Firewall, für die Kopfzeile der DNS-Befundtafel und für die Beschriftungen Letzte Läufe und Funde über den Tabellen des Virenscanners.
- Ein Eingabefeld und der Knopf daneben sitzen auf einer Höhe. Steht unter dem Feld ein Hinweis, war es zwanzig Pixel höher als eines ohne — der sichtbare Kasten sass dadurch zehn Pixel über dem Knopf. Sichtbar war das im Audit-Log, auf der Seite Firewall, in der Node-Übersicht und unter Konto.
- MariaDB prüft die Adresse des Clients, nicht den aufgelösten Namen. Sobald eine Datenbank des Nodes über das Netz erreichbar ist, setzt Kastra
skip-name-resolve. Ohne das prüfte MariaDB den Namen, den ein Reverse-Lookup zur Client-Adresse liefert — auf einem Hoster-Server der generische Servername —, und ein Zugang für eine Adresse oder ein Netz traf nie zu. Umgeschaltet wird nur, wenn kein Benutzer des Nodes auf einem Hostnamen steht; sonst bleibt es beim Bisherigen, und der Rollout nennt die betroffenen Zugänge. Der Wert wirkt wie der Bind-Wert erst nach einem Neustart von MariaDB: beim ersten Öffnen und beim letzten Schließen bricht jede offene Verbindung auf diesem Node einmal ab. - Port 3306 bleibt beim Container-Zugriff auf das Container-Netz beschränkt. MariaDB kann nur auf einer Adresse lauschen, und die Bridge gibt es beim Booten noch nicht — der Listener steht deshalb offen. Die Firewall-Regel entsteht aus derselben Angabe wie der Zugang und lässt nur die Container-Netze und die eingetragenen Adressen durch.
- **Der Bereich Datenbanken nennt den Socket-Weg beim Namen.** Der Schalter Container dieser Site bleibt, ist aber ab jetzt die Ausnahme: er öffnet den Listener von MariaDB und braucht eine Firewallregel. Wer einen Container auf demselben Node betreibt, nimmt den Socket.
Behoben
- Die Beschriftung eines Eingabefeldes in einem Dialog ist wieder ganz zu sehen. Stand ein Feld zuoberst in einem Dialog — etwa Name der Datei unter Neue Textdatei, Subscription unter Domain anlegen —, fehlte der Beschriftung die obere Hälfte, sobald man hineinschrieb.
- Ausgabe und Fehler einer Node.js-Anwendung tragen Datum und Uhrzeit. Unter Ausgabe (Node.js) und Fehler (Node.js) stand bisher nur, was die Anwendung schrieb — ohne Zeitpunkt. Ein Fehler ließ sich so keiner Anfrage und keinem Deploy zuordnen. Jetzt beginnt jede Zeile mit Datum, Uhrzeit und Zeitzone, etwa
2026-09-13 10:15:02.123 +0200. Das gilt ab dem nächsten Neustart oder Deploy der Anwendung; ältere Zeilen bleiben, wie sie sind. - Ein Datenbankbenutzer mit
localhostkommt auch über127.0.0.1herein. Für MariaDB heißtlocalhostnur „über den Socket“. Eine Anwendung mitDB_HOST=127.0.0.1verbindet sich per TCP — und wurde abgewiesen, sobald auf dem Node eine Datenbank für Container oder von außen geöffnet war, weil MariaDB dann Adressen statt Namen vergleicht. Bisher musste127.0.0.1deshalb bei jedem Benutzer von Hand unter Hosts ergänzt werden. Jetzt legt Kastra den Eintrag nebenlocalhostselbst an. Bestehende Benutzer bekommen ihn, sobald ihre Hosts oder ihr Passwort das nächste Mal gespeichert werden. - Ein Node.js-Deploy im Mischbetrieb sagt, dass die Route fehlt. Zeigte noch kein Pfad auf die Node.js-Anwendung, liefen Installation und Bau trotzdem durch, und der Deploy endete mit
INTERNAL_ERRORund „Unit … not found“. Deploy und Neu starten weisen jetzt vorher mitNODE_UNIT_MISSINGab und nennen den Grund: fehlende Route, abgeschaltete Domain oder gesperrte Subscription. Eine Domain, die den Healthcheck nicht besteht, reißt keinen fremden Rollout mehr mit. Nach dem Rollout ruft der Node die Domains ab, die der Durchlauf verändert hat — so stand es im Handbuch. Umgesetzt war es anders: gezählt wurde jede geschriebene Datei, und geschrieben wird bei jedem Rollout die ganze Konfiguration, auch die unveränderte. Damit galt bei jeder Änderung jede Domain des Servers als betroffen.
Die Folge sah aus wie ein Rätsel: „Der Healthcheck für fremde-domain.de ist fehlgeschlagen" nach einer Änderung, die mit dieser Domain nichts zu tun hatte. Eine einzige Domain, die nicht binnen zehn Sekunden antwortet — eine langsame Anwendung, ein ausgelasteter Server —, ließ von da an jeden Rollout scheitern.
Geprüft wird jetzt, was sich wirklich geändert hat: der Vhost einer Domain, ihre Zusatzkonfiguration oder ihr PHP-Pool. Wer davon unberührt bleibt, wird nicht mehr abgerufen.
Der Wartungsmodus überlebt den Rollout, der ihn einschaltet. Eine Domain in Wartung antwortet mit 503, und dafür gab es eine Ausnahme im Healthcheck. Sie trug nur, solange die Domain auch antwortete: lief der Abruf in die Zeitüberschreitung — auf einem langsamen Server der Normalfall —, griff die Ausnahme nicht, und der Rollout nahm genau die Wartung wieder zurück, die er gerade ausgerollt hatte. Die Domain lieferte weiter aus, während im Panel die Wartung als aktiv stand.
Eine Domain in Wartung wird jetzt gar nicht mehr abgerufen. Sie liefert absichtlich nicht aus; es gibt nichts zu prüfen und erst recht nichts zurückzunehmen.
Ein gescheiterter Healthcheck meldet nicht mehr den ganzen Server als abgewichen. Die Drift-Erkennung vergleicht die Dateien auf dem Server mit dem Stand, den der letzte Rollout geschrieben hat. Endete ein Rollout mit einem Healthcheck-Fehler, merkte sich der Node diesen Stand gar nicht — er verglich weiter gegen den Stand davor und meldete jede Datei des Rollouts als Abweichung. Eine einzige Domain löste so einen Drift-Alarm über den ganzen Server aus.
Gemerkt wird jetzt auch nach einem Fehlschlag. Als abgewichen steht dann genau die Domain da, die zurückgenommen wurde — und das ist die Meldung, die dazu gehört.
Nach dem Ausstellen steht die Laufzeit des Zertifikats sofort da. Der Bereich Zertifikat einer Domain zeigte gleich nach der Ausstellung „Gültig bis: unbekannt" und füllte sich erst irgendwann von selbst. Der Node nennt das Ablaufdatum in seiner Antwort — die Control Plane las es nur nicht. Eingetragen wurde es allein von einem stündlichen Abgleich, der bei jedem Node nachfragt; bis zur nächsten vollen Stunde stand die Zeile ohne Datum.
Schwerer als die Anzeige wog, was daran hängt: die Ablaufübersicht und der nächtliche Erneuerungslauf suchen über das Ablaufdatum. Eine Zeile ohne Datum kam in beiden nicht vor. Blieb der Node zur vollen Stunde stumm, blieb sie leer — und das Zertifikat wäre abgelaufen, ohne dass es jemand vorher angesehen hätte.
Ausstellung und Erneuerung übernehmen die Laufzeit jetzt aus der Antwort des Nodes, so wie Mail-, FTP- und Panel-Zertifikat es schon taten. Der stündliche Abgleich bleibt als zweites Netz.
Ein Nameserver, der die Zone gar nicht hat, wird als solcher erkannt. Antwortet er mit
REFUSED— „dafür bin ich nicht zuständig", die übliche Antwort, wenn eine Zone fehlt oder auf dem falschen Server liegt —, dann meldete die Prüfung unter ACME-Delegation und im DNS-Befund „Der Prüf-Resolver hat nicht geantwortet". Ein Satz, der auf nichts zeigt, während der Nameserver gerade sehr deutlich geantwortet hatte. Die Ursache war eine Zeile zu weit unten in der Zuordnung: fürREFUSEDwurde eine Ausnahme erwartet, die Java in diesem Fall nie wirft.Der Befund sagt jetzt gestört und nennt die eigene Anlage als Ort, an dem nachzusehen ist — so wie er es bei
SERVFAILschon tat.Die Seriennummer einer DNS-Zone steigt wieder, wenn sich etwas ändert. Jede von Kastra angelegte Zone trug
soa_edit_api = INCEPTION-INCREMENT. Das ist ein gültiger Wert fürSOA-EDIT, aber keiner fürSOA-EDIT-API— PowerDNS lässt die Seriennummer dann unverändert, ohne Fehler und ohne Meldung. Die Zonen standen deshalb für immer auf der Nummer, die sie beim Anlegen bekommen hatten, egal wie oft ein Eintrag geändert wurde.Für einen Secondary heißt eine stehende Seriennummer: es gibt nichts Neues. Er hat die Zone nach dem ersten Transfer nie wieder abgeholt und beantwortete Anfragen dauerhaft aus dem alten Stand — auch die nach einem ACME-Nachweis, den Let's Encrypt bei irgendeinem der autoritativen Server abfragt. Wer einen zweiten Nameserver betreibt, sollte nach dem Update einmal nachsehen, ob dessen Stände zur eigenen Zone passen.
Der Wert steht jetzt auf
DEFAULT(JJJJMMTTnn). Bestehende Zonen stellt der nächste Rollout um; im Protokoll steht dann eine Zeile je Zone.Nach einem Neustart der Control Plane ist der Node gleich wieder da. Reißt die Verbindung ab, wählt der Agent mit wachsendem Abstand neu an — das soll er auch, damit eine ausgefallene Control Plane nicht im Sekundentakt angeklopft bekommt. Zurückgesetzt wurde dieser Abstand aber nie: er wuchs über die Laufzeit des Dienstes hinweg auf eine Minute und blieb dort. Wer die Control Plane zweimal hintereinander neu startete — nach einer geänderten Einstellung etwa —, sah den Node danach bis zu eine Minute lang als nicht verbunden, und jeder Rollout, den er in dieser Zeit anstieß, lief ins Leere, ohne das zu melden.
Der Abstand fängt jetzt wieder bei einer Sekunde an, sobald eine Verbindung eine Minute lang gestanden hat.
Ein verlorener Sicherungsspeicher kommt von selbst zurück. Startet der Server hinter dem Sicherungsziel neu, wechselt am anderen Ende die Adresse oder stirbt die SMB-Sitzung, dann stand
/backupdanach als toter Einhängepunkt da: jeder Zugriff meldete „no such device", und jede Sicherung scheiterte — bis jemand von Hand eingriff. Von selbst kam das nie zurück; eine Einbindung versucht es nach einem Fehler nicht erneut, und ein WireGuard-Tunnel sucht die Gegenstelle nur beim Aufbauen.Der Node sieht jetzt alle drei Minuten nach, ob der Speicher benutzbar ist, und setzt sonst in Stand: Tunnel neu aufbauen, wenn von dort nichts mehr kommt, die tote Einbindung lösen, neu einhängen, nachsehen. Bleibt der Speicher aus, versucht er es in größer werdenden Abständen weiter (bis zu einer halben Stunde) statt im Minutentakt. Was er getan hat, steht im Protokoll des Agents auf dem Node.
Mitgeprüft wird dabei etwas, das vorher niemand bemerkt hätte: dass unter
/backupwirklich das Sicherungsziel liegt und nicht das leere Verzeichnis des Nodes. Fehlte die Einbindung ganz, lief die Sicherung nämlich durch — auf die Systemplatte des Nodes.Die Aufbewahrung scheitert nicht mehr an einer alten Sperre. Auf jeder Subscription meldete die Sicherung „Die Sicherung liegt vor, die Aufbewahrung konnte aber nicht angewendet werden“ — Tag für Tag, mit einer Sperre, die Tage zurücklag. Gesichert wurde weiter, weggeräumt nichts mehr: die Snapshots wuchsen über jede eingestellte Aufbewahrung hinaus.
Die Sperre stammte von einem Lauf, der abgebrochen wurde, bevor er sie entfernen konnte — ein Zeitlimit oder ein Neustart des Agents mitten im Lauf genügt. restic räumt eine solche Sperre nur weg, wenn der Prozess dahinter nicht mehr existiert; nach Stunden ist die Prozessnummer aber neu vergeben, und dann sieht restic dort einen lebenden Besitzer, wo keiner ist. Auch
restic unlockhalf deshalb nicht.Der Node sieht jetzt selbst nach, wer die Sperre hält: läuft unter der Nummer kein restic mehr, entfernt er sie und wiederholt den Schritt. Im Protokoll des Laufs steht unter Aufbewahrung, welche Sperre weggeräumt wurde. Arbeitet dagegen wirklich noch ein Lauf am Repository, bleibt die Sperre stehen und die Meldung nennt Prozessnummer und Zeitpunkt — Warten ist dann richtig. Der nächste Lauf räumt von selbst auf, ein Eingriff am Node ist nicht nötig.
Eine ausgenommene Domain wurde trotzdem gesperrt. Steht bei einer Domain der Schalter Aus dem Zugriffsprotokoll dieser Domain entsteht keine Sperre, soll ihr Verkehr keine IP-Sperre mehr auslösen. Der Node sperrte weiter, und im Panel war der Grund nicht zu sehen: die Ausnahme stand da, der Bouncer sperrte trotzdem.
Die Ausnahme hängt am Pfad der Protokollzeile. Seit dem Umzug der Protokolle nach
/var/log/kastra/subscriptionsnannte sie diesen Ort — eingelesen wurden die Protokolle aber noch über den Verweislogsim Heimatverzeichnis, also unter dem alten Pfad. Für CrowdSec waren das zwei verschiedene Dateien, und die Ausnahme traf auf keine einzige Zeile zu.Am selben Pfad hängt die Zuordnung einer Sperre zu ihrer Domain: der Bereich Sperren einer Domain blieb deshalb leer, obwohl der Node wegen dieser Domain gesperrt hatte.
Der Node liest die Protokolle jetzt unter ihrem echten Pfad ein, und die Quellenliste wird bei jedem Rollout nachgezogen: CrowdSec muss dafür nicht neu eingerichtet werden. Eine Sperre, die vorher entstanden ist, bleibt bis zu ihrem Ablauf stehen und lässt sich im Bereich Sperren aufheben.
- Der Probelauf der Wiederherstellung schlägt nicht mehr grundlos fehl. Seit die Protokolle aus dem Heimatverzeichnis heraus umgezogen sind, steht dort ein Verweis
logsauf ihren neuen Ort. Er wird mitgesichert und mitzurückgeholt — beim Nachzählen des Probelaufs fiel er aber unter den Tisch, weil nur Dateien und Verzeichnisse gezählt wurden. Der Probelauf kam so genau einen Eintrag zu kurz, meldete „unvollständig" und färbte die Sicherung rot, obwohl restic alles zurückgeholt hatte. Gezählt wird jetzt jeder Eintrag. Der Wartungsmodus schaltet sich jetzt wirklich ein. Wer die Wartung an einer Domain oder einer Subscription einschaltete, sah sie im Panel als aktiv — die Domain lieferte aber unverändert weiter aus. Schuld war der Gesundheitscheck am Ende jedes Rollouts: er ruft jede geänderte Domain auf und wertet eine 503 als kaputte Konfiguration, die er zurücknimmt. Genau diese 503 ist im Wartungsmodus aber das Gewollte, und so nahm derselbe Rollout die Wartung wieder zurück, der sie gerade ausgerollt hatte.
Unbemerkt blieb das, weil eine Ausnahme für die eigene Adresse des Nodes den Check durchlässt: wer eine solche Ausnahme eingetragen hatte, bei dem funktionierte die Wartung. Der Check kennt den Wartungsmodus jetzt und lässt eine 503 von einer Domain in Wartung stehen.
Protokolle aus dem Journal reichen wieder weit genug zurück. Auf einem Node mit vielen Subscriptions war das Mailprotokoll einer Domain oft leer, obwohl eben noch zugestellt worden war; dasselbe traf jede andere Auskunft aus dem Journal.
systemd legt für jeden Unix-Benutzer ein eigenes Journal an, und eine gekündigte Subscription behält ihren — gesperrten — Benutzer. Ab hundert Journaldateien insgesamt räumt systemd bei jeder Drehung sofort das gerade abgelegte System-Journal wieder weg, und übrig bleibt allein die laufende Datei; auf einer belebten Maschine sind das Minuten. Die eingestellte Frist im Bereich Protokolle lief damit ins Leere. Kastra hebt die Grenze jetzt auf tausend Dateien an. Wie viel Platz das Journal belegen darf, bleibt unverändert die Einstellung des Betriebssystems.
Ein Kunde konnte über sein Protokollverzeichnis auf dem Node zu root-Rechten kommen. Das Verzeichnis
logs/<domain>im Heimatverzeichnis gehörte ihm; er konnte darinaccess.loglöschen und an dieselbe Stelle einen Verweis auf eine beliebige Datei des Nodes legen. nginx, Apache und systemd öffnen die Protokolle als root und folgten dem Verweis — die angefragte Adresse landete damit unverändert in einer fremden Datei, etwa in/etc/cron.d/. Über denselben Weg gab der Bereich Protokolle jede Datei des Nodes aus.Die Protokolle liegen jetzt unter
/var/log/kastra/subscriptions/und damit ausserhalb der Reichweite des Kunden: das Verzeichnis gehört root, der Kunde ist Gruppe und darf lesen, aber nichts anlegen oder löschen. Im Dateimanager findet er sie weiter unterlogs, und der Bereich Protokolle zeigt unverändert dasselbe. Bestehende Protokolle zieht der erste Rollout nach dem Update um; ein schon abgelegter Verweis wird dabei entfernt und nicht mitgenommen.Automatische Sicherungen laufen wieder. Seit Fassung 26.09.02.20 wurde der Zeitplan nicht mehr ausgeführt: eingetragen war er, angezeigt wurde er auch, aber nachts geschah nichts. Die minütliche Prüfung brach mit einem internen Fehler ab, noch bevor sie den Crontab-Ausdruck überhaupt ansah — und weil das vor der Fehlerbehandlung geschah, gab es weder einen fehlgeschlagenen Lauf im Verlauf noch eine Meldung. Es sah aus, als sei nie etwas fällig gewesen.
Betroffen war jeder Lauf über den Zeitplan: Sicherungen, die zeitgesteuerten Suchläufe nach Schadsoftware und der monatliche Probelauf der Wiederherstellung. Von Hand angestoßene Läufe gingen die ganze Zeit durch.
Nach dem Update prüfen, ob unter Sicherung › Verlauf je Subscription wieder ein Lauf der letzten Nacht steht. Die bereits vorhandenen Snapshots sind unberührt — es kam in dieser Woche nur keiner dazu, und weggeräumt hat die Aufbewahrung in derselben Zeit auch nichts. Wer die Lücke nicht abwarten will, stößt einen Lauf von Hand an.
- Eine fehlende PHP-Datei zeigt die eigene Fehlerseite statt „File not found." Im Modus nginx + Apache reichte Apache jeden Pfad, der auf
.phpendet, an PHP-FPM weiter — auch einen, den es gar nicht gibt. PHP-FPM beantwortete ihn dann selbst mit diesen zwei Wörtern, und weil Apache den 404 nie zu sehen bekam, blieb seinErrorDocumentwirkungslos: der Aufruf einer nicht vorhandenen.php-Adresse zeigte die nackte Meldung, während dieselbe Adresse ohne.phpdie hinterlegte Seite brachte. Apache prüft jetzt vorher, ob die Datei existiert. Anwendungen, die ihre 404 selbst beantworten, behalten ihre Seite unverändert — daran ändert sich nichts. - Der Wartungsmodus zeigt die hinterlegte 503-Seite. Wer eine eigene Fehlerseite für 503 hinterlegt hatte, bekam im Wartungsmodus trotzdem die eingebaute Seite von nginx: der Statuscode stimmte, der Inhalt kam nie an. Grund war die interne Weiterleitung auf die Seite — sie lief ein zweites Mal in die Wartungsprüfung, wurde wieder mit 503 beantwortet, und nginx bricht in diesem Fall ab und antwortet selbst. Die Weiterleitung ist jetzt von der Prüfung ausgenommen. Wer keine 503-Seite hinterlegt hat, sieht wie bisher die Seite von nginx.
Ein GitHub-Zugang bleibt jetzt verbunden, statt nach ein paar Stunden zu verfallen. Wer unter Einstellungen › GitHub ein Konto verbunden hatte, fand es je nach Einrichtung schon am nächsten Tag mit „GitHub hat den Zugang abgelehnt (HTTP 401)" vor — jedes Suchen und jedes Holen eines Repositories scheiterte, und es half nur, das Konto von Hand neu zu verbinden.
Der Grund lag daran, welche Anwendung bei GitHub registriert ist: eine GitHub App vergibt Zugriffstoken mit acht Stunden Gültigkeit und schickt ein Erneuerungstoken mit. Kastra hat dieses Erneuerungstoken bisher weggeworfen. Es wird jetzt verschlüsselt aufbewahrt, und das Zugriffstoken wird selbsttätig ausgetauscht, kurz bevor es abläuft. Wer eine OAuth App registriert hat, merkt von der Änderung nichts — deren Token laufen nicht ab.
Lässt sich ein Zugang wirklich nicht mehr erneuern, steht das jetzt am Konto und sagt, dass es neu zu verbinden ist, statt beim nächsten Holen als Fehler am Repository zu erscheinen.
- **Ein Wurzelverzeichnis, das im Bereich FTP einer Domain eingetragen wird, gilt jetzt ab dem Verzeichnis dieser Domain.** Wer auf einer Subdomain
httpdocs/downloadseintrug, landete bisher neben der Hauptdomain statt in der Subdomain — der Pfad wurde vom Verzeichnis der Subscription aus gezählt, und der Ordner am falschen Ort wurde dabei stillschweigend angelegt. Unter dem Feld steht ab sofort, worauf sich der Pfad bezieht, und die Liste zeigt den Ort in derselben Form. Auf der Subscription bleibt es beim ganzen Weg (example.com/httpdocs). Bestehende Zugänge behalten ihr Verzeichnis; wer einen falsch abgelegten hat, trägt den Pfad einmal neu ein. - **Eine Maildomain im Modus nur Versand lässt die Empfangs-Einträge der Zone in Ruhe.** Wurde eine Maildomain gleich in diesem Modus angelegt, blieben MX, Autodiscover und Autoconfig aus der Zonenvorlage in der Zone stehen — und die DNS-Prüfung bemängelte einen Empfang, der nie zu Kastra wechseln sollte. Beides ist behoben: das Anlegen räumt die drei Einträge jetzt genauso auf wie ein Moduswechsel, und Kastra pflegen lassen schlägt sie für eine solche Domain nicht mehr vor. SPF, DKIM und DMARC bleiben stehen — sie schützen den Versand, und der läuft weiter über Kastra. Bei einer schon betroffenen Domain genügt es, den Modus einmal neu zu speichern; danach verschwinden die drei Einträge aus der Zone.
- Der Record-Editor übernimmt getippte Änderungen wieder in seinen Entwurf. Die Zellen schrieben ihren Wert unmittelbar in das Objekt der Zeile, ohne den Entwurf selbst anzufassen. Sichtbar wurde das erst mit der neuen Befundkarte, die genau daran hängt — sie wäre erst beim Hinzufügen einer Zeile erschienen, nicht beim Ändern eines Werts. Gespeichert wurde immer richtig; betroffen war nur, was auf den Entwurf hört.
- Nach einem Update lädt die Oberfläche von selbst neu. Bisher lief die offene Seite mit dem alten Stand weiter, und der erste Klick auf einen Bereich, der noch nachgeladen werden musste, tat schlicht nichts — das sah aus, als seien die Schaltflächen kaputt, und ging erst nach einem F5 von Hand wieder. Der Grund: jede Datei des Bauwerks trägt einen Inhaltshash im Namen, nach dem Update heißen sie anders, und die offene Seite kennt noch die alten Namen. Jetzt lädt die Seite in diesem Fall selbst neu — nach dem eigenen Update mit einem Hinweis, und ebenso, wenn das Update von woanders kam. Fehlt eine Datei dauerhaft, wird höchstens einmal neu geladen; danach steht die Fehlermeldung, statt dass die Seite sich im Kreis dreht.
- Ohne angegebene E-Mail-Adresse wird bei Let's Encrypt kein erfundener Kontakt mehr hinterlegt. Bisher trug Kastra
acme@<hostname>ein — eine Adresse, die es in aller Regel nicht gibt, sodass Hinweise der CA vor dem Ablauf ins Leere gingen. Bei einem Namen unter einer reservierten Endung (.example,.test,.invalid) wies die CA sogar die Registrierung ab, mit einer Meldung über die Kontaktadresse statt über den Namen. Das Konto wird jetzt ohne Kontakt registriert; wer Hinweise möchte, trägt eine Adresse ein. - **Der Bereich FTP einer Subscription zeigt seine Zugänge wieder.** Statt der Liste stand dort eine Fehlerkarte mit NG0950: die Tafel holte die Zugänge, bevor sie wusste, welche Subscription gemeint ist. Auf einer Domain trat der Fehler nicht auf — dieselbe Tafel entsteht dort erst, wenn die Domain geladen ist. Nebenbei behoben: wechselt man von einer Domain zur nächsten, ohne die Seite zu verlassen, zeigte die Tafel weiter die Zugänge der vorigen Domain.
- Die Verwaltungskonsole von WildFly spielt Anwendungen wieder ein — und ist über den Namen des Panels überhaupt erreichbar. Ein Upload endete mit Unexpected status code: die Konsole schickt die Datei nach
/management-upload, und dieser Pfad fehlte im Durchreicher, in der Rechteliste, in der Sicherheitsregel der Konsole und im Vhost des Panels; außerdem nahm die Control Plane dem Formular den Inhalt ab, bevor er den Node erreichte. Beim Nachsehen fiel auf, dass der Vhost die Konsole gar nicht kannte:/console/index.htmllieferte die Panel-Oberfläche statt der Konsole. Beides ist behoben; die Regel im Vhost trägt das Update an einer bestehenden Anlage nach, legt vorher eine Sicherung daneben und nimmt sie zurück, wennnginx -tdie Fassung ablehnt. Dateien über 40 MiB gehen nicht durch die Konsole — sie liegen sonst vollständig im Speicher der Control Plane; für größere Anwendungen ist der Weg über SFTP oder den Dateimanager nachstandalone/deploymentsgedacht. - Auf einem schmalen Fenster rollt nichts mehr waagerecht. Auf einem gefalteten Telefon (280 px) schoben zwei Kopfzeilen die Seite seitlich auf: unter Laufzeiten die Zeile einer PHP-Fassung mit ihren Marken (Standard, FPM active, 3 Domain(s)), der Hinweis mit dem Knopf Paketquelle einrichten daneben, und unter Firewall die Zeile mit Rechnername, Rollen und dem Schalter Firewall aktiv. Alle drei brechen jetzt um, statt nebeneinander stehen zu bleiben.
- Der Composer-Editor meldet keinen Fehler mehr in der Browser-Konsole. Monaco fragte für JSON einen Arbeitsprozess, der die Sprache nicht kennt, und bekam Missing requestHandler or method: doValidation. Die Prüfung der
composer.jsonim Editor blieb damit aus. - Ein verwaister Benutzer hält keine Prozesse mehr. Wird eine Subscription gelöscht, bleibt ihr Unix-Benutzer gesperrt stehen — seine Daten sollen für ein Wiederherstellen erhalten bleiben. Seine Prozesse blieben bisher ebenfalls stehen: rootlose Container überleben das Löschen ihrer Domain, und das eingeschaltete Lingering hielt ihre Sitzung offen. Auf einem Node sammelten sich so über Wochen Container von Subscriptions, die es nicht mehr gibt. Der Rollout beendet die Sitzung eines verwaisten Benutzers jetzt über sein systemd-Slice und schaltet das Lingering ab; im Protokoll des Rollouts steht, wessen Sitzung beendet wurde.
- Eine gelöschte Container-Domain nimmt ihre Container mit. Bisher blieben sie stehen:
systemctl disable --nowbeendet podman-compose, die Container selbst hängen aber an conmon, und lief der Aufräumschritt der Unit nicht durch — weil der Startversuch abgebrochen wurde oder das Verzeichnis der Domain schon weg war —, liefen sie weiter. Sie belegten Speicher und, was schlimmer ist, ihren Port: die Control Plane vergibt ihn nach dem Löschen neu, und die nächste Domain auf demselben Port bekam ihren Container nicht mehr hoch. Weil auf dem Port trotzdem jemand antwortete — der alte Container —, sah sie im Panel gesund aus. Beim Entfernen einer Unit werden die Container ihres Compose-Projekts jetzt mit entfernt; andere Domains derselben Subscription bleiben unberührt. - Ein Container, der nicht hochkommt, hält den Rollout nicht mehr auf. Startet ein Container nicht — ein Image, das es nicht gibt, ein Netz, das sich nicht einrichten lässt —, versucht systemd es alle paar Minuten erneut und wartet dabei jedes Mal fünf Minuten auf den ersten laufenden Container. Kastra stellte sich hinter genau diesen Startauftrag: jeder Rollout des Nodes kostete dadurch zwei Minuten zusätzlich, auch einer, der mit dieser Domain nichts zu tun hatte. Auf einem Node mit einer solchen Domain wurde damit alles zäh — eine Domain anlegen, ein Zertifikat erneuern, eine Einstellung ändern. Ein laufender Startversuch wird jetzt nicht mehr abgewartet; das Protokoll des Rollouts sagt, welche Unit gerade startet und dass er nicht darauf wartet. Am Ergebnis für den Container ändert sich nichts: systemd versucht es weiter, und was dabei herauskommt, steht wie bisher im Bereich Container.
- Die Verwaltungskonsole von WildFly lädt. Sie blieb mit Access Provider Error, Status 403 - Forbidden stehen und riet dazu, den Benutzer einer RBAC-Rolle zuzuordnen — obwohl der im Panel angelegte Verwaltungsbenutzer stimmte und es an den Rollen gar nicht lag. WildFly vergleicht bei jedem Aufruf von
/managementdie Herkunft, die der Browser mitschickt, mit seiner eigenen Adresse; die Konsole läuft aber unter der Adresse des Panels, weil sie von dort durchgereicht wird. Der Agent setzt diesen Kopf jetzt auf die Adresse des Anwendungsservers. Die Oberfläche der Konsole war deshalb zu sehen, ihr erster Aufruf an den Server aber nicht. - Der Ablagepfad wirkt jetzt wirklich. Die Repositories landeten trotz gesetztem Ablagepfad unmittelbar in der Freigabe (
sub-1statt<pfad>/sub-1). Grund: die Control Plane suchte das Sicherungsziel nur an der Sicherungsregel, und dort steht es fast nie — die Oberfläche schickt beim Speichern des Zeitplans keine Zielkennung mit, und wer das Ziel einmal entfernt und neu anlegt, verliert die Verknüpfung ohnehin. Jetzt wird das Ziel des Nodes genommen, wenn die Regel keines nennt; ein Node hat ohnehin genau eines. Bereits angelegte Repositories ziehen nicht um — sie liegen weiter am alten Ort und werden nicht mehr gefunden; wer den Ablagepfad nachträglich setzt, sichert ab dann neu. - Ein laufender Sicherungslauf ist im Panel zu sehen. Die Zeile mit dem Zustand läuft wird geschrieben, bevor der Node loslegt — nur wurde sie bisher erst festgeschrieben, wenn der Lauf längst vorbei war: der Endpunkt hielt die ganze Zeit eine einzige Transaktion offen. Genau dafür war die Zeile gedacht. Nebenbei blockierte das eine Datenbankverbindung über die volle Laufzeit, bis zu einer Stunde.
- Der Verlauf einer Subscription ist auch dann da, wenn er leer ist. Bisher verschwand die ganze Karte, solange noch keine Sicherung gelaufen war — es sah aus, als gäbe es die Funktion nicht. Jetzt steht dort, dass noch nichts gelaufen ist. Läuft gerade eine Sicherung, fragt die Seite den Stand alle 15 Sekunden nach, und die Zustände heißen geglückt, fehlgeschlagen und läuft statt
SUCCEEDED,FAILEDundRUNNING. mount error(13)sagt jetzt, was alles dahinterstecken kann. Der Server ist erreichbar und lehnt die Anmeldung ab — daran hängen mehr Stellschrauben als Benutzer und Passwort: die Berechtigung auf der Freigabe, eine erwartete Domäne (domain=<name>in den Zusatzoptionen), und ein Server, der nur SMB1 spricht. Der Hinweis nennt sie.- Zeigt die Adresse des Speichers auf den Node selbst, sagt der Verbindungstest das. Er hängt gar nicht erst ein. Das ist der häufigste Griff daneben bei einem Ziel hinter WireGuard: die Konfiguration nennt zwei Adressen — die eigene unter
[Interface] Addressund die der Gegenstelle — und im Feld Server landet die eigene. Bisher endete das inmount error(111), was nach einem Server aussieht, der nicht antwortet, und die Suche zum NAS schickte statt ins Formular. - Scheitert der Mount an einem Ziel hinter WireGuard, zeigt der Bericht den Tunnel.
wg show,ip addr show kastra-backupundip route get <server>hängen an der Originalausgabe. Nötig, weil „der Tunnel steht" drei verschiedene Dinge heißen kann: der Schnittstelle fehltAddress =, der Server liegt außerhalb vonAllowedIPs, oder die Gegenstelle hat nie geantwortet. Alle drei sahen im Panel gleich aus, und der Mount scheiterte mit einer Fehlernummer, die nach einem Problem am Server aussieht. mount error(111)wird gedeutet. StehtUnable to find suitable addressdabei — cifs hängt beide Meldungen ohne Trennzeichen aneinander —, nennt der Hinweis die fehlende Route und nicht den Server: der Grund liegt auf dem Node. Ohne den Zusatz bleibt es bei „auf Port 445 nimmt niemand an".- Komponenten mit setuid-Dateien lassen sich wieder einrichten. Der Knopf Einrichten brach bei
cifs-utilsmiterror setting permissions of './usr/sbin/mount.cifs': Operation not permittedab und ließ das Paket halb eingespielt liegen. Ursache war die Härtung des Agents selbst: seine systemd-Unit verbietet ihm, setuid-Dateien anzulegen, und diese Sperre vererbt sich auf dpkg. Der Agent ruftaptjetzt als eigene systemd-Unit auf, die die Sperre nicht erbt — die Sperre für den Agent bleibt, wo sie hingehört. Betroffen war neben dem Mount-Helfer auch die Container-Laufzeit, dieuidmapnachzieht; dort war es nur noch nie aufgefallen. Nebenbei verschwinden die vier Zeilendebconf: unable to initialize frontendaus jedem Installationsprotokoll. - Ein gescheiterter Mount sagt jetzt, woran es lag. Der Verbindungstest des Sicherungsziels gab bisher nur die Antwort von systemd weiter —
Job failed. See "journalctl -xe" for details.Das ist ein Verweis auf eine Sitzung, die derjenige nicht hat, der im Panel auf Verbindung prüfen gedrückt hat. Jetzt stehensystemctl status, die letzten 40 Journalzeilen und die Warnungen ausdmesgim Bericht, und die bekannten Meldungen bekommen einen Hinweis:mount error(13)nennt Benutzer und Passwort,mount error(2)den Freigabenamen,mount error(95)die SMB-Fassung,mount error(112)den Port 445. - Fehlt
cifs-utilsodernfs-common, steht das im Bericht. Ohne den Mount-Helfer scheitert das Einhängen mitunknown filesystem type— dieselbe Falle wie bei den WireGuard-Werkzeugen. Gefragt wird jetzt vorher, und die Antwort nennt das Paket. Auch der Rollout schreibt es in seinen Bericht, statt es der ersten fehlgeschlagenen Sicherung zu überlassen. - Ein abschließender Schrägstrich im Freigabepfad stört nicht mehr. Er entsteht beim Kopieren aus einem Dateimanager. Bisher schrieb ihn Kastra unverändert in die Mount-Unit:
//nas/backups/kunde/und//nas/backups/kundewaren für systemd zwei verschiedene Werte, die Unit wurde bei jedem Rollout neu geschrieben, undmount.cifsdeutete den Schrägstrich je nach Fassung als leeren letzten Pfadteil. - Die Ausgabe eines Updates bricht nicht mehr mitten im Einspielen ab. Sie endete regelmäßig bei „Setting up kastra-control-plane …", und danach kam nichts mehr — auch nicht, nachdem sich das Panel wieder verbunden hatte. Beim Update tauscht sich der Agent selbst aus, und auf dem Panel-Host danach die Control Plane; mit jedem dieser beiden Neustarts starb das Mitlesen des Node-Protokolls, ohne dass es jemand bemerkte. Kastra knüpft jetzt von selbst wieder an und liest dort weiter, wo es abgerissen ist — bis zum abschließenden „Update abgeschlossen". Dazu kündigt die Ausgabe an, dass die Control Plane sich gleich selbst neu startet, meldet, wenn der Agent weg ist und wenn er zurück ist, und schreibt in längeren Pausen, worauf gewartet wird. Und ein Rollout gilt erst als beendet, wenn auf dem Node wirklich Ruhe eingekehrt ist: bisher konnte er zumachen, während
aptnoch lief, und schnitt damit die letzten Zeilen ab. - WildFly belegt nicht mehr den Port der Control Plane. Die
standalone.xmlbringt ab Werk einen HTTPS-Listener auf 8443 mit — genau die Nummer, auf der die Control Plane hört. Kastra setzte nur den HTTP- und den Verwaltungsport, den dritten nicht; wer beim Systemstart zuerst kam, gewann. Kam WildFly zuerst, startete die Control Plane nicht mehr, und das Panel antwortete mit 502, ohne dass irgendwo stand, warum. WildFly bekommt jetzt auch diesen Port von der Control Plane (Vorgabe 8283, veränderbar überKASTRA_WILDFLY_HTTPS). Auf einem Node, auf dem WildFly schon eingerichtet ist, greift das erst nach einem erneuten Einrichten: Laufzeiten → WildFly → Einrichten mit der Fassung, die dort schon läuft. - **Der Bereich DNS zeigt jetzt alle Einträge, die der Arbeitskopf zählt.** Über der Domain stand „7 DNS-Einträge kommen nicht an", die Tafel darunter führte fünf auf: gezeigt wurden nur Adressen und CAA, die beanstandeten Mail-Einträge waren allein über den Bereich Mail zu finden. Die Tafel zeigt jetzt die ganze Zone — samt den Zeilen der Subdomains, die ja ebenfalls dort gepflegt werden — und die Zahl steht auch über der Tabelle, die sie erklärt. Jetzt prüfen nimmt die Subdomains mit.
- Eine Subdomain sagt, welche ihrer Einträge draußen nicht ankommen. Ihr Bereich DNS zeigte nur den Knopf Ganze Zone, während der Arbeitskopf „2 DNS-Einträge kommen nicht an" meldete — welche zwei, stand nirgends. Der Befund steht jetzt über dem Knopf, und der Bereich trägt wieder eine Marke.
- **Der Bereich Container zeigt nur noch die Anwendungen dieser Domain.** Zwei Container-Domains derselben Subscription laufen unter demselben Systembenutzer, und die Liste kam von
podman ps— die zeigt alles, was diesem Benutzer gehört. Unter der einen Domain standen deshalb die Container der anderen, samt ihren Ports. Gefiltert wird jetzt nach dem Compose-Projekt der Domain. Dasselbe galt für die Auswahl im [Protokollfenster](handbuch:protokolle): dort standen die Container fremder Domains zur Wahl. - Ein Zugang für ein Netz wirkt jetzt wirklich. Ein Host wie
203.0.113.0/24ging bis hierher unverändert an MariaDB, das im Host-Teil eine Maske erwartet und keine Präfixlänge — die Angabe wurde als Hostname gelesen. Der Zugang stand inSHOW GRANTS, sah richtig aus und traf nie zu. Kastra übersetzt ihn jetzt in die Schreibweise, die MariaDB versteht (203.0.113.%, bei ungewöhnlichen Netzgrenzen10.0.0.0/255.240.0.0). Eingetragen wird weiterhin CIDR. Alte, wirkungslose Einträge verschwinden spätestens beim Entfernen ihres Benutzers. - Eine Domain, deren Container nicht startet, gilt jetzt als gestört.
podman-compose upbeendet sich nicht, wenn ein Dienst scheitert — es meldet den Fehler und wartet dann auf Ereignisse, die nie kommen. systemd sah einen laufenden Hauptprozess, meldete läuft, und im Panel stand eine Domain, die lief und nichts auslieferte; auf einem Node blieb das stundenlang so, während das Imagemysql:8.0gar nicht aufgelöst werden konnte. Die Unit prüft nach dem Start, ob wenigstens ein Container läuft — bis zu fünf Minuten lang, damit ein Image noch geholt werden kann. Kommt keiner, gilt der Start als gescheitert, und der Bereich Protokolle zeigt unter Container-Dienst die Zeilen, die es erklären. Nach fünf gescheiterten Anläufen in einer Stunde bleibt die Unit stehen, statt im Minutentakt weiterzurattern. - **Der Bereich Protokolle zeigt endlich, was
podman-composesagt.** Das Journal der Container-Unit blieb leer — nicht, weil nichts geschrieben wurde, sondern weil Python seine Ausgabe zurückhält, solange sie nicht auf ein Terminal geht. Ein Bau, der zwanzig Minuten lief, meldete zwanzig Minuten lang nichts, und ein hängender Start meldete überhaupt nie etwas. Die Unit setzt jetztPYTHONUNBUFFERED=1; die Ausgabe erscheint, während sie entsteht. - Rootlose Container bekommen wieder Netz. Die Container-Unit setzte
PrivateTmp=true. systemd gibt ihr damit ein eigenes/tmpund räumt es weg, sobald die Unit endet — rootless Podman hält seinen Namensraum aber über einen Pause-Prozess fest, der die Unit überlebt, und jeder spätere Aufruf desselben Benutzers tritt diesem Namensraum bei. Darin war/tmpein gelöschter Eintrag,pastakonnte sein tmpfs nicht mehr anlegen und brach mit „Failed to sandbox process" ab. Danach kam kein Container dieses Kunden mehr ins Netz, auch nach einem Neustart des Nodes nicht, und die Meldung sah nach einem Fehler von pasta oder AppArmor aus. Die Zeile ist weg; für die Trennung sorgtTMPDIRim Verzeichnis des Kunden, das ohnehin gesetzt wird. Ein Node, der schon in diesem Zustand ist, heilt sich beim nächsten Rollout selbst: scheitert eine Unit mit dieser Meldung, erneuert der Agent den festgehaltenen Namensraum und startet sie neu. Der Vorgang steht im Protokoll der Aufgabe. - Die Container-Laufzeit spielt
pastamit ein und sagt es, wenn er fehlt. Ab Podman 5 bautpastadas Netz eines rootlosen Containers auf; bis Podman 4 war esslirp4netns, und nur das spielte Kastra ein. Auf einem Node mit Podman 5 startete deshalb kein einziger Container — mit der Meldungcould not find pasta, the network namespace can't be configured, die im Panel nirgends stand. Jetzt einrichten spielt das Paketpasstmit ein und bricht ab, wenn es das auf dieser Distribution nicht gibt und die Fassung es braucht. Der Bereich Container unter Laufzeiten führtpastaals eigene Zeile, und die Komponente gilt als nicht eingerichtet, solange er fehlt — vorher meldete sie „läuft". Auf Ubuntu 22.04 ändert sich nichts: dort läuft Podman 4. - Kurze Image-Namen wie
nginxlösen auch dann auf, wenn der Node schon eineregistries.confmitbringt.containers-commonlegt die Datei an und lässtunqualified-search-registriesdarin auskommentiert. Jetzt einrichten fasste eine vorhandene Datei nicht an und meldete im Bereich Container trotzdem „registries.conf: da" — jedesimage: nginxund jedesFROM redminebrach danach mitshort-name did not resolve to an aliasab. Geprüft wird jetzt die wirksame Angabe; fehlt sie, kommt sie als/etc/containers/registries.conf.d/99-kastra.confdazu. Die Datei der Distribution bleibt unangetastet, und wer Docker Hub bewusst nicht absuchen lässt, behält seine Einstellung. - Ein doppelter Eintrag im DNS-Editor legt die Zone nicht mehr still. Ein Node mit zwei Adressen bekommt je Name zwei A-Einträge; wer beide auf dieselbe Adresse setzte, schrieb dieselbe Zeile zweimal. PowerDNS weist ein RRset mit doppeltem Eintrag ab — und zwar die ganze Zone. Von da an lief jede weitere Änderung an dieser Zone ins Leere: neue Einträge kamen nicht an, DNSSEC liess sich nicht einschalten, und der Rollout meldete trotzdem Erfolg. Der Editor weist die doppelte Zeile jetzt vorher ab und sagt, welche es ist. Mehrere verschiedene Adressen unter einem Namen bleiben erlaubt.
- Konfiguration, Protokolle und Installer des Webmails sind nicht mehr erreichbar.
/webmail/config/,/webmail/logs/,/webmail/temp/und/webmail/installer/antworteten mit HTTP 200 und der Anmeldeseite. Inhalt gaben sie nicht preis — aber von aussen ist ein 200 auf/webmail/installer/nicht von einem erreichbaren Installer zu unterscheiden. Die Regel stand seit dem 2. September in der Vorlage; bestehende Anlagen bekamen sie nicht, weil der Nachtrag am vorhandenen Vhost fehlte. Er wird beim Update nachgezogen. - **Die Bereiche PHP und Mail einer Domain rollen auf schmalen Fenstern nicht mehr waagerecht.** Auf 280 px — ein zugeklapptes Foldable — schoben ein starres Mindestmass und ein zu langes Feldetikett die Seite über den Rand.
- Ein zweiter Versandzugang derselben Maildomain legt nicht mehr den Versand des ganzen Servers lahm. Beide Zugänge bekamen in
sender_login_mapsdenselben Eintrag@domain, und eine Postfix-Karte mit doppeltem Eintrag wird nicht geladen: jeder Versandversuch endete danach mit „451 4.3.0 Temporary lookup failure" — auch auf allen anderen Domains des Nodes. Zugänge, die sich eine Absenderadresse teilen, stehen jetzt gemeinsam in einer Zeile. Dasselbe gilt für Weiterleitungen, die auf denselben Absender treffen wie ein Catch-All. - Der Pfadwähler für die zusätzlichen
open_basedir-Pfade zeigt wieder Verzeichnisse. Er meldete bei jedem Aufruf, das Kommando werde von dieser Agent-Version nicht unterstützt, und riet zum Aktualisieren des Agents — der aktuelle Agent hatte den Fehler aber genauso: er nahm das Kommando entgegen, ohne es an den Dateimanager weiterzureichen. - „Ganze Zone" bei einer Subdomain führt jetzt wirklich zur Hauptdomain. Der Knopf wechselte die Adresse, die Seite blieb aber auf der Subdomain stehen — Kopfzeile, Bereichsleiste und der Bereich DNS zeigten weiter die alten Angaben.
- Der Balken unter einer Meldung läuft gleichmässig ab. Er sprang bisher im Zehntelsekundentakt und blieb hängen, wenn die Seite gerade zu tun hatte. Unter der Meldung stand ausserdem mehr Luft als darüber.
- Der Dateimanager behauptet kein Verzeichnis mehr, das er nicht lesen konnte. Antwortete der Node nicht, stand über der leeren Tabelle Eine Ebene höher — anklickbar, obwohl es gar keine Ebene darüber gab —, und darunter „Das Verzeichnis ist leer.". Neben dem Fehlerkasten las sich das, als sei dort bloß nichts abgelegt. Jetzt steht dort „Das Verzeichnis wurde nicht gelesen.", und die Zeile nach oben erscheint nur, wenn ein Verzeichnis wirklich geladen ist.
- Ein Dienst bleibt nicht mehr an seiner Startsperre hängen. systemd zählt die Startversuche einer Unit und verweigert danach jeden weiteren Start — auch den aus dem Panel — mit „start-limit-hit“. Wer die Ursache behoben hatte und auf Neu starten drückte, bekam die Unit trotzdem nicht mehr hoch; sichtbar wurde das an einer Container-Domain, deren Dienst nach fünf Fehlversuchen tot blieb. Der Agent löst die Sperre jetzt vor jedem Start — bei Containern, Node.js, WildFly, dem Objekt-Cache und ebenso bei nginx, Apache, PHP-FPM, Postfix und Dovecot. Die Bremse für den automatischen Wiederanlauf bleibt: eine kaputte Konfiguration rattert weiterhin nicht im Minutentakt weiter. Kastras eigene Dienste — Agent und Control Plane — kennen die Sperre gar nicht mehr: bei ihnen hätte sie bedeutet, dass jemand vor Ort sein muss, um das Panel wieder in Gang zu bringen.
- Das Suchsymbol in den Filterfeldern klebt nicht mehr am Rand. In den Listen Domains und Datenbanken und im Dateimanager sass die Lupe vor dem Filterfeld bündig auf dem Rahmen und stiess rechts fast an den Text dahinter. Den Abstand vergibt Material nur an sein eigenes Icon; Kastras Icons bekommen ihn jetzt ebenso — zwölf Pixel zur Kante, sechzehn zum Text. Dasselbe gilt für das Suchfeld im Handbuch.
- Das Fenster „Kastra wird eingespielt" rollt nicht mehr waagerecht. Es war breiter als sein eigenes Blatt: der Inhalt verlangte 680 Pixel Mindestbreite, während jeder Dialog auf 560 gedeckelt ist. Die rechte Hälfte jeder Zeile stand damit ausserhalb — der Fortschritt der Nodes, der Knopf In den Hintergrund und der Hinweis zum Neustart der Control Plane waren nur über eine Rollleiste zu erreichen, ausgerechnet während des Updates. Das Fenster ist jetzt so breit, wie Platz ist (höchstens 860 Pixel), und nimmt auf dem Telefon die ganze Fläche. Waagerecht rollt allein die Ausgabe des Rollouts, und die hat ihren eigenen Rahmen.
- Nach einem Neustart der Control Plane bleibt das Panel nicht mehr leer. Bricht die Verbindung mitten in einer Antwort ab — beim Neustart des Dienstes der Normalfall —, meldet der Browser einen Aufruf ohne Status, aber mit ein paar Bytes Rumpf. Angular hielt das für eine gelungene Antwort und reichte die Bytes als Zeichenkette weiter; die Oberfläche hielt sich daraufhin für angemeldet, begann die Navigation aufzubauen und brach beim ersten Zugriff auf die Rollen mittendrin ab. Zu sehen war eine leere Fläche — warum, stand nur in der Konsole des Browsers. Eine Antwort, die keine ist, gilt jetzt als Control Plane nicht erreichbar: es erscheint die Anmeldung, und sobald der Dienst wieder läuft, genügt ein erneutes Laden.
- Eine DNS-Zone bekommt eine echte Seriennummer. Neue Zonen entstanden mit Seriennummer 0 und behielten sie, solange niemand einen Eintrag änderte: PowerDNS vergibt die Nummer aus seiner Vorlage, und die Eintragsliste kommt beim Anlegen im selben Aufruf mit — es gab also nie eine Änderung, an der er hätte hochzählen können. Eine Zone mit Serial 0 holt kein zweiter Nameserver je ab, denn 0 ist nie größer als 0, und Prüfdienste halten sie für unfertig. Der nächste Rollout setzt bei betroffenen Zonen eine Nummer im üblichen Format JJJJMMTT01; Zonen mit einer echten Nummer bleiben unberührt.
- Ein schweigender Resolver meldet keinen fehlenden Eintrag mehr. Blieb eine DNS-Abfrage ohne Antwort — Zeitüberschreitung, SERVFAIL, kein Netz —, stand in der Tafel wird nicht veröffentlicht, dasselbe wie bei einem Eintrag, den es wirklich nicht gibt. Das gab dem Betreiber eine Aufgabe, die es womöglich gar nicht gab. Jetzt steht dort keine Antwort vom Resolver, und diese Zeilen zählen nicht als Beanstandung.
- Ein Adresswechsel legt den Nameserver nicht mehr still. Die Adressen, auf denen PowerDNS lauscht, wurden beim Einrichten einmal aus der Standardroute erkannt und fest in die Konfiguration geschrieben. Bekam der Node später eine andere Adresse — beim Wechsel von einer automatisch gebildeten IPv6 auf eine feste etwa —, band PowerDNS beim Start weiter die alte, brach mit Cannot assign requested address ab und lief überhaupt nicht mehr an; im Panel stand nur „Der Dienst läuft nicht", und mit ihm waren alle Zonen des Nodes weg. Der Rollout zieht die Adressen jetzt bei jedem Lauf nach und startet den Dienst nur, wenn sich wirklich etwas geändert hat.
- Ein installationsweites GitHub-Konto stand jedem angemeldeten Benutzer offen, nicht nur Administratoren. Die Liste unter Einstellungen › GitHub zeigte einem Kunden zu Recht kein Konto ohne eigene Subscription — aber mit der Kennung eines solchen Kontos kam er trotzdem an dessen Repositories, konnte es prüfen und sogar trennen. Jetzt gilt für die Kennung dieselbe Regel wie für die Liste: nur ein Administrator sieht ein installationsweites Konto.
- Die Warnung „das würde dich aussperren“ bei der Firewall prüft jetzt wirklich das Netz. Trug die Verwaltungsfreigabe ein Netz, dessen Präfixlänge nicht /24 war — etwa /8 oder /25 —, verglich die Prüfung nur den Text bis zum letzten Punkt vor dem Schrägstrich. Ein /8-Netz wie 10.0.0.0/8 deckte die eigene Adresse 10.1.2.3 damit gar nicht, und ein /25-Netz verhielt sich wie ein /24. Beim Einschalten der Firewall oder der begrenzten Verwaltung kam so entweder eine falsche Warnung oder gar keine.
Der DKIM-Eintrag steht als Wert da, nicht als ganze Zonenzeile. Im Bereich DNS und DKIM einer Maildomain enthielt die Spalte Wert die vollständige Ausgabe von
rspamadm: den Namen,IN TXT, Klammern und den Schlüssel in mehrere Anführungszeichen zerlegt. Wer das so in das Wertfeld seines Registrars kopierte, bekam einen Eintrag, derkastra._domainkeynoch einmal als Text enthielt — gegen den prüft keine Signatur, und die ausgehende Post galt beim Empfänger als unsigniert. Führt Kastra die Zone selbst, stand dieselbe Zeile auch dort im TXT-Eintrag.Jetzt steht in der Spalte und in der Zone nur der Wert:
v=DKIM1; k=rsa; p=…. Bestehende Schlüssel werden beim Anzeigen mitgezogen; erneuert werden muss keiner. Steht in einer eigenen Zone schon ein falscher TXT-Eintrag, wird er beim nächsten Schreiben richtiggestellt — beim Erneuern des Schlüssels oder beim Aus- und wieder Einschalten von Mail für die Domain. Die Spalte hat dabei Platz bekommen: Typ und Name brechen nicht mehr mitten im Wort um.Ein erneuerter DKIM-Schlüssel steht sofort in der eigenen Zone. DKIM-Schlüssel erneuern legte ein neues Paar an, und der Node signierte ab diesem Augenblick damit — der öffentliche Teil in der Zone blieb aber der alte. Jede ausgehende Mail trug von da an eine Signatur, die kein Empfänger prüfen konnte, und nichts im Panel sagte es: die Meldung schickte auch bei einer Zone in Kastra jeden zum Registrar.
Führt Kastra die Zone, zieht sie den TXT-Eintrag jetzt mit, und die Meldung sagt, was geschehen ist. Angefasst wird dabei nur der DKIM-Eintrag — ein SPF, den jemand von Hand anders gesetzt hat, bleibt stehen, wie er steht. Bei einer fremden Zone ändert sich nichts: der Eintrag gehört dort weiter von Hand nachgezogen.
Rendert anders
- nodejs-unit —
ExecStartstartet die Anwendung jetzt hinter/usr/local/bin/kastra-agent zeitstempel --, der jeder Ausgabezeile Datum und Uhrzeit voranstellt. Die Protokolldateien bleiben dieselben. Eine laufende Anwendung wird dafür nicht neu gestartet; die neue Unit gilt ab ihrem nächsten Neustart. - nginx-vhost — im server-Block stehen jetzt
send_timeout,keepalive_timeoutund, bei eingeschalteter Kompression,gzipsamtgzip_types. Die Werte entsprechen dem, was vorher galt; komprimiert wird jetzt auch CSS, JavaScript, JSON und SVG statt nur HTML. - apache-vhost — der Backend-Block bekommt
LimitRequestBody,Timeout,ProxyTimeoutundKeepAliveTimeout.ProxyTimeoutist neu wirksam: Apache brach vorher nach seiner eigenen Vorgabe von 60 Sekunden ab, auch wenn nginx davor länger gewartet hätte. - apache-vhost — der
SetHandlerauf den FPM-Socket steht jetzt in einem<If "-f %{REQUEST_FILENAME}">. Nur vorhandene Dateien gehen damit an PHP-FPM; ein fehlender Pfad wird von Apache beantwortet und läuft dadurch in dessenErrorDocument. - nginx-vhost — bei einer Domain im Wartungsmodus liest die
mapjetzt$uristatt$request_uri, trägtvolatileund nimmt neben/.well-known/auch/.kastra-fehler/aus. Ohne Wartungsmodus bleibt die Datei unverändert. - mariadb-99-kastra-cnf — die Datei trägt neben
bind-addressjetzt auchskip-name-resolve. Ein Rollout kann MariaDB dafür einmal neu starten. - pdns-kastra-conf — die Zeile
local-addresswird ab jetzt bei jedem Rollout nachgezogen statt nur beim Einrichten. Auf einem Node, dessen Adressen sich seit der Einrichtung geändert haben, wird sie damit einmalig neu geschrieben, und PowerDNS startet dabei neu. Ist nichts anders, bleibt die Datei unberührt. - crowdsec-acquis — die Quellenliste
/etc/crowdsec/acquis.d/kastra.yamlnennt die Protokolle der Domains jetzt unter/var/log/kastra/subscriptionsstatt unterlogsim Heimatverzeichnis, und sie wird bei jedem Rollout nachgezogen statt nur beim Einrichten. Eingelesen werden dieselben Dateien wie vorher, nur unter ihrem echten Pfad. Mit dem Schalter CrowdSec aus räumt der Rollout sie weg — wie die Whitelist auch. - crowdsec-whitelist — ist mindestens eine Domain von den IP-Sperren ausgenommen, entsteht neben
kastra-whitelist.yamlundkastra-panel.yamleine dritte Dateikastra-domains.yamlmit den Protokollpfaden dieser Domains. Ohne ausgenommene Domain gibt es sie nicht, und eine früher geschriebene wird beim Rollout weggeräumt.