Backup und Disaster Recovery im GLPI: der umfassende Leitfaden

Produktionsfahrplan für Backup und Disaster Recovery im GLPI: konsistenter Dump, die glpicrypt.key, die fast alle vergessen, Rotation, geprobter Restore-Test und Entscheidungsmatrix für RPO/RTO.

In diesem Artikel6 Abschnitte

Ein Backup, das nie wiederhergestellt wurde, ist Hoffnung, keine Strategie – und im GLPI scheitert der Restore meist nicht am Datenbank-Dump, sondern an der glpicrypt.key. Im Betriebssupport von Kundenumgebungen haben wir schon einen „perfekten“ Restore der Datenbank erlebt, nach dem sich niemand mehr per LDAP anmelden oder E-Mails versenden konnte: Die Daten waren zurück, aber der Schlüssel, der die Passwörter für LDAP, SMTP und E-Mail-Collector entschlüsselt, war zurückgeblieben. Dieser Leitfaden fasst den Fahrplan für Backup, Rotation, Restore-Test und Disaster Recovery zusammen, den wir in der Produktion anwenden, mit den Stellen, an denen es wirklich bricht.

Was wirklich ins Backup gehört

Das GLPI hat drei Zustandsschichten, und alle drei müssen gemeinsam und konsistent zurückkommen:

  • Datenbank – Tickets, Assets, Benutzer, Regeln und Konfigurationen. Sie ist das Herzstück, bringt die Umgebung allein aber nicht wieder zum Laufen.
  • Dateiverzeichnis (files/) – angehängte Dokumente (files/_documents), Bilder, XML-Inventare und Plugin-Daten. Wenn die Datenbank den Eintrag des Dokuments hat, die Datei aber nicht zurückgekommen ist, klickt der Benutzer und erhält einen Fehler.
  • Konfiguration (config/) – die config_db.php (Host, Datenbank und Zugangsdaten) und vor allem die glpicrypt.key. Dieser Schlüssel entschlüsselt die in der Datenbank gespeicherten Passwörter: LDAP-Bind, E-Mail-Collector (mailcollector), SMTP der Benachrichtigungen und OAuth-Secrets. Wer die Datenbank ohne ihn wiederherstellt, macht all diese Passwörter zu nicht entschlüsselbarem Datenmüll.

Innerhalb von files/ braucht nicht alles ein Backup. Flüchtige Verzeichnisse wie _cache, _tmp, _sessions, _cron und _lock werden automatisch neu erzeugt und blähen das Backup nur auf – schließen Sie sie aus. Erhalten müssen Sie _documents, _pictures, _uploads, _inventories und _plugins.

Konsistenter Dump der Datenbank

GLPI 10 und 11 verwenden InnoDB für alle Tabellen, daher erstellt --single-transaction einen konsistenten Snapshot, ohne die Anwendung zu sperren – die Benutzer erstellen während des Backups weiter Tickets. --quick verhindert, dass riesige Tabellen in den Speicher geladen werden, und --default-character-set=utf8mb4 verhindert beschädigte Umlaute, Akzente und Emojis. Übergeben Sie das Passwort nie auf der Kommandozeile (es erscheint in ps und in den Logs); verwenden Sie eine Zugangsdatendatei mit eingeschränkten Rechten:

# ~/.my.cnf (chmod 600) - evita a senha no 'ps' e nos logs
[client]
host = 127.0.0.1
user = glpi
password = ...senha_do_glpi...

Das native Backup des GLPI (Verwaltung > Wartung) schreibt eine .sql nach files/_dumps, stößt bei großen Datenbanken aber gern an die Zeit- und Speichergrenzen von PHP. Für die Produktion ist ein geplanter mysqldump zuverlässiger.

Backup-Skript mit Rotation

Ein einziges Skript, das Datenbank, Dateien und Konfiguration in der richtigen Reihenfolge sichert und zusätzlich alles bereinigt, was älter als 30 Tage ist:

#!/usr/bin/env bash
set -euo pipefail

# Credenciais em ~/.my.cnf (chmod 600), nunca na linha de comando
DATA=$(date +%F)
DEST="/backup/glpi/${DATA}"
mkdir -p "${DEST}"

