Duplicati

Duplicati ist eine Software, mit der man verschlüsselte, inkrementelle Sicherungen durchführen kann. Eine Besonderheit ist, dass auch ferne Sicherungsziele z.B. per SFTP genutzt werden können. Obwohl die Weboberfläche recht übersichtlich und aufgeräumt daherkommt, verfügt die Anwendung über sehr viele und komplexe Features, die ich hier nicht alle darstellen kann. Ich beschränke mich auf das, was ich selbst davon nutze.

Screenshot: Die Weboberfläche von Duplicati
Abb. 1: Screenshot: Die Weboberfläche von Duplicati


Installation

Am Einfachsten ist die Installation per Docker und Docker-Compose. Zunächst ist also eine Docker-Umgebung zu installieren (s. Docker). Dann erstellt man ein Verzeichnis namens duplicati und wechselt dort hinein. Das kann auch im Homeverzeichnis liegen:


mkdir duplicati && cd duplicati
Darin erstellt man dann die Datei docker-compose.yml (z.B. mit dem Editor nano).

nano docker-compose.yml
mit folgendem Inhalt:

services:
    duplicati:
      image: lscr.io/linuxserver/duplicati:latest
      container_name: duplicati
      environment:
        - PUID=0
        - PGID=0
        - TZ=Europe/Berlin
        - SETTINGS_ENCRYPTION_KEY=strenggeheimerundkomplexerkey
        - DUPLICATI__WEBSERVICE_PASSWORD=strenggeheimesundkomplexespasswort
      volumes:
        - ./config:/config
        - ./logs:/logs
        - /sicherungsverzeichnis1:/source1
        - /sicherungsverzeichnis2:/source2
      ports:
        - 8200:8200
      restart: unless-stopped
Ein paar Hinweise zu den gemounteten Verzeichnissen: Das Config-Verzeichnis habe ich in den duplicati-Ordner gemountet. Dadurch werden dann dort ein paar Konfigurationsdateien und insbesondere die intern verwendete SQLite-DB abgelegt. Ohne dieses persistente Volume würden diese Einstellungen und damit auch alle Sicherungsjobs nach jeder Neuinitialisierung der Container weg sein. Dann habe ich das Verzeichnis für die Log-Files gemountet, weil ich später auf die Protokolle zugreifen möchte, um die Ausführung der Sicherungsjob zu monitoren.

Ferner habe ich hier beispielhaft zwei Verzeichnisse namens "sicherungsverzeichnis1" und "sicherungsverzeichnis2" angegeben. Hierbei handelt es sich um Verzeichnisse auf dem Server, die in diesem Fall auf der Wurzelebene des Servers liegen. Hier kann man beliebige Verzeichnisse angeben, die dann später von der Weboberfläche aus und für den Dockercontainer erreichbar sind. Wenn es die Verzeichnisse auf dem Server bereits gibt, werden sie entsprechend eingebunden, ansonsten werden sie (leer) erstellt. Das kann man zum Beispiel auch nutzen, um die Daten von anderen Servern, als dem auf dem duplicati läuft, zu sichern. Ich habe so z.B. nur auf einem Server duplicati laufen und sichere damit die exportierten Daten aus meinem DMS mit Paperless-NGX. Das Exportverzeichnis auf dem DMS-Server habe ich per Samba freigegeben und auf dem Server mit duplicati gemountet. Duplicati kann nämlich Sicherungsziele per SFTP nutzen, aber nicht die Quellen.

Der Encryption-Key wird als Teil der Verschlüsselung der Sicherungsdaten verwendet und das Webservice-Passwort wird benötigt, um sich an der Weboberfläche anzumelden (wer hätte das gedacht?). Diese ruft man mit [IP-Adresse des Server]:8200 auf.



Bedienung

Unter Settings oder Einstellungen kann man die Oberfläche an seinen Geschmack anpassen. Hier lässt sich bei Bedarf auch die Sprache der Oberfläche ändern. Ich gehe im Folgenden von einer deutschsprachigen Oberfläche aus. Einen Parameter stelle ich hier aber auf jeden Fall ein. Und zwar füge ich unter "Optionen für Profis" die erweiterte Option "log-file-log-level" mit dem Wert "Warning" ein. Damit werden Logfiles geschrieben, wenn bei den Sicherungen ein Problem auftritt. Dazu später mehr.



Sicherungen anlegen

