Überblick

Das Problem

Eine Contao-Installation, die produktiv läuft, wird selten aktualisiert — und genau das ist der Kern des Problems. Je länger der letzte Composer-Lauf zurückliegt, desto größer wird der Sprung, und desto mehr hängt an einem einzigen Kommando, das man irgendwann abends über SSH absetzt und dann hofft, dass es durchläuft.

  • Das Zeitfenster ist nicht planbar. composer update dauert je nach Paketzahl und Hoster zwischen zwei und zwanzig Minuten. Läuft es im Browser, reißt irgendwann das PHP-Timeout, und man weiß nicht, ob der Vorgang abgeschlossen ist oder mittendrin abgebrochen wurde.
  • Der Rückweg ist nicht vorbereitet. Ein Backup vor dem Update ist eine Aufgabe, die man vergisst oder auf „mache ich gleich noch" verschiebt. Wenn das Update die Seite zerlegt, stellt sich heraus, dass das letzte Backup vom Hoster stammt, zwei Tage alt ist und über ein Support-Ticket beantragt werden muss.
  • Nach einem kaputten Update fehlt der Zugang. Ein fehlgeschlagenes Update trifft üblicherweise vendor/. Danach bootet Symfony nicht mehr, also bootet Contao nicht mehr, also gibt es kein Backend — und jedes Werkzeug, das im Backend liegt, ist genau in dem Moment weg, in dem man es braucht.
  • Auf Shared Hosting stimmen die PHP-Versionen nicht überein. Bei Plesk läuft der Webserver über /opt/plesk/php/8.4/sbin/php-fpm, die CLI liegt unter /opt/plesk/php/8.4/bin/php. Ruft man Composer über einen Shell-Wrapper auf, erwischt man womöglich eine andere PHP-Version mit anderen Extensions als die, unter der die Seite tatsächlich läuft.
  • Man sieht nicht, was überhaupt anliegt. Ob ein Paket verlassen („abandoned") ist, ob eine neuere Version existiert und ob sie wegen der Constraints anderer Pakete überhaupt installierbar wäre, steht in keinem Backend-Bildschirm — man erfährt es erst, wenn Composer sich weigert.
  • Regelmäßige Backups sind Handarbeit. Ohne Automatisierung entsteht eine Sicherung nur dann, wenn jemand daran denkt. Das ist der Zustand, in dem sich die meisten kleinen und mittleren Contao-Installationen befinden.

Am härtesten trifft es Agenturen und Freelancer, die eine zweistellige Zahl fremder Installationen betreuen, auf Hosting-Umgebungen, die sie sich nicht ausgesucht haben, und die im Ernstfall nachts erreichbar sein müssen.

Die Lösung

Guardian verlegt Update und Restore aus dem Browser-Request in einen eigenständigen Hintergrundprozess und legt daneben einen zweiten, framework-freien Zugang, der auch dann noch funktioniert, wenn Contao nicht mehr bootet.

Strukturell ändert sich dadurch dreierlei. Erstens läuft ein Update als Job in einem eigenen PHP-CLI-Prozess, losgelöst vom Webserver-Timeout; das Backend fragt nur noch Status und Log ab. Zweitens wird der Snapshot nicht mehr optional nebenher erstellt, sondern ist ein fester Schritt der Update-Pipeline, der vor jeder Änderung läuft. Drittens liegt das Wiederherstellungswerkzeug bewusst außerhalb von Contao — eine einzelne PHP-Datei, die der Webserver direkt ausliefert.

Aufgabe Ohne Guardian Mit Guardian
Update ausführen SSH, composer update im Terminal, Verbindung offen halten Job im Backend starten; läuft im eigenen Prozess weiter, Browser kann zu
Update vorher testen Kopie der Seite aufsetzen Dry-Run: composer update --dry-run und contao:migrate --dry-run
Backup vor dem Update Manueller Schritt, der oft ausfällt Pre-Update-Snapshot als fester erster Schritt jeder Pipeline
Regelmäßige Backups Hoster-Backup oder gar keins Zwei getrennte Zeitpläne (Mini / Full) über Contaos Cron-System
Wiederherstellen nach kaputtem Update Backend weg — Ticket beim Hoster, Datenbank-Import von Hand Standalone-Panel im Webroot, arbeitet ohne Contao, Symfony oder Composer
Überblick über Paketstand composer outdated über SSH Paketübersicht im Backend, direkt gegen Packagist, 24 h gecacht

Zugeordnet zu den Punkten oben:

  • ZeitfensterUpdate-Jobs: eigener CLI-Worker mit aufgehobenem Zeitlimit, Fortschritt per Polling.
  • RückwegPre-Update-Snapshot: erster Schritt der Pipeline, mit Ein-Klick-Rollback, wenn der Job fehlschlägt.
  • Fehlender ZugangStandalone-Recovery-Panel: eine PHP-Datei ohne Abhängigkeiten, eigene Token-Authentifizierung.
  • PHP-VersionenPHP-CLI-Einstellungen: der Pfad zur CLI-Binary ist im Backend konfigurierbar; Composer läuft immer als <konfiguriertes PHP> composer.phar, nie über einen Shell-Wrapper.
  • SichtbarkeitVorabprüfung und Paketübersicht.
  • HandarbeitGeplante Backups mit Aufbewahrungsgrenze und optionaler E-Mail-Benachrichtigung.

Wann das Paket passt

Situation Einschätzung
Contao 5.3+ auf Shared Hosting (Plesk, cPanel, DirectAdmin) Passt. Genau dafür gebaut — inklusive konfigurierbarem CLI-Pfad und Fallbacks, wenn mysqldump oder tar fehlen.
Agentur betreut mehrere fremde Installationen Passt. Backup, Update und Notfallzugang ohne SSH auf jeder Installation — pro Installation allerdings eine eigene Lizenz, gebunden an deren Domain.
Redaktionsseite ohne Entwickler im Haus Passt. Vorabprüfung und Dry-Run zeigen vor jeder Änderung, was passieren würde.
Sie wollen nur regelmäßige Datenbank-Backups, sonst nichts Passt, aber prüfen Sie die Alternativen. Geplante Backups sind Pro. Contao bringt mit contao:backup:create bereits einen eigenen Datenbank-Backup-Befehl mit, den ein Server-Cron direkt aufrufen kann.
Deployment läuft über Git und CI/CD, vendor/ wird im Build erzeugt Eher nicht. In dieser Aufstellung gehört das Update in die Pipeline, nicht ins Backend der Produktivinstallation. Guardian würde gegen Ihren Deployment-Prozess arbeiten.
Mehrere Knoten hinter einem Loadbalancer ohne gemeinsames var/ Nicht geeignet. Lizenzzustand, Job-Ablage und Replay-Ledger liegen im Dateisystem unter var/ und setzen einen gemeinsamen, transaktionalen Speicher voraus.
Contao 4.13 oder älter Nicht geeignet. contao/core-bundle: ^5.3 ist eine harte Anforderung.
Hosting ohne PHP-Extension sodium Nicht nutzbar. Ohne sodium kann keine Lizenz verifiziert werden; die Installation bleibt unlizenziert (fail closed).

Teil 1 — Einrichtung

Der Weg von der Installation bis zum ersten verwendbaren Backup:

  1. Voraussetzungen prüfen
  2. Vor der Installation: sichern und entscheiden
  3. Installation über den Contao Manager — oder über Composer
  4. Installation überprüfen
  5. Lizenz aktivieren
  6. PHP-CLI-Pfad konfigurieren
  7. Das erste Backup erstellen

Voraussetzungen

Aus composer.json des Pakets.

Anforderung Version Anmerkung
PHP ^8.2 Zusätzlich wird eine erreichbare PHP-CLI-Binary benötigt.
contao/core-bundle ^5.3
ext-json In praktisch jeder PHP-Installation vorhanden.
ext-sodium Erforderlich für die Ed25519-Signaturprüfung der Lizenz. Fehlt sie, bleibt die Installation unlizenziert.
symfony/process ^6.4 || ^7.0 Start des Hintergrund-Workers.
symfony/console ^6.4 || ^7.0
symfony/http-client ^6.4 || ^7.0 Kommunikation mit dem Lizenzserver.

Nicht erzwungen, aber empfohlen:

Werkzeug Wofür Wenn es fehlt
mysqldump / mysql Datenbank sichern und zurückspielen Ein PHP-basierter Fallback übernimmt.
tar Verzeichnisse archivieren (gzip) Ein ZipArchive-Fallback übernimmt.
composer.phar Update-Jobs Updates lassen sich nicht ausführen. Pfad ist konfigurierbar.
exec() nicht in disable_functions Worker-Start, PHP-Binary-Test Der Test der PHP-Binary meldet „Cannot test: exec() is in disable_functions."

Vor der Installation

  1. Sichern Sie die Installation außerhalb von Guardian. Das erste Guardian-Backup entsteht erst nach der Einrichtung. Für den Installationsschritt selbst brauchen Sie eine unabhängige Sicherung.
  2. Klären Sie die Domain. Die Lizenz wird exakt an die Hostnamen gebunden, die auf den Website-Startseiten im Seitenbaum unter DNS eingetragen sind. Es gibt kein Wildcard-Matching, kein Suffix-Matching und keine automatische Gleichsetzung von www.beispiel.de und beispiel.de. Tragen Sie die Domain also vor der Aktivierung ein — und zwar in genau der Schreibweise, unter der die Seite erreichbar ist.
  3. Finden Sie den Pfad zur PHP-CLI-Binary heraus. Bei Plesk ist es derselbe Pfad, den auch der Contao Manager verwendet, typischerweise /opt/plesk/php/8.4/bin/php. Ohne ihn laufen keine Update- und Restore-Jobs.
  4. Entscheiden Sie über den Speicherort der Backups. Standard ist var/updater/backup. Ein eigener absoluter Pfad ist möglich — siehe Geplante Backups.

Schreibrechte werden für diese Verzeichnisse benötigt:

Verzeichnis Wofür
var/updater/ Jobs, Logs, Backups, Laufzeitkonfiguration, Lizenzzustand, Zeitplan
vendor/ Composer-Update und Restore des Verzeichnisses
public/ Nur wenn das Standalone-Recovery-Panel ausgeliefert werden soll

Die Vorabprüfung kontrolliert genau diese drei Pfade und meldet fehlende Schreibrechte als „Kein Schreibzugriff: …".

Installation über den Contao Manager

  1. Contao Manager öffnen und anmelden.
  2. Bereich Entdecken öffnen. Neue Pakete werden immer dort gesucht und hinzugefügt; der Bereich Pakete daneben zeigt unter Installierte Pakete nur, was bereits vorhanden ist. Entdecken ist zugleich die Startansicht des Managers.
  3. Über Pakete suchen nach vtinnovations/guardian suchen und beim Treffer Paket hinzufügen wählen.
  4. Änderungen anwenden. Der Contao Manager installiert das Paket und aktualisiert den Autoloader. Das Bundle registriert sich über seinen ContaoManager\Plugin selbst — es ist kein Eintrag in einer Bundle-Konfiguration nötig.
  5. Bereich SystemwartungDatenbank-Migrationen und -BackupsDatenbank prüfen; die angezeigten Datenbank-Änderungen bestätigen.
  6. Unter Systemwartung den Anwendungs-Cache leeren (in der Navigation auch als Cache erneuern bezeichnet).

Der Contao Manager spricht Sie in seiner Oberfläche mit du an, etwa: „Dieses Paket wird installiert, wenn du die Änderungen anwendest." Das ist die wörtliche Beschriftung des Werkzeugs und wurde hier nicht angepasst.

Installation über Composer

composer require vtinnovations/guardian

Anschließend Cache leeren und die Datenbank aktualisieren:

vendor/bin/contao-console cache:clear
vendor/bin/contao-console contao:migrate

Bei einer Managed Edition, die frisch aufgesetzt wurde, übernimmt contao:setup die Einrichtung der Verzeichnisse und Symlinks:

vendor/bin/contao-console contao:setup

Ein späteres Update des Pakets:

composer update vtinnovations/guardian --with-dependencies
vendor/bin/contao-console cache:clear
vendor/bin/contao-console contao:migrate

Nicht per ZIP austauschen. Guardian ist ein Composer-Bundle mit PSR-4-Autoloading. Wird das Verzeichnis unter vendor/ von Hand ersetzt, bleibt der Autoloader auf dem alten Stand und die Klassen werden nicht gefunden. Aktualisieren Sie ausschließlich über Composer oder den Contao Manager.

Installation überprüfen

Dass das Bundle registriert ist, zeigt der Konsolenbefehl, den es mitbringt:

vendor/bin/contao-console list guardian

In der Ausgabe muss guardian:run-job auftauchen. Erscheint der Befehl nicht, ist das Bundle nicht geladen — dann Cache leeren und prüfen, ob das Paket tatsächlich in composer.lock steht.

Im Backend erscheint nach dem Anmelden als Administrator:

  • Im Hauptmenü unter Inhalte der Eintrag Guardian. Liegen Paket-Updates vor, steht deren Anzahl in Klammern dahinter, etwa Guardian (7).
  • Unter Einstellungen der Abschnitt V-T.ONE Licence management mit dem Unterpunkt Guardian und dem Hilfetext „Guardian-Lizenz für diese Installation aktivieren, aktualisieren oder entfernen."
  • Auf der Backend-Startseite eine Systemmeldung „📦 N Paket-Updates verfügbar", sobald eine Paketprüfung gelaufen ist und Updates gefunden hat.

Alle Guardian-Funktionen erfordern einen Contao-Administrator (ROLE_ADMIN). Ein normaler Backend-Benutzer sieht den Menüpunkt nicht nutzbar; jede Aktion der Backend-API prüft die Administratorrolle serverseitig erneut. Das ist bewusst strenger als Contaos Standard, bei dem Backend-Routen jedem angemeldeten Benutzer offenstehen — ein Redakteur könnte sonst ein echtes Update auslösen oder den PHP-Binary-Pfad umschreiben.

Lizenz aktivieren

Die Lizenzverwaltung liegt zentral unter Contao → Einstellungen → Guardian Licence management. Der Abschnitt wird direkt in Contaos eigenes Einstellungsformular eingeblendet; das Bundle besitzt dafür keine eigene Route.

  1. Lizenzschlüssel in das Feld Lizenzschlüssel eintragen (Format laut Platzhalter: XXXXX-XXXXX-XXXXX-XXXXX).
  2. Auf Lizenz prüfen & aktivieren klicken.
  3. Bei Erfolg erscheint: „Die Guardian-Lizenz wurde erfolgreich aktiviert."

Zwei weitere Schaltflächen stehen zur Verfügung:

Schaltfläche Wirkung
Lizenz prüfen & aktivieren Prüft den eingegebenen Schlüssel gegen den Lizenzserver und legt das signierte Ergebnis lokal ab.
Lizenz aktualisieren Holt den aktuellen signierten Zustand erneut. Nötig nach Ablauf der Online-Prüffrist und bei einem Schlüssel aus einer früheren Version.
Lizenz entfernen Fragt per Dialog nach: „Lizenz entfernen? Lizenzierte Funktionen werden sofort deaktiviert; Backups, Jobs und Einstellungen bleiben erhalten."

Der Hinweistext des Panels lautet: „Der Schlüssel wird als signierter Datensatz abgelegt, nicht in der Contao-Konfiguration." Konkret landet er unter var/updater/registration.json, zusammen mit dem Integritäts-Envelope registration.seal und der gebundenen Domain registration.scope.

Ohne konfigurierte Domain schlägt die Aktivierung fehl. Die Meldung lautet: „Für diese Installation ist keine Domain konfiguriert. Setze die Domain auf einer Website-Root-Seite (oder über die Umgebungsvariable VTINNOVATIONS_GUARDIAN_DOMAINS), bevor du eine Lizenz aktivierst." Die Domain-Inventur speist sich aus den dns-Feldern aller Website-Startseiten im Seitenbaum; die Umgebungsvariable ergänzt sie als Komma-Liste für Installationen, deren Startseiten kein DNS-Feld gesetzt haben.

Ein Netzwerkfehler löscht niemals eine bestehende Lizenz. Ist der Server nicht erreichbar, meldet das Panel: „Der Lizenzserver war nicht erreichbar. Es wurde nichts geändert — eine bestehende Lizenz bleibt aktiv. Bitte später erneut versuchen."

PHP-CLI-Pfad konfigurieren

Im Backend unter Guardian → ⚙️ Einstellungen → ⚙️ PHP-CLI-Einstellungen. Der beschreibende Text lautet dort: „Updates und Restores laufen in einem Background-PHP-Prozess. Wir brauchen den absoluten Pfad zur PHP-CLI-Binary (nicht die FPM/Web-Version). … Leer lassen für Auto-Erkennung."

Guardian sucht die Binary in dieser Reihenfolge:

  1. Der im Backend eingetragene Pfad (var/updater/runtime.json).
  2. Die Umgebungsvariable PHP_CLI_BINARY aus .env.local.
  3. Symfonys PhpExecutableFinder.
  4. Die Konstante PHP_BINARY — aber nur, wenn sie auf eine CLI-Binary zeigt.
  5. Ableitung der CLI-Binary aus dem FPM-Pfad (/opt/plesk/php/8.4/sbin/php-fpm/opt/plesk/php/8.4/bin/php).
  6. command -v php über die Shell.

Die Schaltfläche 🔍 Testen ruft den angegebenen Pfad mit -v auf und prüft die Ausgabe. Ein Pfad, dessen Dateiname -fpm oder -cgi enthält, wird sofort abgelehnt: „This appears to be an FPM/CGI binary, not CLI. Look for the same path under /bin/ instead of /sbin/."

Der Test prüft bewusst nicht mit file_exists(), ob die Datei existiert. Unter Plesk verhindert open_basedir, dass PHP-FPM /opt/plesk/php/… überhaupt sehen kann — obwohl exec() dieselbe Binary problemlos ausführt. Aus demselben Grund zeigt die Vorschlagsliste auf solchen Hosts alle üblichen Kandidaten statt nur die nachweislich vorhandenen.

Das erste Backup

Im Backend unter Guardian → 💾 Backup. Wählen Sie unter Backup-Inhalte die gewünschten Komponenten und klicken Sie auf 💾 Backup jetzt erstellen.

Das manuelle Backup läuft synchron. Der Bestätigungsdialog sagt es deutlich: „Es läuft synchron — lasse diesen Tab offen, bis es fertig ist." Anders als ein Update-Job ist dies kein Hintergrundprozess. Ist files/ ausgewählt, warnt der Dialog zusätzlich: „files/ ist ausgewählt — das kann bei vielen Uploads mehrere Minuten dauern."

Nach Abschluss erscheint das Backup in der Liste darunter, mit Name, Größe und enthaltenen Komponenten. Backups liegen unter var/updater/backup/<Zeitstempel> und werden nie überschrieben.

Teil 2 — Funktionen im Detail

Die Backend-Oberfläche gliedert sich in fünf Reiter: 📊 Dashboard, 🔄 Update, 💾 Backup, 🛟 Recovery und ⚙️ Einstellungen.

Dashboard

Zeigt oben ein Lizenz-Abzeichen — „⭐ Pro-Paket aktiv", „🆓 Free-Paket aktiv" oder „🚫 Keine Lizenz" — mit der dazugehörigen Erläuterung, welche Funktionen daraus folgen.

Darunter drei Kennzahlen: Aktuelle Contao-Version, Installierte Pakete und Verfügbare Backups.

Der Block Aktueller Status zeigt den Zustand der letzten Operation:

Anzeige Bedeutung
✓ Idle — keine Operation läuft Nichts in Arbeit. Der Hinweistext ergänzt: „Die nächste Aktion (Update, Backup oder Restore), die du startest, erscheint hier."
⏳ Läuft — Operation in Bearbeitung Ein Job arbeitet gerade.
✓ Letzte Operation erfolgreich Der letzte Job ist sauber durchgelaufen.
⚠️ Letzte Operation fehlgeschlagen Der letzte Job ist gescheitert.

Vorabprüfung (Pre-Update-Analyse)

Auf dem Dashboard, Schaltfläche 🔍 Analyse starten. Der Beschreibungstext: „Prüft die Voraussetzungen für ein Update — vollständig nur lesend, verändert nichts." Das Ergebnis wird zusammengefasst als „✅ N OK · ⚠️ N Warnungen · ❌ N Fehler".

Prüfung Kriterium Meldung bei Problem
PHP-Version mindestens 8.2.0 „PHP … ist zu alt — Contao 5 benötigt mindestens PHP 8.2.0"
Composer composer.phar in den üblichen Pfaden auffindbar „Composer wurde in den üblichen Pfaden nicht gefunden — Updates müssen ggf. anders ausgeführt werden"
Schreibrechte vendor/, var/, public/ beschreibbar „Kein Schreibzugriff: …"
Speicherplatz mindestens 500 MB frei „Nur N MB frei — mindestens 500 MB empfohlen"
Composer-Pakete keine verlassenen Pakete in vendor/composer/installed.json „N verlassene(s) Paket(e): …"
Datenbank-Konfiguration DATABASE_URL in .env / .env.local „DATABASE_URL nicht in .env / .env.local gefunden — Backup muss übersprungen werden"
Legacy-Module kein Inhalt unter system/modules/ „N Legacy-Modul(e) gefunden: … Diese verwenden das alte Contao-3-Extension-Format und sollten vor einem Upgrade auf Composer/Symfony-Bundles migriert werden."

Die Gesamtbewertung lautet „Alles bereit — Update kann gestartet werden", „Update grundsätzlich möglich — bitte Warnungen prüfen" oder „Kritische Probleme gefunden — bitte zuerst beheben".

Paketübersicht

Ebenfalls auf dem Dashboard. 📦 Pakete laden zeigt alle installierten Composer-Pakete; 🔄 Updates prüfen fragt Packagist nach den neuesten stabilen Versionen ab — unabhängig von den aktuellen composer.json-Constraints. Die Ergebnisse werden 24 Stunden zwischengespeichert; bis dahin trägt die Anzeige den Zusatz „(gecacht — für Refresh „Updates prüfen" klicken)".

Die Tabelle hat vier Spalten: Paket, Aktuell, Verfügbar, Status. Der Status ist einer von:

Markierung Bedeutung
aktuell Keine neuere Version auf Packagist.
Update Eine neuere Version existiert und ist voraussichtlich installierbar.
⚠ blockiert „Update existiert, ist aber durch Constraints anderer Pakete blockiert"
abandoned Das Paket wurde von seinem Autor als verlassen markiert.

Die Oberfläche formuliert die wichtigste Einschränkung selbst: „‚Update verfügbar' bedeutet nur, dass auf Packagist eine neuere Version existiert. Ob sie tatsächlich installiert werden kann, hängt von Dependency-Constraints ab und erfordert unter Umständen, mehrere Pakete gemeinsam zu aktualisieren (z. B. bei einem Contao-Major-Upgrade)."

Manuelles Backup

Reiter 💾 Backup. Verfügbar ab der Free-Lizenz.

So erstellen Sie ein Backup

  1. Im Backend Inhalte → Guardian öffnen und auf den Reiter 💾 Backup wechseln.
  2. Unter Backup-Inhalte die Komponenten ankreuzen. composer.json, composer.lock und die Datenbank sind immer enthalten und lassen sich nicht abwählen. Wählbar sind nur vendor/, templates/ (zusammen mit contao/templates/), files/ und assets/. Welche Sie brauchen, steht in der Tabelle unten.
  3. Auf 💾 Backup jetzt erstellen klicken.
  4. Den Bestätigungsdialog lesen und bestätigen. Er lautet: „Backup jetzt erstellen? Es läuft synchron — lasse diesen Tab offen, bis es fertig ist." Ist files/ angekreuzt, kommt hinzu: „⚠️ files/ ist ausgewählt — das kann bei vielen Uploads mehrere Minuten dauern."
  5. Den Browser-Tab offen lassen und warten. Währenddessen steht dort „Backup wird erstellt…". Anders als ein Update ist dies kein Hintergrundjob — schließen Sie den Tab, bricht der Vorgang ab.
  6. Nach Abschluss erscheint die Bestätigung „Backup erstellt: <Name> · <Größe>", und das Backup steht in der Liste darunter — mit Zeitstempel, Größe und den enthaltenen Komponenten.

Welche Komponenten braucht man wirklich? Für ein Backup, aus dem sich die Seite vollständig wiederherstellen lässt, brauchen Sie vendor/ und files/. Ohne vendor/ müssen Sie nach einer Wiederherstellung composer install von Hand nachziehen; ohne files/ verweist die wiederhergestellte Datenbank auf Bilder und Dokumente, die nicht mehr da sind. Wer files/ wegen der Größe weglässt, sollte dieses Verzeichnis getrennt sichern — etwa über das Backup des Hosters.

Komponente Beschreibung laut Oberfläche Standard
composer.json + composer.lock + Datenbank „Immer enthalten — klein (wenige MB)." immer
vendor/ „Composer-Abhängigkeiten. Empfohlen. Typischerweise 100–500 MB." an
templates/ + contao/templates/ „Eigene Twig- und HTML5-Templates. Klein." an
files/ „Uploads der Nutzer — Bilder, PDFs, Videos. Oft mehrere GB. Ohne dieses Verzeichnis kann ein Rollback zu inkonsistenten DB-Referenzen und fehlenden Mediendateien führen." aus
assets/ „Generierte Bilder, Webfonts und JS/CSS-Asset-Cache. Meist wieder aufbaubar." aus

Ablage: var/updater/backup/<Zeitstempel>, Format JJJJ-MM-TT_SS-MM-SS. Jedes Backup enthält eine manifest.json mit Erstellungszeit, Contao-Version, Gesamtgröße und Komponentenliste. Verzeichnisse werden per tar gzip-komprimiert, die Datenbank per mysqldump; fehlen die Werkzeuge, greifen die genannten PHP-Fallbacks.

Ein vorhandenes Backup lässt sich über Löschen entfernen. Der Dialog warnt: „Backup „…" löschen? Das kann nicht rückgängig gemacht werden."

Geplante Backups

Ebenfalls im Reiter 💾 Backup, unterhalb der Backup-Liste. Erfordert eine Pro-Lizenz; ohne sie steht dort: „🔒 Das System für geplante Backups benötigt eine gültige Pro-Lizenz. … Manuelle Backups oben bleiben verfügbar."

So richten Sie einen Zeitplan ein

  1. Reiter 💾 Backup öffnen und bis zum Abschnitt Geplante Backups scrollen.
  2. Bei 🗄️ Mini-Backup (nur DB) das Häkchen Geplante Mini-Backups aktivieren setzen. Als Einstieg sinnvoll: Häufigkeit = Täglich, Uhrzeit = eine verkehrsarme Zeit, Behalte letzte = 7 Backups.
  3. Bei 📦 Full-Backup ebenso verfahren — hier zusätzlich unter In Full-Backup einschließen: die Verzeichnisse wählen. Standard ist wöchentlich, sonntags, 02:00, 4 Backups mit vendor/ und templates/.
  4. Unter Speicherort & Benachrichtigungen bei Bedarf einen eigenen Speicherpfad eintragen (absoluter Pfad; leer lassen für var/updater/backup).
  5. Empfänger eintragen und mindestens Bei fehlgeschlagenem Backup benachrichtigen aktiviert lassen — sonst erfahren Sie von einem gescheiterten nächtlichen Backup nichts.
  6. Auf 💾 Zeitplan speichern klicken. Es erscheint „✅ Gespeichert".
  7. Einmal testen, bevor Sie sich darauf verlassen. Erst ✉️ Test-E-Mail jetzt senden (speichert vorher und verschickt eine Probemail), dann ▶ Mini jetzt ausführen bzw. ▶ Full jetzt ausführen. Beides läuft synchron — Tab offen lassen. Der Full-Lauf zeigt Ihnen außerdem, wie lange ein echter Durchlauf dauert.
  8. Unterhalb jedes Zeitplans steht danach „Letzter Lauf: …" und „Nächster Lauf: …". Vor dem ersten Lauf steht dort „Noch nie ausgeführt."

Beim Web-Cron trägt die Angabe Nächster Lauf den Zusatz „(ungefähr — feuert beim ersten Seitenaufruf nach diesem Zeitpunkt)". Das ist der Normalfall ohne eingerichteten Server-Cron und kein Fehler.

Es gibt zwei unabhängige Zeitpläne:

Zeitplan Inhalt Standard
🗄️ Mini-Backup (nur DB) „Nur die Datenbank und Composer-Dateien. Schnell (wenige Sekunden)." deaktiviert · täglich · 03:00 · 7 Backups aufbewahren
📦 Full-Backup „Datenbank + ausgewählte Verzeichnisse. Langsamer (Minuten bis zehn Minuten)." deaktiviert · wöchentlich · sonntags · 02:00 · 4 Backups aufbewahren · vendor/ und templates/ an, files/ und assets/ aus

Als Häufigkeit stehen zwei Gruppen zur Wahl:

Gruppe Werte Logik
🧪 Testen (intervallbasiert) Alle 5 Minuten · Alle 15 Minuten · Stündlich Feuert, sobald diese Zeitspanne seit dem letzten Lauf vergangen ist — unabhängig von der Uhrzeit.
Produktion Täglich · Wöchentlich · Monatlich Feuert zur eingestellten Uhrzeit, bei wöchentlich zusätzlich am gewählten Wochentag, bei monatlich am gewählten Tag im Monat (1–28).

Das Feld Behalte letzte N Backups begrenzt die Aufbewahrung, zulässig sind 1 bis 999.

Die Aufbewahrung räumt nur denselben Zeitplan-Typ auf. Ein Mini-Zeitplan löscht ausschließlich ältere Mini-Backups, ein Full-Zeitplan nur ältere Full-Backups. Manuell erstellte Backups sowie automatische Pre-Update- und Pre-Restore-Snapshots werden davon nie erfasst und müssen bei Bedarf selbst gelöscht werden.

Unter Speicherort & Benachrichtigungen lässt sich ein eigener Speicherpfad angeben. Der Hilfetext lautet: „Absoluter Pfad zur Ablage der Backups. Leer lassen für den Standard. Vermeide vendor/, public/ und files/." Die Prüfung ist strenger als der Hinweis: Pfade innerhalb von vendor/, public/, web/ und files/ werden ebenso abgelehnt wie geschützte Systemverzeichnisse (/etc, /usr, /var/log, /boot, /root und weitere) und die zu weiten Wurzeln /, /home und /tmp.

E-Mail-Benachrichtigungen: Empfänger, optional Absender-E-Mail und Absender-Name (Standard Guardian), sowie die Schalter Bei erfolgreichem Backup benachrichtigen (Standard aus) und Bei fehlgeschlagenem Backup benachrichtigen (Standard an). ✉️ Test-E-Mail jetzt senden speichert zuerst und verschickt dann eine Probemail.

Zum Absender merkt die Oberfläche an: „Leer lassen, um Contaos System → Einstellungen → Administrator-E-Mail-Adresse zu nutzen. Nur überschreiben, wenn dein Hosting einen bestimmten Absender verlangt." Auf Plesk und cPanel verlangen viele Shared-Hoster, dass die From-Adresse eine echte Mailbox auf dem Server ist.

Wie geplante Backups ausgelöst werden

Guardian klinkt sich in Contaos eingebautes Cron-System ein. Beide Wege funktionieren nebeneinander und lassen sich jederzeit wechseln.

Weg Einrichtung Verhalten
Web-Cron (Standard) keine Contao führt Cronjobs am Ende jedes Seitenaufrufs aus, nachdem die Antwort gesendet wurde. Der Besucher wartet nicht. Aber: „Ein für 03:00 geplantes Backup startet erst beim ersten Seitenaufruf nach 03:00. Ohne nächtlichen Traffic kann es auch erst um 08:30 laufen."
Echter Cron (empfohlen) Serverseitiger Cron-Eintrag Backups laufen pünktlich, auch ohne Besucher, und teilen keine Ressourcen mit Web-Requests.

Der einzurichtende Befehl:

*/5 * * * * /usr/bin/php /pfad/zur/site/vendor/bin/contao-console contao:cron >/dev/null 2>&1

Anleitungen für Plesk, cPanel, DirectAdmin und SSH stehen ausklappbar direkt im Backup-Reiter. Zur Frequenz merkt die Oberfläche an: „Alle 5 Minuten ist völlig ok. Der Scheduler rate-limitet unser Backup-Job intern auf ‚stündlich' — häufigere Cron-Läufe verringern nur den Drift."

files/ in geplanten Backups ohne echten Cron ist riskant. Beim Web-Cron läuft das Backup während eines Seitenaufrufs im Hintergrund. Dauert es länger als ein paar Minuten und der Hoster beendet den PHP-Worker, ist das Backup unvollständig. Testen Sie einmal mit ▶ Full jetzt ausführen, um die Größe abzuschätzen, bevor Sie es planen.

Gegen Überschneidungen wirken zwei Mechanismen: Contao merkt sich den letzten Ausführungszeitpunkt jedes Cronjobs, und zusätzlich verhindert ein Dateilock (flock() auf var/updater/backup.lock), dass zwei Backups parallel laufen. Ein Lock, das älter als 30 Minuten ist, gilt als verwaist und wird entfernt.

Update-Jobs

Reiter 🔄 Update. Erfordert eine Pro-Lizenz. Die Oberfläche beschreibt es so: „Updates laufen als Background-Jobs in einem separaten PHP-Prozess — der Browser muss nicht offen bleiben. Fortschritt und Live-Log aktualisieren sich automatisch."

So führen Sie ein Update durch

Der vollständige Weg, in der Reihenfolge, in der er gedacht ist:

  1. Vorabprüfung laufen lassen. Reiter 📊 Dashboard🔍 Analyse starten. Stehen dort Fehler (❌), beheben Sie diese zuerst — insbesondere fehlende Schreibrechte oder zu wenig Speicherplatz lassen ein Update mitten im Lauf scheitern.
  2. Sehen, was überhaupt ansteht. Auf dem Dashboard 📦 Pakete laden, dann 🔄 Updates prüfen. Das Häkchen Nur Pakete mit Updates anzeigen reduziert die Liste.
  3. Ein eigenes Backup anlegen. Der Update-Job erstellt zwar selbst einen Pre-Update-Snapshot, aber ein zusätzliches vollständiges Backup mit files/ kostet wenig und deckt den Fall ab, dass etwas grundsätzlich schiefgeht. Siehe Manuelles Backup.
  4. Recovery-Panel aktivieren und testen, falls das Update riskant ist. Siehe Standalone-Recovery-Panel. Das ist der Schritt, den man im Ernstfall nicht nachholen kann.
  5. Dry-Run starten. Reiter 🔄 Update🧪 Dry-Run (sichere Simulation). Lesen Sie im Live-Log, was Composer vorhat und ob contao:migrate Schemaänderungen melden würde. Scheitert der Dry-Run, scheitert auch das echte Update.
  6. Echtes Update starten. ▶ Echtes Update… öffnet den Dialog. Dort den Update-Modus wählen, vendor/ in den Snapshot aufnehmen" angehakt lassen und — wenn eine Recovery-E-Mail konfiguriert ist — auch „📧 Recovery-URLs + Access-Token vor dem Update per E-Mail senden". Dann ▶ Update jetzt starten.
  7. Warten. Die Seite geht in den Wartungsmodus. Fortschritt und Live-Log aktualisieren sich selbst; der Browser-Tab darf zu, der Job läuft im eigenen Prozess weiter.
  8. Ergebnis prüfen. Nach „Job beendet" die Seite im Frontend und das Backend aufrufen. Bei einem Fehlschlag steht im Job-Bereich „⚠️ Update fehlgeschlagen — Rollback verfügbar"; siehe Rollback.
  9. Recovery-E-Mail löschen, falls eine verschickt wurde. Sie enthält den vollständigen Access-Token und ist damit ein Vollzugriff auf die Seite.

Es gibt drei Update-Modi:

Modus Beschriftung Verhalten
Full (Standard) „Full — alles innerhalb der composer.json-Constraints aktualisieren" „Aktualisiert alle Pakete auf die höchsten von composer.json erlaubten Versionen. Häufigste Wahl."
Konservativ „Konservativ — stabile Releases bevorzugen" „Wie Full, aber ohne Pre-Release-Versionen. Für strikt Patch-only in composer.json auf ~X.Y.Z pinnen."
Selektiv „Selektiv — einzelne Pakete auswählen" „Wähle exakt aus, welche Pakete aktualisiert werden. Abhängigkeiten werden automatisch mitgezogen."

„Konservativ" ist kein Patch-only-Modus. Technisch entspricht er composer update --prefer-stable innerhalb der bestehenden Constraints. Wer wirklich nur Patch-Versionen zulassen will, muss die Constraints in composer.json selbst auf ~X.Y.Z setzen.

Jeder echte Update-Job durchläuft sechs Schritte in dieser Reihenfolge:

backup → maintenance_on → composer → cache_clear → migrate → maintenance_off

Also: Pre-Update-Snapshot, Wartungsmodus an, composer update, Cache leeren, contao:migrate, Wartungsmodus aus.

Dry-Run

Die Schaltfläche 🧪 Dry-Run (sichere Simulation) führt die Schritte backup → composer → cache_clear → migrate aus, wobei Composer und contao:migrate mit --dry-run laufen. Der Bestätigungsdialog: „Das simuliert ein Update — composer läuft mit --dry-run, contao:migrate ebenso. Ein ECHTES Backup wird trotzdem angelegt (Sicherheitsnetz). Sonst wird nichts verändert." Der Wartungsmodus wird dabei nicht aktiviert.

Der Dialog vor dem echten Update

▶ Echtes Update… öffnet einen Dialog mit dem Hinweis: „Dies verändert deine Live-Seite. Zuvor wird ein Pre-Update-Snapshot erstellt, damit du zurückrollen kannst." Dort werden zwei Optionen gesetzt:

Option Hilfetext Standard
vendor/ in den Snapshot aufnehmen (empfohlen)" „Erlaubt einen vollständigen Rollback. Ohne dies umfasst der Rollback nur Composer-Dateien + DB, du müsstest composer install manuell nachziehen." empfohlen
„📧 Recovery-URLs + Access-Token vor dem Update per E-Mail senden" „Falls etwas schiefgeht, ist diese Mail deine Rettungsleine. … Lösche die E-Mail nach erfolgreichem Update — sie enthält deinen vollständigen Access-Token."

Schlägt der Versand der Recovery-E-Mail fehl, wird das Update gar nicht erst gestartet. Die Meldung lautet: „Recovery-E-Mail konnte nicht gesendet werden: … Deaktiviere die E-Mail-Option oder korrigiere die Mail-Konfiguration, bevor du das Update startest." Das ist Absicht — ohne die Rettungsleine soll kein Update laufen.

Hängende Jobs

Es kann immer nur ein Job gleichzeitig aktiv sein. Steht ein alter Job im Weg, meldet die Oberfläche: „Ein anderer Job steht im Weg:" und verweist auf die beiden Aufräum-Schaltflächen. Als stale gilt ein Job, wenn:

  • er länger als 2 Minuten im Zustand queued steht — der Worker wurde nie gestartet;
  • er running ist, aber der vermerkte Worker-Prozess nicht mehr existiert;
  • er running ist, keine Prozess-ID hat und die Job-Datei seit 30 Minuten nicht mehr angefasst wurde.
Schaltfläche Wirkung
🗑 Stale-Job aufräumen „Das bricht den vorherigen Job ab (der offenbar gecrasht ist oder nie startete), damit du einen neuen starten kannst. Es macht KEINE bereits erledigte Arbeit rückgängig — es gibt nur den Queue-Slot frei."
⛔ Abbruch erzwingen „Nur nutzen, wenn du sicher weißt, dass der Worker wirklich hängt. Teilweise erledigte Arbeit wird NICHT zurückgenommen." Der zugrunde liegende Prozess wird dadurch nicht zwingend beendet.

Rollback nach fehlgeschlagenem Update

Scheitert ein echtes Update, erscheint im Job-Bereich: „⚠️ Update fehlgeschlagen — Rollback verfügbar", mit der Schaltfläche ↩️ Automatischer Rollback auf Pre-Snapshot.

So rollen Sie zurück

  1. Im Reiter 🔄 Update auf ↩️ Automatischer Rollback auf Pre-Snapshot klicken.
  2. Den Bestätigungsdialog lesen und bestätigen: „Composer-Dateien, Datenbank und (falls enthalten) das vendor/-Verzeichnis werden auf den Stand vor dem fehlgeschlagenen Update zurückgesetzt. Die Seite geht während des Rollbacks in den Wartungsmodus."
  3. Der Rollback läuft als eigener Job. Im Live-Log erscheint „Rollback gestartet. Verfolge den Live-Log unten."
  4. Nach Abschluss den Wartungsmodus prüfen und die Seite im Frontend aufrufen.

Dieser Weg ist an einen bestimmten fehlgeschlagenen Job gebunden: Guardian schlägt dessen Pre-Update-Snapshot im Job-Archiv nach und stellt ihn wieder her. Eine Auswahl, welche Komponenten zurückgesetzt werden, gibt es hier bewusst nicht — der Rollback stellt alle im Snapshot enthaltenen Komponenten wieder her (Composer-Dateien, Datenbank, vendor/, templates/, files/, assets/) und schaltet dabei immer den Wartungsmodus ein.

Der Restore ist best-effort, nicht transaktional. Die Komponenten werden nacheinander wiederhergestellt. Bricht ein Schritt ab, wird kein bereits abgeschlossener Schritt automatisch zurückgenommen. Der Rollback selbst ist zudem ein bewusster manueller Klick, kein automatischer Vorgang.

Existiert kein Snapshot zu dem Job, meldet die API: „Kein Pre-Update-Snapshot zu diesem Job vorhanden. Manueller Restore erforderlich."

Für den Fall, dass der Button nicht mehr erreichbar ist, verweist die Oberfläche selbst weiter: „Wenn dieser Button nicht funktioniert (z. B. weil das fehlgeschlagene Update Contao selbst zerlegt hat), nutze das Standalone-Recovery-Panel aus dem Recovery-Tab — es funktioniert ohne Contao oder Symfony."

Aus einem Backup wiederherstellen

Das Contao-Backend bietet keinen Weg, ein beliebiges Backup zurückzuspielen. Die einzige Wiederherstellung im Backend ist der Rollback auf den Pre-Update-Snapshot eines fehlgeschlagenen Jobs. Wollen Sie ein anderes Backup einspielen — etwa das nächtliche Mini-Backup von vorgestern —, führt der Weg ausschließlich über das Standalone-Recovery-Panel.

Das ist Absicht und wird im Recovery-Reiter begründet: „Restore ist eine Out-of-Band-Operation — bewusst wird sie nicht aus diesem Contao-Backend heraus ausgelöst." Zum einen braucht man einen Restore meistens genau dann, wenn Contao nicht mehr läuft. Zum anderen ist es gefährlich, vendor/ zurückzuspielen, während Symfony aus demselben Verzeichnis liest — das Backend würde mitten im Vorgang abstürzen.

Daraus folgt eine Konsequenz, die man vor dem Ernstfall kennen sollte:

Ohne Pro-Lizenz und ohne aktiviertes Recovery-Panel gibt es keinen Weg, ein Backup über Guardian zurückzuspielen. Mit einer Free-Lizenz können Sie Backups erstellen, aber nicht einspielen. Die Archive unter var/updater/backup/<Zeitstempel>/ sind reguläre tar-/gzip-Dateien plus ein SQL-Dump und lassen sich selbstverständlich von Hand über SSH entpacken und importieren — komfortabel ist das nicht.

Der Ablauf im Überblick

Ausgangslage Weg
Update ist gerade fehlgeschlagen, Backend läuft noch Rollback-Schaltfläche im Update-Reiter — ein Klick, stellt den Pre-Update-Snapshot vollständig wieder her.
Contao bootet nicht mehr Standalone-Recovery-Panel im Browser öffnen. Setzt voraus, dass es vorher aktiviert wurde.
Backend läuft, Sie wollen ein älteres Backup einspielen Ebenfalls über das Standalone-Recovery-Panel — es ist auch bei intaktem Contao erreichbar und der einzige Weg mit Komponentenauswahl.
Panel wurde nie aktiviert und Contao ist kaputt Kein Guardian-Weg mehr. Es bleibt die manuelle Wiederherstellung über SSH oder das Backup des Hosters.

Standalone-Recovery-Panel

Reiter 🛟 Recovery. Erfordert eine Pro-Lizenz.

Das Panel ist eine einzelne PHP-Datei ohne Framework-Abhängigkeiten, die der Webserver direkt ausliefert. Sie kann Backups auflisten, Komponenten selektiv wiederherstellen — inklusive Datenbank-Import — und den Wartungsmodus steuern.

Die Begründung, warum Restore bewusst nicht aus dem Contao-Backend heraus läuft, steht im Reiter selbst: „Wenn Contao läuft, brauchst du meistens keinen Restore. Wenn du einen brauchst, ist Contao wahrscheinlich kaputt." Und: vendor/ wiederherzustellen, während Symfony aus demselben Verzeichnis liest, ist gefährlich — das Backend würde mitten im Restore abstürzen."

Auslieferung aktivieren

Die Auslieferung ist opt-in. In .env.local:

VTINNOVATIONS_GUARDIAN_DEPLOY_RECOVERY_PANEL=1

Danach Cache leeren. Beim nächsten Kernel-Boot kopiert das Bundle die Datei nach public/. Akzeptierte Werte für das Flag sind 1, true, yes und on.

Zwei Bedingungen müssen gemeinsam erfüllt sein: das Flag und eine gültige Pro-Berechtigung. Fällt eine davon weg, entfernt das Bundle die Datei beim nächsten Boot selbsttätig wieder aus dem Webroot — das Abschalten beseitigt die Angriffsfläche also tatsächlich, statt eine verwaiste Datei liegen zu lassen. Die Berechtigungsprüfung läuft dabei unabhängig von den Controllern direkt beim Boot.

Empfehlung des Bundles: Panel nur für die Dauer riskanter Updates aktivieren und zusätzlich auf Webserver-Ebene schützen (IP-Allowlist oder HTTP-Auth). Der Token ist die letzte Verteidigungslinie, nicht die einzige. Testen Sie den Zugriff vor einem Update — im Ernstfall lässt sich das nicht nachholen.

Dateiname

Standard ist _updater-recovery.php. Unter 🛟 Recovery-Panel-Dateiname lässt sich ein eigener Name setzen: „Ein eigener Dateiname erschwert das Auffinden durch Scanner (Security through Obscurity zusätzlich zur Token-Authentifizierung). Muss auf .php enden, nur Buchstaben/Zahlen/._-, max. 60 Zeichen." Beim Umbenennen wird die vorherige Datei beim nächsten Boot entfernt.

Access-Token

Das Panel nutzt HTTP Basic Auth: „Der Benutzername ist beliebig; das Passwort ist der hier verwaltete Access-Token." Alternativ wird ein Authorization: Bearer-Header akzeptiert. Ein Token im URL-Query-String wird bewusst nicht akzeptiert — er würde in Server-Logs und Referer-Headern landen.

Zwei Token-Quellen, in dieser Reihenfolge:

  1. VTINNOVATIONS_GUARDIAN_TOKEN in .env.local — hat Vorrang.
  2. Eine automatisch erzeugte Datei var/updater/access.token.

Stammt der Token aus der Umgebung, zeigt die Oberfläche das Abzeichen „aus .env", sonst „auto-generiert". Bei einem Token aus .env ist die Rotation im Backend gesperrt: „Der Token stammt aus .env. Bearbeite VTINNOVATIONS_GUARDIAN_TOKEN in .env.local, um ihn zu rotieren."

Der Token wird nur einmal vollständig angezeigt. Im Normalfall zeigt das Backend eine maskierte Vorschau. Um den vollständigen Token zu erhalten, klicken Sie auf 🔄 Token rotieren, um eine neue Kopie zu erhalten — der alte Token wird dabei sofort ungültig, der neue genau einmal angezeigt. Speichern Sie URL und Token an diesem Punkt außerhalb von Contao: „Wenn Contao ausfällt, kannst du sie von dieser Seite nicht mehr kopieren."

So stellen Sie damit wieder her

  1. Panel öffnen. https://ihre-domain.de/_updater-recovery.php im Browser aufrufen — bzw. den selbst gesetzten Dateinamen.
  2. Anmelden. Der Browser zeigt einen Basic-Auth-Dialog. Tragen Sie einen beliebigen Benutzernamen ein und als Passwort den Access-Token.
  3. Lage prüfen. Unter System diagnostics zeigt das Panel, was es auf dem Server vorfindet — etwa ob mysql und tar verfügbar sind. Unter Available backups stehen alle Backups mit ihrem Manifest.
  4. Backup wählen. Im Abschnitt Restore from backup das gewünschte Backup auswählen.
  5. Komponenten ankreuzen. Wählbar sind sechs: composer, database, vendor, templates, files und assets. Anders als beim Rollback im Backend entscheiden Sie hier selbst, was zurückgespielt wird.
  6. Wartungsmodus. Er ist standardmäßig eingeschaltet und sollte es bleiben, sobald vendor/ oder die Datenbank betroffen sind. Besucher sehen währenddessen die Seite „Site is being restored".
  7. Wiederherstellung starten und im Live log mitlesen. Das Panel hebt Zeit- und Speicherlimit selbst an und protokolliert jeden Schritt.
  8. Nachkontrolle. Frontend und Backend aufrufen. Wurde vendor/ zurückgespielt, anschließend den Cache leeren.

Die Oberfläche des Panels ist englisch — es ist bewusst eine abhängigkeitsfreie Einzeldatei und bindet Contaos Übersetzungen nicht ein. Die Abschnitte heißen System diagnostics, Available backups, Restore from backup und Live log.

Neben der Wiederherstellung kann das Panel Backups auflisten, deren Manifest anzeigen, ein Backup löschen und den Wartungsmodus separat schalten.

Ein Brute-Force-Schutz sperrt nach 8 Fehlversuchen je IP-Adresse innerhalb von 15 Minuten für 15 Minuten. Hinter einem gemeinsamen Proxy oder CDN mit fester Absender-IP teilen sich alle Clients dasselbe Kontingent. Vor dem Entpacken prüft das Panel jeden Archiveintrag — keine absoluten Pfade, kein .., kein Verlassen des Zielverzeichnisses.

Eine Einschränkung: Die Komponente templates umfasst im Panel immer templates/ und contao/templates/ zusammen — beide lassen sich hier nicht getrennt wiederherstellen.

Lizenzzustände

Guardian kennt drei Stufen — Trial, Free und Pro — und jede davon erfordert einen aktivierten, signierten Schlüssel. Es gibt keinen anonymen Free-Modus und keine Testphase, die sich lokal starten ließe.

Funktion Ohne Lizenz Free Pro / Trial
Dashboard und Einstellungen
Vorabprüfung und Paketübersicht
Manuelles Backup
Update-Jobs (Composer)
Restore / Recovery
Geplante Backups (Mini + Full)
Standalone-Recovery-Panel
Recovery-E-Mail-Benachrichtigungen

Trial und Pro sind hinsichtlich der freigeschalteten Funktionen identisch; der Unterschied liegt allein in der Befristung des signierten Datensatzes.

Die Meldungen, die das Lizenz-Panel je nach Zustand anzeigt:

Zustand Meldung
Pro aktiv „Pro-Lizenz aktiv. Alle Funktionen freigeschaltet."
Trial aktiv „Trial-Lizenz aktiv. Alle Funktionen freigeschaltet, bis die Testphase endet."
Free aktiv „Free-Lizenz aktiv. Nur manuelles Backup."
Pro abgelaufen, Fallback erlaubt „Pro-Lizenz abgelaufen. Läuft im Free-Funktionsumfang (nur manuelles Backup)."
Abgelaufen, kein Fallback „Lizenz abgelaufen. Alle lizenzierten Funktionen sind deaktiviert."
Noch nicht gültig „Lizenz ist noch nicht gültig. Alle lizenzierten Funktionen sind deaktiviert."
Domain passt nicht „Lizenz ist für keine der auf dieser Installation konfigurierten Domains gültig."
Vom Aussteller zurückgezogen „Lizenz ist nicht mehr gültig. Klicke auf „Lizenz aktualisieren", oder kontaktiere V&T Innovations."
Online-Prüffrist überschritten „Lizenz muss online neu geprüft werden und war nicht rechtzeitig erreichbar. Klicke auf „Lizenz aktualisieren", sobald wieder eine Verbindung besteht."
Keine Lizenz „Keine Lizenz aktiviert. Nur Dashboard und Einstellungen sind verfügbar."
sodium fehlt „Guardian kann auf diesem Server keine Lizenzen prüfen: die PHP-Sodium-Erweiterung fehlt."

Die Lizenz wird exakt an Hostnamen gebunden — kein Wildcard, kein Suffix-Matching, keine automatische Gleichsetzung von www-Variante und Apex-Domain. Der signierte Datensatz trägt eine Online-Prüffrist; läuft sie ab und bleibt der Server unerreichbar, greift zunächst ein signiertes Kulanzfenster und danach fallen die geschützten Funktionen aus (fail closed). Ein stündlicher Cronjob versucht die Auffrischung rechtzeitig — er beginnt sechs Stunden vor der Frist und wiederholt es frühestens alle 30 Minuten.

Teil 3 — Für Entwickler

Konsolenbefehl

Das Bundle registriert genau einen Befehl:

vendor/bin/contao-console guardian:run-job <job-id>
Eigenschaft Wert
Name guardian:run-job
Beschreibung „Executes a queued update job (CLI worker, internal use)"
Argument job-id (erforderlich) — ID des auszuführenden Jobs
Optionen keine

Der Befehl ist der Worker, den das Backend als eigenständigen Prozess startet. Er lässt sich zu Diagnosezwecken auch manuell aufrufen, erwartet dann aber genau die ID des aktuell in var/updater/job.json hinterlegten Jobs — andernfalls bricht er mit „Job ID mismatch" ab. Er hebt sein eigenes Zeitlimit auf, setzt das Speicherlimit auf 512 MB und prüft die Lizenzberechtigung eigenständig noch einmal: ein Restore-Job verlangt die Restore-Berechtigung, jeder andere die Update-Berechtigung. Fehlt sie, endet er mit „This operation requires a valid Guardian licence."

Routen

Alle Backend-Routen tragen das Präfix %contao.backend.route_prefix%/updater (standardmäßig /contao/updater), laufen im Scope backend und verlangen bis auf die Einstiegsseite POST. Jede Aktion prüft ROLE_ADMIN serverseitig.

Pfad (nach dem Präfix) Routenname Methode
/updater…\Controller\BackendControllerGET
/updater/analysevtinnovations_guardian_analysePOST
/updater/packagesvtinnovations_guardian_packagesPOST
/updater/backup/createvtinnovations_guardian_backup_createPOST
/updater/backup/listvtinnovations_guardian_backup_listPOST
/updater/backup/deletevtinnovations_guardian_backup_deletePOST
/updater/job/startvtinnovations_guardian_job_startPOST
/updater/job/statusvtinnovations_guardian_job_statusPOST
/updater/job/logvtinnovations_guardian_job_logPOST
/updater/job/archivevtinnovations_guardian_job_archivePOST
/updater/job/rollbackvtinnovations_guardian_job_rollbackPOST
/updater/job/clear-stalevtinnovations_guardian_job_clear_stalePOST
/updater/schedule/getvtinnovations_guardian_schedule_getPOST
/updater/schedule/savevtinnovations_guardian_schedule_savePOST
/updater/schedule/runvtinnovations_guardian_schedule_runPOST
/updater/schedule/test-emailvtinnovations_guardian_schedule_test_emailPOST
/updater/runtime/getvtinnovations_guardian_runtime_getPOST
/updater/runtime/savevtinnovations_guardian_runtime_savePOST
/updater/runtime/testvtinnovations_guardian_runtime_testPOST
/updater/runtime/test-recovery-emailvtinnovations_guardian_runtime_test_recovery_emailPOST
/updater/panel/getvtinnovations_guardian_panel_getPOST
/updater/panel/rotatevtinnovations_guardian_panel_rotatePOST

Eine Route liegt bewusst außerhalb des Backends:

Pfad Routenname Zweck
/rest/api/v1/guardian-license-updater vtinnovations_guardian_registry_hook Server-zu-Server-Zustellung neuer Lizenzpakete. Nicht durch den Backend-Login geschützt, sondern kryptografisch authentifiziert: signiert werden Methode, Pfad, Request-ID, Zeitstempel, Nonce und Body-Hash. Wiedereinspielungen wehrt ein Replay-Ledger unter var/updater/exchange.journal ab.

Schreibende Backend-Requests unterliegen zusätzlich einem Same-Origin-CSRF-Check (Origin, mit Referer-Fallback). Die Updater-Route ist davon ausgenommen, da sie signaturbasiert authentifiziert wird.

Dateien unter var/updater/

Guardian legt keine eigenen Datenbanktabellen an. Der gesamte Zustand liegt im Dateisystem:

Pfad Inhalt
backup/<Zeitstempel>/Backup-Archive und manifest.json
backup.lockflock()-Sperre gegen parallele Backups
job.jsonDer eine aktive Job
job.logLive-Log des aktiven Jobs
jobs/Archiv abgeschlossener Jobs
status.jsonZustand der letzten Operation (Dashboard)
outdated.jsonGecachtes Ergebnis der Packagist-Abfrage (24 h)
runtime.jsonPHP-CLI-Pfad, Composer-Phar, Recovery-E-Mail, Panel-Dateiname
schedule.jsonKonfiguration der geplanten Backups
schedule_state.jsonLetzter Lauf je Zeitplan-Typ
access.tokenToken des Recovery-Panels (nur wenn nicht über .env gesetzt)
registration.json / .seal / .scopeLizenzdatensatz, Integritäts-Envelope, gebundene Domain
registration.tomb / .tomb.sealSignierter Grabstein: höchste akzeptierte negative Version
lease.attemptZeitstempel des letzten Auffrischungsversuchs
exchange.journalReplay-Ledger für server-initiierte Lizenzupdates

Das Zurückspielen einer alten registration.json aus einem Backup hebt einen Widerruf nicht auf. Ein signierter negativer Zustand wird als selbst-authentifizierender Grabstein festgehalten; die höchste jemals akzeptierte Version überlebt jede Dateiwiederherstellung. Jede Veränderung an registration.json, .seal oder .scope führt beim nächsten Lesen zu „unlizenziert" — es gibt keinen Lesepfad an der Signaturprüfung vorbei.

Cronjobs

Zwei Cronjobs registrieren sich über Contaos AsCronJob-Attribut:

Klasse Intervall Aufgabe
Cron\BackupCron minutely Prüft, ob ein geplantes Backup fällig ist, und führt es gegebenenfalls aus. Das Minutenintervall erlaubt die Test-Frequenzen (5/15 Minuten); die Fälligkeitsprüfung selbst ist praktisch kostenlos.
Cron\LeaseRefreshCron hourly Frischt den signierten Lizenzzustand auf, sobald die Online-Prüffrist näher rückt. Beginnt 6 Stunden vor der Frist, wiederholt frühestens alle 30 Minuten. Ein Netzwerkfehler verändert nichts.

Im Web-Scope führt Contao beide in kernel.terminate aus, also nachdem die Antwort gesendet wurde. BackupCron hebt dafür Zeit- und Speicherlimit an, setzt ignore_user_abort(true) und leert die Ausgabepuffer.

Umgebungsvariablen

Variable Wirkung
VTINNOVATIONS_GUARDIAN_DEPLOY_RECOVERY_PANEL Schaltet die Auslieferung des Standalone-Recovery-Panels frei. Akzeptiert 1, true, yes, on. Ohne sie wird eine vorhandene Panel-Datei beim nächsten Boot entfernt.
VTINNOVATIONS_GUARDIAN_TOKEN Fixiert den Access-Token des Recovery-Panels. Hat Vorrang vor var/updater/access.token; die Rotation im Backend ist dann gesperrt.
VTINNOVATIONS_GUARDIAN_DOMAINS Komma-getrennte Liste zusätzlicher Domains für die Lizenzbindung. Gedacht für Installationen, deren Website-Startseiten kein DNS-Feld gesetzt haben.
PHP_CLI_BINARY Absoluter Pfad zur PHP-CLI-Binary. Greift, wenn im Backend nichts eingetragen ist, und geht der Auto-Erkennung vor.

Achtung, abweichender Variablenname in einer Fehlermeldung. Schlägt der Start des Workers fehl, nennt die Meldung VTINNOVATIONS_GUARDIAN_PHP_BINARY. Diese Variable wird vom Code nicht gelesen. Die wirksame Variable heißt PHP_CLI_BINARY; der bevorzugte Weg bleibt ohnehin das Feld PHP-Binary unter PHP-CLI-Einstellungen.

Protokollierung

Wichtige Ereignisse aus Updates und geplanten Backups schreibt Guardian zusätzlich in Contaos Systemlog. Zu finden unter System → Systemlog, filterbar über die Aktion VTINNOVATIONS_GUARDIAN. Die Oberfläche begründet es so: „So kannst du auch nachträglich nachvollziehen, was passiert ist, wenn das Live-Log hier weg ist."

Zu unterscheiden sind zwei Protokolle:

Protokoll Umfang Verwendung
Live-Log (var/updater/job.log) Jede Ausgabezeile jedes Schritts Die laufende Anzeige im Backend während eines Jobs
Systemlog (tl_log) Zusammenfassung der wichtigen Ereignisse Nachträgliche Fehlersuche über Contaos reguläre Oberfläche

Lizenzschlüssel, Payloads, Digests, Signaturen und Nonces werden nie protokolliert und erscheinen nicht in Browser-Antworten. Das Paket sichert das über eine eigene Testsuite strukturell ab.

Keine Erweiterungspunkte

Guardian ist bewusst geschlossen gebaut. Folgendes existiert nicht und sollte nicht erwartet werden:

  • Keine eigenen Hooks oder Events. Das Bundle hört auf Contaos getSystemMessages-Hook und auf die Kernel-Events für Backend-Menü, CSRF-Prüfung und Nutzungssignal — es sendet aber keine eigenen Events, in die sich andere Pakete einklinken könnten.
  • Keine Bundle-Konfiguration. Die DI-Extension lädt ausschließlich die eigene services.yaml; es gibt keinen guardian:-Abschnitt in config.yaml. Alles Konfigurierbare liegt im Backend bzw. in var/updater/runtime.json.
  • Keine Datenbanktabellen und keine Models. Der gesamte Zustand liegt unter var/updater/.
  • Keine eigene Route für die Lizenzverwaltung. Das Panel rendert innerhalb von Contaos eigenem tl_settings-Formular; die Schaltflächen tragen bewusst kein formaction.
  • Kein Frontend-Modul und kein Content-Element. Guardian ist reines Backend-Werkzeug.
  • Der Major-Upgrade-Modus ist deaktiviert. Der Code für die Pipeline ist im Paket vorhanden, aber jede Anfrage dafür wird abgelehnt: „Der Major-Upgrade-Modus ist in dieser Version deaktiviert." Weder Oberfläche noch Route bieten ihn an.

Zu umgehen sind die Lizenz-Gates ebenfalls nicht durch das Ausschalten der Oberfläche: Sie werden serverseitig an jeder Funktionsgrenze einzeln durchgesetzt — im Controller, im CLI-Worker, im Cron-Runner, beim Mailversand und beim Panel-Deployment im Bundle-Boot.

Fehlerbehebung

Symptom Ursache und Prüfung
Menüpunkt Guardian erscheint nicht unter „Inhalte" Sie sind nicht als Administrator angemeldet, oder das Bundle ist nicht geladen. Prüfen mit vendor/bin/contao-console list guardian — erscheint guardian:run-job nicht, Cache leeren und composer.lock prüfen.
„❌ Worker konnte nicht gestartet werden" Die PHP-CLI-Binary wurde nicht gefunden oder ist nicht ausführbar. Der Hinweis der Oberfläche: „Öffne unten den Bereich ‚PHP-CLI-Einstellungen' und trage den korrekten Pfad zur PHP-CLI-Binary ein (z. B. /opt/plesk/php/8.4/bin/php bei Plesk), dann erneut versuchen." Siehe PHP-CLI-Pfad konfigurieren.
„This appears to be an FPM/CGI binary, not CLI." Der eingetragene Pfad zeigt auf die Web-Variante. Dieselbe Version liegt meist unter /bin/ statt /sbin/, ohne -fpm-Suffix.
„Cannot test: exec() is in disable_functions." Der Hoster hat exec() gesperrt. Der Test der Binary ist dann nicht möglich; der Worker-Start ebenfalls nicht. Hier hilft nur der Hoster.
Lizenz lässt sich nicht aktivieren: „Für diese Installation ist keine Domain konfiguriert." Keine Website-Startseite im Seitenbaum hat ein dns-Feld gesetzt. Domain dort eintragen oder VTINNOVATIONS_GUARDIAN_DOMAINS in .env.local setzen.
„Lizenz ist für keine der auf dieser Installation konfigurierten Domains gültig." Schreibweise prüfen. www.beispiel.de und beispiel.de sind zwei verschiedene Hosts; es gibt kein Wildcard- oder Suffix-Matching.
„Guardian kann auf diesem Server keine Lizenzen prüfen: die PHP-Sodium-Erweiterung fehlt." ext-sodium ist nicht installiert. Ohne sie bleibt die Installation unlizenziert — das ist keine Einstellung, sondern eine harte Voraussetzung.
„Guardian hat einen Lizenzschlüssel aus einer früheren Version gefunden…" Ein Schlüssel aus einer Version vor den signierten Datensätzen. Auf Lizenz aktualisieren klicken, um ihn neu zu authentifizieren.
„Der Lizenzserver war nicht erreichbar." Netzwerk oder Firewall. Es wurde nichts geändert, eine bestehende Lizenz bleibt aktiv. Später erneut versuchen.
Datenbank fehlt im Backup / „DATABASE_URL nicht in .env / .env.local gefunden" Ohne DATABASE_URL wird nur der Datenbankteil übersprungen; das übrige Backup läuft durch. Die Vorabprüfung meldet es als Warnung.
Geplantes Backup läuft nicht zur eingestellten Zeit Beim Web-Cron feuert es erst beim ersten Seitenaufruf nach dem Zeitpunkt. Ohne nächtlichen Traffic verschiebt sich das. Abhilfe: echter Server-Cron auf contao:cron, siehe Geplante Backups.
Geplantes Backup mit files/ bleibt unvollständig Beim Web-Cron beendet der Hoster den PHP-Worker, bevor das Archiv fertig ist. Erst mit ▶ Full jetzt ausführen die Dauer messen, dann echten Cron einrichten.
Speicherpfad wird abgelehnt „Speicherpfad ist ungültig: …" — der Pfad ist nicht absolut, liegt in einem geschützten Systemverzeichnis, innerhalb von vendor/, public/, web/ oder files/, oder er ist nicht beschreibbar.
„Ein anderer Job steht im Weg:" Ein vorheriger Job ist noch aktiv oder hängt. Erst 🗑 Stale-Job aufräumen versuchen; ⛔ Abbruch erzwingen nur, wenn sicher ist, dass der Worker nicht mehr reagiert.
Update startet nicht, „❌ Recovery-E-Mail konnte nicht gesendet werden" Absichtlich. Entweder die Mail-Konfiguration unter Einstellungen → Recovery-E-Mail korrigieren, oder das Häkchen „Recovery-URLs per E-Mail senden" im Update-Dialog für diesen Lauf entfernen.
„Symfony Mailer ist nicht verfügbar." MAILER_DSN ist in .env.local nicht gesetzt. Ohne sie funktionieren weder Recovery- noch Backup-Benachrichtigungen.
Test-Mail schlägt fehl, obwohl Contao sonst Mails versendet Viele Shared-Hoster verlangen, dass die Absenderadresse eine echte Mailbox auf dem Server ist. Absender auf eine in Plesk/cPanel angelegte Adresse setzen.
Es gibt keine Schaltfläche, um ein vorhandenes Backup einzuspielen Richtig — das Backend bietet nur den Rollback auf den Snapshot eines fehlgeschlagenen Update-Jobs. Jede andere Wiederherstellung läuft über das Standalone-Recovery-Panel. Siehe Aus einem Backup wiederherstellen.
„Unbekannter Job-Typ: restore" Ein Restore lässt sich nicht über den regulären Job-Start auslösen; die Backend-API akzeptiert dort nur dry_run und update. Nutzen Sie die Rollback-Schaltfläche oder das Recovery-Panel.
Backup ist da, aber ohne Pro-Lizenz nicht einspielbar Wiederherstellung und Recovery-Panel sind Pro-Funktionen. Free deckt nur das Erstellen von Backups ab. Die Archive selbst sind reguläre tar-/gzip-Dateien plus SQL-Dump und lassen sich über SSH auch von Hand einspielen.
Standalone-Recovery-Panel liefert 404 Die Datei wurde nicht ausgeliefert. Drei Bedingungen prüfen: VTINNOVATIONS_GUARDIAN_DEPLOY_RECOVERY_PANEL=1 gesetzt, gültige Pro-Lizenz vorhanden, und danach der Cache geleert — die Datei entsteht erst beim nächsten Kernel-Boot.
Panel fragt nicht nach Zugangsdaten oder weist den Token ab Der Token gehört als Passwort in den Basic-Auth-Dialog, der Benutzername ist beliebig. Ein Token im Query-String wird bewusst nicht akzeptiert. Nach 8 Fehlversuchen je IP innerhalb von 15 Minuten greift eine 15-minütige Sperre.
Der angezeigte Token funktioniert nicht Angezeigt wird nur eine maskierte Vorschau. Den vollständigen Token gibt es ausschließlich einmalig nach Token rotieren — dabei wird der alte sofort ungültig.
Paketübersicht zeigt veraltete Zahlen Die Packagist-Abfrage wird 24 Stunden gecacht. 🔄 Updates prüfen erzwingt eine frische Abfrage.
Angezeigtes Update lässt sich nicht installieren, Markierung ⚠ blockiert Die neuere Version existiert, ist aber durch Constraints anderer Pakete gesperrt. Typischerweise müssen mehrere Pakete gemeinsam aktualisiert werden; bei Contao zieht meist ein Update von contao/manager-bundle alles nach.

Bekannte Einschränkungen

  • Restore und Rollback sind best-effort, nicht transaktional. Komponenten werden nacheinander wiederhergestellt; bricht ein Schritt ab, wird kein bereits abgeschlossener Schritt automatisch zurückgenommen.
  • Der Rollback nach einem fehlgeschlagenen Update ist ein manueller Klick, kein automatischer Vorgang.
  • „Konservativ" ist kein echter Patch-only-Modus — technisch composer update --prefer-stable innerhalb der bestehenden Constraints.
  • Der Wartungsmodus wird beim Restore nur dann automatisch aktiviert, wenn vendor/ zu den wiederherzustellenden Komponenten gehört.
  • Die Aufbewahrung greift nur je Zeitplan-Typ. Manuelle Backups und Pre-Update-/Pre-Restore-Snapshots werden nie automatisch gelöscht.
  • „Abbruch erzwingen" beendet den Hintergrundprozess nicht zwingend — es markiert den Job als abgebrochen und gibt den Queue-Slot frei.
  • Im Contao-Backend lässt sich kein beliebiges Backup zurückspielen. Dort gibt es nur den Rollback auf den Pre-Update-Snapshot eines fehlgeschlagenen Jobs — ohne Komponentenauswahl, immer vollständig. Jede andere Wiederherstellung läuft über das Standalone-Recovery-Panel, das dafür vorher aktiviert worden sein muss.
  • Das Standalone-Panel kann contao/templates/ nicht getrennt von templates/ wiederherstellen — die Komponente templates umfasst dort immer beide Verzeichnisse.
  • Das manuelle Backup läuft synchron im Browser-Request, nicht als Hintergrundjob. Bei großen files/-Verzeichnissen kann es das PHP-Zeitlimit reißen.
  • Mehrknoten-Betrieb ohne gemeinsames var/ wird nicht unterstützt. Lizenzzustand, Job-Ablage und Replay-Ledger liegen im Dateisystem und setzen einen gemeinsamen, transaktionalen Speicher voraus.
  • Der Major-Upgrade-Modus ist in dieser Version deaktiviert. Sprünge über Major-Versionen hinweg — etwa Contao 5.3 auf 5.7 — müssen außerhalb von Guardian durchgeführt werden.
  • Eine Lizenz gilt genau für die signierten Hostnamen. Umzug auf eine neue Domain erfordert eine Aktualisierung durch V&T Innovations.

Deinstallation

  1. Lizenz entfernen unter Contao → Einstellungen → Guardian Licence managementLizenz entfernen. Das gibt die Bindung an diese Installation frei, bevor das Paket verschwindet.
  2. Auslieferung des Recovery-Panels abschalten: die Zeile VTINNOVATIONS_GUARDIAN_DEPLOY_RECOVERY_PANEL=1 aus .env.local entfernen und den Cache leeren. Beim nächsten Boot entfernt das Bundle die Datei aus public/ selbsttätig. Führen Sie diesen Schritt vor dem Entfernen des Pakets aus — danach räumt niemand mehr auf und die Datei bliebe im Webroot liegen.
  3. Serverseitigen Cron-Eintrag entfernen, falls einer nur für Guardian eingerichtet wurde. Nutzen andere Erweiterungen contao:cron, lassen Sie ihn stehen.
  4. Paket entfernen — im Contao Manager unter Pakete bei vtinnovations/guardian, oder über Composer:
    composer remove vtinnovations/guardian
    vendor/bin/contao-console cache:clear
  5. Arbeitsdaten prüfen. Das Verzeichnis var/updater/ bleibt erhalten. Es enthält Ihre Backups. Löschen Sie es erst, wenn Sie die darin liegenden Sicherungen nicht mehr benötigen oder an einen anderen Ort kopiert haben.

Prüfen Sie nach der Deinstallation, ob public/_updater-recovery.php — oder Ihr eigener Dateiname — wirklich verschwunden ist. Wurde das Paket entfernt, ohne vorher das Flag abzuschalten und den Cache zu leeren, bleibt die Datei liegen und ist weiterhin über den Webserver erreichbar. In dem Fall von Hand löschen.

Weitere Spuren hinterlässt Guardian nicht: Es gibt keine eigenen Datenbanktabellen. Die Einträge im Contao-Systemlog mit der Aktion VTINNOVATIONS_GUARDIAN bleiben als Historie bestehen und lassen sich über Contaos reguläre Log-Verwaltung entfernen.