# Banco: snapshot consistente de InnoDB, sem travar a aplicacao
mysqldump --single-transaction --quick --routines --triggers \
  --default-character-set=utf8mb4 glpi \
  | gzip -6 > "${DEST}/glpi_db.sql.gz"

# Arquivos + config DEPOIS do dump (arquivo a mais e inofensivo;
# linha no banco apontando para arquivo ausente, nao)
tar -czf "${DEST}/glpi_files.tar.gz" \
  --exclude='files/_cache' --exclude='files/_tmp' \
  --exclude='files/_sessions' --exclude='files/_lock' \
  -C /var/www/glpi files config

# Rotacao: manter 30 dias
find /backup/glpi -maxdepth 1 -type d -mtime +30 -exec rm -rf {} +

echo "Backup OK: ${DEST}"

Achten Sie auf die Reihenfolge: Der Dump kommt vor dem tar. Eine Datei, die nach dem Dump auf die Platte geschrieben wurde, ist beim Restore harmlos; der umgekehrte Fall – ein Datenbankeintrag, der auf eine Datei verweist, die beim Lauf von tar noch nicht existierte – wird zum defekten Anhang. Planen Sie es im Cron ein:

# /etc/cron.d/glpi-backup - diario as 02h15
15 2 * * * root /opt/scripts/backup-glpi.sh >> /var/log/glpi-backup.log 2>&1

Entscheidungsmatrix: RPO x RTO

Bevor Sie Häufigkeit und Aufbewahrung festlegen, beantworten Sie zwei Fragen: Wie viele Daten darf das Unternehmen verlieren (RPO), und wie schnell muss es wieder laufen (RTO)? Die Antwort hängt von der Kritikalität ab:

Profil der UmgebungZiel-RPOZiel-RTOHäufigkeit (Datenbank)AufbewahrungOffsite
Abnahme / Test24 hTagetäglich7 Tageoptional
Standardproduktion24 h4 htäglich14–30 Tageja (Cloud)
Kritische Produktion (SLA)15 min1 htäglich + Binlog oder Replikat30–90 Tageja, verschlüsselt

Das sind ehrliche Spannen, keine Versprechen. Ein RPO von 15 Minuten erfordert das Binlog von MariaDB/MySQL oder ein Replikat – der tägliche Dump allein leistet das nicht.

Restore-Test: der Schritt, den fast niemand macht

Ein Backup, das nie wiederhergestellt wurde, ist eine Zahl in einem Bericht, keine Garantie. Proben Sie den Restore regelmäßig in einer Wegwerfumgebung – Docker ist ideal – und niemals über der Produktion:

# Ambiente DESCARTAVEL (Docker). Nunca ensaie por cima da producao.
mysql -u root -e "CREATE DATABASE glpi_restore CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"

# 1) Banco
zcat glpi_db.sql.gz | mysql --default-character-set=utf8mb4 -u root glpi_restore

# 2) Arquivos + config (INCLUI o config/glpicrypt.key)
tar -xzf glpi_files.tar.gz -C /var/www/glpi

# 3) Codigo mais novo que o dump? aplica a migracao de schema
php bin/console db:update --no-interaction

# 4) Limpa o cache e sobe para validar login/LDAP/e-mail
php bin/console cache:clear

Bestätigen Sie nach dem Restore, dass der Zustand mit der Realität übereinstimmt, bevor Sie ihm vertrauen. Zwei schnelle Abfragen fangen bereits die häufigsten Probleme ab:

-- Versao gravada no banco (precisa casar com a do codigo antes do db:update)
SELECT value AS versao_db
FROM glpi_configs
WHERE context = 'core' AND name = 'version';

-- Quantos documentos apontam para um arquivo fisico em files/_documents
SELECT COUNT(*) AS docs_com_arquivo
FROM glpi_documents
WHERE filepath <> '';

Die erste zeigt die in der Datenbank gespeicherte Version: Ist sie niedriger als die des Codes, gleicht db:update das Schema an. Die zweite zählt die Dokumente, für die eine Datei auf der Platte erwartet wird – vergleichen Sie das mit dem, was tatsächlich in files/_documents angekommen ist. In Docker laufen dieselben Schritte mit docker exec -u www-data glpi php bin/console ....

Echtes Disaster Recovery