Der Dialog zum Einrichten neuer Sicherungen ist recht intuitiv gehalten. Die wichtigsten Einstellungen lassen sich mit wenigen Mausklicks vornehmen. Die Einrichtung neuer Sicherungsjobs beginnt mit einer Seite namens "Allgemeine Sicherungseinstellungen", Hier gibt man der Sicherung einen Namen. Der darf ruhig sprechend sein. Eine Beschreibung kann man optional angeben. Dann wählt man die Verschlüsselungsmethode aus. Die integrierte AES-Verschlüsselung ist vorausgewählt und kann auch so übernommen werden. Alternativ kann man GnuPG auswählen. Dann muss man die entsprechenden Parameter auf der letzten Dialogseite (Optionen) angeben. Auf der zweiten Dialogseite wählt man das Sicherungsziel aus. Hier zeigt Duplicati seine Stärken. Hier werden neben dem Dateisystem zahlreiche externe Ziele für die Sicherungen angeboten. Die jeweils spezifischen Parameter werden dann in individuellen Dialogen erfasst. Im Dialog Quelldaten gibt man natürlich die zu sichernden Dateien oder Verzeichnisse an. Zu beachten ist, dass hier nur die Verzeichnisse verfügbar sind, die entweder vom System vorgegeben sind oder die zuvor in der Datei docker-compose.yml definiert wurden. Es handelt sich schließlich um eine Anwendung in einem Docker-Container. Darum ist das Dateisystem des Servers hier nicht verfügbar.

Auf der Dialogseite "Zeitplan" definiert man die Zeitplanung für die Sicherungen. Diese Seite ist selbsterklärend. Auf der letzten Dialogseite kann man sehr viele Parameter definieren. Die Ziel-Volumen-Größe kann man die maximale Größe der einzelnen Chunks, hier Volumes genannt, definieren. Der voreingestellte Wert sollte meines Erachtens passen. Spannend ist der Parameter "Sicherungsaufbewahrung". Hier kann man sehr differenzierte Retentionregeln vorgeben. Das wäre ein Kapitel für sich, über das man Bücher schreiben könnte. Für die meisten Anwendungsfälle sollte die "Intelligente Sicherungsaufbewahrung" eine gute Wahl sein. Damit kann man dann später auf die Sicherungen für jeden der letzten 7 Tage, jede der letzten 4 Wochen und jeden der letzten 12 Monate zurück greifen.

Darunter wird noch ein Kasten "Optionen für Profis" angeboten. Hier kann man sehr viele individuelle Vorgaben machen. Zum Beispiel könnte man einige Parameter erfassen, damit das System Logfiles per Mail versendet. Da das recht kompliziert ist, habe ich mir eine einfachere Lösung mittels eines Skript ausgedacht (s.u.). Wenn ich das nicht allgemein unter "Einstellungen" gemacht hätte (s.o.), dann könnte ich hier jetzt ein Loglevel auswählen.

Mit diesen Einstellungen kann ich die Sicherung speichern und mit "Start" testen.



Restore

Datenrücksicherungen kann ich auf der Hauptseite unter "Wiederherstellungen" anstoßen. Hier kann ich entweder basierend auf den gespeicherten Sicherungsjobs eine Wiederherstellung vornehmen oder Sicherungsziele auswählen und alle benötigten Parameter, wie z.B. Zugangsdaten manuell eingeben. Die zurück zu sichernden Daten können über die Ursprungsquelle oder an einen anderen Ort gespeichert werden. Hier stehen natürlich nur Verzeichnisse zur Verfügung, die zuvor in der docker-compose.yml gemountet wurden.



Benachrichtigung per Mail

Duplicati kann auch per Mail kommunizieren. Das einzurichten, ist aber einigermaßen kompliziert. Für meine Zwecke reicht es aus, wenn Logfiles bedarfsweise auf dem lokalen System per Mail bereit gestellt werden. Dazu muss ich zunächst den Log-Level so einstellen, dass Logfiles immer oder zumindest im Fehlerfall geschrieben werden. Ich habe oben bereits beschrieben, dass ich entweder in den allgemeinen Einstellungen oder den Einstellungen für die jeweiligen Sicherungsjobs unter "Optionen für Profis" den Parameter "log-file-log-level" auswähle und auf "Warning" einstelle. So werden Logfiles geschrieben, wenn die Sicherungen nicht ohne Warnungen oder Fehlermeldungen laufen. Auf dem Server müssen Mails zumindest netzwerkintern versendet werden können. Dazu ist ein Mail-Transfer-Agent erforderlich und da ich die Mails per imap mit einem Mailclient abrufen möchte, wird auch ein IMAP-Server benötigt. Ich installiere hierzu immer postfix und dovecot (s. hierzu z.B. Wiki von Ubuntuusers.de: postfix und: doevecot). Auf die Spezifika des Mailservers oder des Clients will ich hier nicht näher eingehen. Damit die Logfiles aber per Mail übermittelt werden, habe ich mir ein kleines Bash-Skript ausgedacht. Ich erstelle eine Datei logmonitoring.sh mit folgendem Befehl


nano logmonitoring.sh
mit folgendem Inhalt:

#!/bin/bash