Backup ist ein Befehl; Disaster Recovery ist ein Plan. Das gesunde Minimum ist die 3-2-1-Regel: drei Kopien, auf zwei verschiedenen Medien, eine davon offsite. Und hier liegt der häufige Fehler: den Datenbank-Dump und config/ (mit der glpicrypt.key) unverschlüsselt in dieselbe .tar zu packen und in einen Bucket zu schicken. Wer diese Datei in die Hände bekommt, hat die gesamte Datenbank und den Schlüssel, der die Passwörter für LDAP, SMTP und Collector entschlüsselt – also Infrastruktur-Zugangsdaten des Kunden in wiederherstellbarer Form. Ein Offsite-Backup muss verschlüsselt (zum Beispiel mit age oder gpg) und mit eingeschränktem Zugriff übertragen werden.

Schließen Sie den Plan mit einem schriftlichen Runbook ab – wo die Backups liegen, in welcher Reihenfolge wiederhergestellt wird, wer auslöst – und mit dem in einer echten Probe gestoppten RTO. Im Betriebssupport war das, was einen Schreck von einer Katastrophe trennt, nie das Vorhandensein eines Backups; es war, dieses Backup vorher mit der Stoppuhr in der Hand wiederhergestellt zu haben und zu wissen, dass es in 40 Minuten zurück ist und nicht in „keine Ahnung“.

Wenn Ihr GLPI kritisch ist und Sie noch nie einen vollständigen Restore gestoppt haben – Datenbank, Dateien und Verschlüsselungsschlüssel zusammen –, entwirft und betreibt NexTool die Backup- und Disaster-Recovery-Routine Ihrer Umgebung, mit geprobtem Restore und verschlüsseltem Offsite-Backup. Sprechen Sie mit uns über Support und Betriebssupport für GLPI.


Geprüft vom Team der NexTool Solutions.

Häufig gestellte Fragen

Verwenden Sie mysqldump --single-transaction: Da GLPI 10 und 11 vollständig auf InnoDB laufen, ist der Dump konsistent, ohne die Anwendung zu sperren, und die Benutzer erstellen weiter Tickets. Sichern Sie die Dateien (files/) und die Konfiguration direkt danach, im selben per Cron geplanten Skript.

Sie ist der Schlüssel, der die in der Datenbank gespeicherten Passwörter entschlüsselt: LDAP-Bind, E-Mail-Collector, SMTP der Benachrichtigungen und OAuth-Secrets. Wenn Sie die Datenbank wiederherstellen, aber die config/glpicrypt.key verloren haben, werden diese Passwörter zu nicht entschlüsselbarem Datenmüll, und die LDAP-Anmeldung sowie der E-Mail-Versand fallen aus. Sichern Sie config/ immer zusammen mit der Datenbank.

Datenbank: in der Produktion mindestens täglich. Dateien: täglich oder wöchentlich, je nach Volumen der Anhänge. Für ein kurzes RPO (15 bis 30 Minuten) benötigen Sie das Binlog von MariaDB oder ein Replikat; der tägliche Dump allein liefert ein RPO von bis zu 24 Stunden.

Stellen Sie es regelmäßig in einer Wegwerfumgebung (Docker) wieder her, niemals über der Produktion. Starten Sie das GLPI, melden Sie sich an, öffnen Sie ein altes Ticket mit Anhang und prüfen Sie LDAP und E-Mail-Versand. Stoppen Sie die Zeit: Diese Dauer ist Ihr tatsächliches RTO. Ein nie wiederhergestelltes Backup ist keine Garantie.

Ja, solange der Code gleich alt oder neuer ist als der Dump. Stellen Sie die Datenbank wieder her und führen Sie dann php bin/console db:update aus, um das Schema zu migrieren. Stellen Sie niemals einen neueren Dump auf älterem Code wieder her: Die Struktur lässt sich nicht zurückentwickeln, und die Umgebung bricht.

Nach demselben Prinzip: docker exec im Datenbank-Container für den mysqldump und tar der eingebundenen Volumes von files/ und config/. Fixieren Sie die Image-Version (verwenden Sie nicht :latest), damit der Restore auf Code landet, der mit dem Dump kompatibel ist.

Brauchen Sie Hilfe?