# Konfigurationsvariablen
LOG_FILE="/home/andreas/duplicati/logs/duplicati.log"   # Pfad zur Log-Datei
ARCHIVE_DIR="/home/andreas/archive"                     # Ordner für archivierte Logs
EMAIL_TO="andreas@localhost"                            # Empfaenger der E-Mail

# Pruefen, ob das Log-File existiert
if [ ! -f "$LOG_FILE" ]; then
    echo "Log-Datei existiert nicht: $LOG_FILE" | mail -s "Duplicati Log-Datei existiert nicht!" "$EMAIL_TO"
    exit 1
else

  # Pruefen, ob das Log-File nicht leer ist
  if [ -s "$LOG_FILE" ]; then
      # Log-Datei ist nicht leer, E-Mail senden
      cat $LOG_FILE | mail -s "Duplicati Backup Fehler oder Warnung" "$EMAIL_TO"
      # Log-Datei umbenennen und archivieren
      TIMESTAMP=$(date +"%Y%m%d-%H%M%S")
      mv "$LOG_FILE" "$ARCHIVE_DIR/backup_$TIMESTAMP.log"
  fi
fi
Wo die Datei liegt, ist nachrangig. Ich habe sie in den Ordner duplicati im Homeshare auf dem Server abgelegt. Das Skript prüft, ob das Logfile existiert und leer ist. Wenn die Sicherungen problemlos laufen, dann wird eine leere Logdatei geschrieben. Das heißt, wenn es eine leere Logdatei gibt, dann ist alles OK. Wenn es die Datei nicht gibt, dann ist gar keine Sicherung gelaufen. Das wird per Mail mitgeteilt. Wenn die Datei gibt, sie aber nicht leer ist, dann ist die Sicherung nicht ordnungsgemäß durchgelaufen und ein Fehlerprotokoll wurde in diese Datei geschrieben. Der Inhalt der Datei wird dann per Mail übermittelt. Außerdem wird sie in einen Archivordner verschoben. Das erfordert Schreibberechtigung auf den Ordner logs und die Logdatei. Darum muss das Skript mit Root-Rechten ausgeführt werden.

Zunächst muss die Datei mit

chmod +x logmonitoring.sh
ausführbar gemacht werden und dann kann ich sie mit

sudo ./logmonitoring.sh
testen. Probehalber kann ich mit

sudo nano logs/duplicati.log
eine neue Datei anlegen oder eine bestehende bearbeiten. Hier schreibe ich irgendetwas hinein und starte dann manuell das Skript mit

sudo ./logmonitoring.sh
Es sollte nun eine Mail gesendet werden mit dem Inhalt der Datei und danach die Datei weggesichert werden. Wenn ich das Skript erneut aufrufe, dann sollte es feststellen, dass es keine entsprechende Datei gibt und ebenfalls eine Mail senden, die aufzeigt, dass es diese Datei aktuell nicht gibt. Wenn ich nun noch

sudo touch logs/duplicati.log
eingebe, um eine leere Datei anzulegen und das Skript ein drittes Mal ausführe, dann sollte nichts passieren, weil alles in Ordnung zu sein scheint.

Natürlich will ich das Skript nicht jedesmal manuell ausführen. Es soll regelmäßig automatisiert ausgeführt werden. Dazu bearbeite ich die Datei Crontab des Root-Users mit

sudo crontab -e
Wenn ich diesen Befehl auf diesem System erstmalig eingebe, dann werde ich aufgefordert einen Editor für die Bearbeitung dieser Systemdatei auszuwählen. Hier wähle ich mit der Option "1" den Editor nano aus. Das ist natürlich Geschmackssache. Jedenfalls füge ich folgenden Eintrag am Ende der Datei ein:

0 5     * * *   root    /home/andreas/duplicati/logmonitoring.sh
Mit den ersten beiden Parametern definiere ich die Uhrzeit der Ausführung (Minute Stunde), hier also 5:00 Uhr morgens. Mit den nächsten drei Parametern definiere ich den Tag der Ausführung (Monat, Tag des Monats, Wochentag). Mit den Sternen definiere ich also, dass das jeden Tag ausgeführt werden soll. Dann definiere ich, mit welchem Benutzer (hier root) das ausgeführt werden soll und schließlich den eigentlichen Befehl mit dem kompletten Pfad. Das Skript wird also jeden Morgen um 5:00 Uhr mit den Rechten des Administratorusers root ausgeführt. Wenn die Sicherungsjobs vorher ausgeführt werden, dann erhalte ich so täglich eine Meldung per Mail, wenn es dabei Probleme gab. Keine Mail heißt dabei, dass alles OK ist. Wenn ich in den Einstellungen von Duplicati den Loglevel auf "verbose" setzen würde, dann würde ich immer eine Mail erhalten, auch wenn alles OK ist. Das kann man anfangs zu Testzwecken eine Weile so machen und dann auf "warning" umstellen.