12. August 2020, 22:44

Nextcloud-Datensicherung mit tar

Eine Nextcloud-Instanz zu installieren ist schnell erledigt. Es gibt zahlreiche Tutorials und bei besseren NAS-Systemen oder Hosting-Anbietern sogar fertige Appliances zum eleganten Zusammenklicken. Bei der Datensicherung erschöpfen sich meiner Beobachtung nach die Quellen und die wenigen Anleitungen im Netz würde ich eher nicht verwenden.

Dieser Blog-Beitrag möchte helfen, den Datenschutz mit einer automatisierten, täglichen und vollständigen Sicherung für die eigene Nextcloud zu erhöhen. Zielgruppe sind private Betreiber. Dabei soll nicht das Skript im Vordergrund stehen, sondern viel mehr die Gedanken und Abwägungen drum herum.

Vorüberlegungen

Angefangen mit Bare-Metal-Sicherungen ganzer Server oder Partitionen, tar, rsync oder borg für vollständige oder inkrementielle Datensicherungen bis hin zu 7zip für verschlüsselte Datenweitergaben an Dritte, gibt es zahlreiche Sicherungslösungen. Und das sind nur einige freie Lösungen. Von den vielen unfreien Lösungen wie Acronis, Veeam & Co will ich gar nicht erst anfangen.

Also, warum tar?

Meine Ideallösung eines Sicherungskonzeptes sieht nicht nur eines, sondern mehrere, ineinandergreifende Tools vor. Für die Ansprüche und Datenmengen in meiner Nextcloud-Instanz habe ich mich für GNU tar entschieden. Die Gründe:

  • Es ist freie Software.
  • Einfache Handhabung und Einbindung in Skripte.
  • Hohe Verbereitung auf praktisch allen unixoiden Systemen (POSIX Standard).
  • Seit Jahrzehnten bewährte Stabilität und Zuverlässigkeit, wichtig für Langzeitarchive.
  • Verzeichnisstrukturen, Berechtigungen und Besitzrechte werden in einer handlichen Sicherungsdatei (“tarball”) abgelegt.
  • Sicherungsdateien können ad hoc auf externe Medien oder zwischen Rechnern kopiert werden.
  • Es benötigt keine im Hintergrund mitlaufende Dienste, Extra-Benutzer oder gar eine Backup-Infrastruktur aus Repositories, Index-Datenbanken, Medienverwaltungen oder Klicki-Bunti-Weboberflächen (KISS-Prinzip).

Technische Voraussetzungen

Das Sicherungsziel ist eine SMB-Netzwerkfreigabe auf einem anderen Rechner, in meinem Fall ein FreeNAS. Das Skript geht davon aus, das diese Freigabe direkt erreicht werden kann. Wer seine Nextcloud in abgetrennten Netzwerksegmenten betreibt, muss diese direkte Verbindungsmöglichkeit in Firewall und/oder Routingtabellen eingerichtet haben.

Geschrieben ist alles auch aus der Debian-Perspektive. Bei Anwendung auf die verschiedenen Derivate ist dies bitte zu berücksichtigen. Gestartet und nachher als cronjob ausgeführt wird das Script unter dem Nutzer root. Ein sudo gibt es von Haus aus nicht auf einem frisch installierten Debian-Server und sollte daher, zusammen mit dem cifs-utls, installiert werden:

# apt install cifs-utils sudo

Ferner setze ich einen funktionierenden Mailserver voraus, der Statusmeldungen mit “sendmail” verschicken kann. Zum Überprüfen, ob dieser richtig eingerichtet ist und E-Mails auch wirklich versendet, reicht der nachfolgende Einzeiler an die eigene E-Mail-Adresse. Wenn alles funktioniert sollte eine leere E-Mail im Postfach landen:

# sendmail "email@domain.tld" < /dev/null

Desweiteren setze ich voraus, dass die mySQL/MariaDB Datenbank und das Nextcloud /data Verzeichnis auf dem gleichen Host liegen. Was das /data Verzeichnis betrifft, bitte auch den Abschnitt unter “Optimierungen” lesen.

Datenmengen & Sicherungsdauer

Der überwiegende Teil meiner Daten liegt auf einer FreeNAS und wird als “Externer Speicher” eingebunden. Das hält die Nextcloud relativ schlank. Wir reden, in meinem Beispiel, von “nur” 31 GB an zu sichernden Daten, die in ca. 30 Minuten gesichert werden. Eine akzeptable Downtime der Nextcloud, die während der vollständigen Sicherung in den Wartungsmodus gesetzt wird und während dessen nicht nutzbar ist.

Push vs. Pull

Aus der Vogelperspektive betrachtet existieren grundsätzlich zwei Strategien für Datensicherungen: Push- und Pull-Sicherungen.

Bei einem Push-Backup verbindet sich der zu sichernde Host mit einem meist zentralen Sicherungsserver und kopiert seine Daten dorthin. Der Umkehrfall wird als Pull-Backup bezeichnet. Hier verbindet sich ein zentraler Sicherungsserver mit dem zu sichernden Host und zieht sich die Daten nach einer zuvor fest vorgegebenen Logik.

Oberflächlich betrachtet erscheint ein Pull-Backup sicherer. Praktisch ist die Situation etwas komplizierter. Hier einige Faktoren, die gegen eine Pull-Backup-Strategie sprechen:

  • Auf dem zu sichernden Host muss ein zusätzliches Backupkonto mit sudo-Rechten eingerichtet werden - auf jedem von möglicherweise vielen Hosts in einer Firma oder Entität. Doch was machen Admins in zuverlässiger Regelmäßigkeit? Sie erstellen global gültige Konten mit einheitlichen Kennwörtern auf allen Hosts, ein “Multipass” für jeden Hacker.
  • Ein Remotezugriff muss für solche Backupkonten neben den administrativen Zugängen über SSH, VPN oder SMB-Freigaben hinterlegt sein.
  • Da jede Initiative vom Sicherungsserver ausgeht, muss dieser auch die gesamte Logik vorhalten und alle Eventualitäten berücksichtigen. Lustig wird es, wenn ein Host gerade mit einer wichtigen Berechnung oder Aufgabe betreut ist, bei der jeder CPU-Kern und jedes Byte im I/O benötigt wird, und dann klopft der Sicherungsserver an und beginnt stumpf seine Sicherungen nach Dienst abzuarbeiten.
  • Eine zentral abgelegte Logik skaliert in der Regel schlechter und muss bei mehreren Servern mit Ausnahmen und individuellen Anpassungen zurecht kommen. Aus kleinen Skripten werden komplexe Code-Monster, die kein Admin an dieser kritischen Stelle sehen will.
  • Die wenigsten Anwendungen lassen sich “live” im Betrieb sichern. Auch sind Downzeiten teuer und sollten vermieden werden. Daher halten viele Server ein Backup Ihrer Daten vor, bis sich ein Sicherungsserver endlich erbarmt diese abzuholen. Bis dahin bieten diese Kopien eine ideale Gelegenheit zum Abgreifen oder Manipulieren, die es zuvor im Live-Betrieb nicht gab und später im Backup nicht mehr geben wird.

Wie so oft ist es eine Abwägung zwischen Vor- und Nachteilen und auch anhand der bestehenden Begebenheiten.

Das hier gezeigte Skript arbeitet mit der Push-Strategie, d.h. die Nextcloud mounted einen SMB-Share, kopiert die Daten und unmountet diesen anschließend wieder.

Die Sache mit der Verschlüsselung

Neben dem Umstand, dass tar keine Verschlüsselung anbietet ist aus anderen Gründen eine Verschlüsselung in unserem Szenario unerwünscht:

  • Verschlüsselte Backups erhöhen die Komplexität und schaffen zusätzliche Probleme, die man bei Langzeitsicherungen gerade nicht haben möchte. So könnten z.B. abgelaufene oder vergessene Schlüssel oder von der Zeit längst überholte Container mit irgendwelchen Abhängigkeiten den Zugriff auf das Backup verhindern.
  • Wir bewegen uns vollständig innerhalb einer kontrollierten und geschützten Umgebung.
  • Es ist sinnfrei einzelne Sicherungsdateien verschlüsseln zu wollen, wenn dies bereits auf tieferliegender Ebene durch ein Dateisystem erfolgt. In meinem Fall ist es ein FreeNAS-RAID mit ZFS und aktivierter Festplattenverschlüsselung.

Verschlüsselt werden sollten Daten nach Möglichkeit nur dort, wo ein Übergang oder Transport von der eigenen, sicheren Umgebung in eine unsichere erfolgt (z.B. bei Hinterlegung von Backups auf Festplatten bei Dritten).

Praxis

Vorbereitungen

Die zum Mounten der SMB-Netzwerkfreigabe benötigten Zugangsdaten werden in einer Textdatei im Root-Homeverzeichnis abgelegt. Unerreichbar für andere Benutzer. Der Name dieser Datei ist frei wählbar, wir benennen diese “.smbcredentials”. Der Inhalt besteht nur aus drei Textzeilen, in denen die Zugangsdaten zu hinterlegen sind:

username=
password=
domain=

Mit mysqldump werden wir auch ein vollständiges Backup der Nextcloud-Datenbank machen und benötigen auch die Zugangsdaten hierfür. Daher sind in der Datei “.my.cnf” im Root-Homeverzeichnis zu hinterlegen. Dieser Dateiname ist vorgegeben und muss exakt so übernommen werden.

[mysqldump]
user=
password=

Damit das SMB-Netzwerklaufwerk eingehängt werden kann, braucht es noch einen geeigneten Ordner. Das Skript erwartet diesen im Homeverzeichnis von Root unter /root. Dort erstellt Ihr bitte einfach einen Unterordner mit dem Namen “backup”.

# mkdir /root/backup

Sind die Zugangsdaten hinterlegt, kann es mit dem Skript losgehen.

Das Skript

Mit einem Texteditor der freien Wahl wird eine Textdatei mit dem Namen “backupscript” im Root-Homeverzeichnis erstellt und der nachfolgende Inhalt in dieser eingesetzt.

Das Skript besteht aus zwei Teilen. In der ersten Hälfte werden alle benötigten Parameter gesetzt und sind dem eigenen Anwendungsfall anzupassen.

Die zweite Hälfte beinhaltet das eigentliche Skript. Hier sollte nach Möglichkeit nichts verändert werden. Zum besseren Verständnis habe ich jede Zeile einzeln kommentiert.

Zwei wichtige Hinweise: Am Ende des Skriptes erfolgt ein Aufräumvorgang. Dabei werden die im Root-Homeverzeichnis erstellten temporären Dateien wieder entfernt. Wer die Logdatei benötigt muß das Script entsprechend anpassen.

Es erfolgt auch keine Überprüfung des verfügbaren Speicherplatzes auf dem Ziellaufwerk. Ich gehe davon aus, dass dieses von Zeit zu Zeit überprüft und bereinigt wird.

#!/bin/bash

# Datum Praefix vor den Dateinamen YYYYMMDD
DATE_PREFIX=$(date +%Y%m%d)

# SMB-Netzwerklaufwerk
SMB_DIR="//remotehost/share"

# Mountingpoint vom SMB Netzwerklaufwerkes
MOUNT_DIR="/root/backup"

# SMB Credentials Datei für die SMB Zugangsdaten
SMB_CRED_FILE="/root/.smbcredentials"

# Das Nextcloud Verzeichnis
NEXTCLOUD_DIR="/var/www/cloud.domain.tld"

# Der Datenbankname
NEXTCLOUD_DB=nextcloud

# Name und Ablageort der Statusdatei YYYYMMDD-backuplog.txt
THE_LOG="/root/$DATE_PREFIX-backuplog.txt"

# Name und Ablageort des Datenbank Dumps
THE_DUMP="/root/$DATE_PREFIX-cloud-DB.sql"

# Empfänger der Statusdatei
SEND_REP="email@domain.tld"

# Exclude Dateien oder Ordner
EXCLUDE_PATTERN="--exclude='$NEXTCLOUD_DIR/data/updater*' --exclude='$NEXTCLOUD_DIR/data/*.log'"



# -- Bitte ab hier nichts mehr manuell anpassen --

# Erstellen der Statusdatei und Hinterlegung der Startzeit
echo "Beginne Backup (Startzeit: $(date +%T))..." > $THE_LOG

# SMB Laufwerk mounten
mount -t cifs -o credentials=$SMB_CRED_FILE $SMB_DIR $MOUNT_DIR

# Wartungsmodus der Nextcluod aktivieren
sudo -u www-data php $NEXTCLOUD_DIR/occ maintenance:mode --on

# Erstellen mysql Dump
mysqldump $NEXTCLOUD_DB > $THE_DUMP

# Alles in das Zielverzeichnis mit tar sichern
tar $EXCLUDE_PATTERN -cvpf "$MOUNT_DIR/$DATE_PREFIX-cloud.tar" $NEXTCLOUD_DIR $THE_DUMP

# Wartungsmodus deaktivieren
sudo -u www-data php $NEXTCLOUD_DIR/occ maintenance:mode --off

# Zielverzeichnis prüfen, Stopzeit festhalten
echo "...Backup beendet (Stopzeit: $(date +%T))" >> $THE_LOG
ls -lh $MOUNT_DIR >> $THE_LOG

# Statusdatei senden
sendmail $SEND_REP < $THE_LOG

# Garbagge Collection
rm $THE_LOG $THE_DUMP &
umount $MOUNT_DIR

Ist die Datei erstellt, muss diese noch ausführbar gemacht werden:

# chmod +x /root/backupscript

Das war’s! Das Skript kann jetzt manuell oder automatisiert z.B. mit crontab nachts oder an Wochenenden gestartet werden. Einzige Voraussetzung: Es muss als root gestartet werden.

Optimierungen

Abhängig von Anzahl der Benutzer und Menge der Daten kann eine Sicherung längere Zeit in Anspruch nehmen. Da das Skript bewusst immer vollständige Sicherungen ausführt, beinhaltet es einige kleine aber feine Optimierungen:

Dateien auslassen

Die erste Optimierungsmöglichkeit besteht aus dem Auslassen der in der Regel sehr grossen Log-Dateien. Auch das Updater-Verzeichnis mit den Sicherungen vergangener Versionen kann getrost ausgelassen werden. Aus diesem Grund existiert die EXCLUDE_PATTERN-Zeile:

EXCLUDE_PATTERN="--exclude='$NEXTCLOUD_DATA_DIR/updater*' --exclude='$NEXTCLOUD_DATA_DIR/*.log'"

Papierkorb leeren

Eine weitere Optimierungsmöglichkeit wäre das vorherige Löschen des Papierkorbs aller Benutzer. Ich habe es nicht in das Skript aufgenommen. Wer aber möchte, der kann bei Bedarf zwischen dem Einschalten des Wartungsmodus und dem Erstellen der Datenbank-Dumps diese Zeile einfügen:

sudo -u www-data php $NEXTCLOUD_DIR/occ trashbin:cleanup --all-users

Sicherungszeit vs. Festplattenspeicher

Das Skript sichert ohne Kompression damit die Downtime möglichst gering gehalten wird. Wem diese egal ist und mehr Wert auf möglichst kleine, komprimierte Sicherungsdateien legt, der kann die -j Option (für bzip2) aktivieren und die Dateierweiterung ergänzen:

tar $EXCLUDE_PATTERN -cvjpf "$MOUNT_DIR/$DATE_PREFIX-cloud.tar.bz2" $NEXTCLOUD_DIR $THE_DUMP

In meinem Fall lohnt sich eine Kompression nicht, da der Benefit nur bei ca. 5% (2 GB) an gewonnenem Speicherplatz liegt, dafür aber eine 4x längere Sicherungszeit kostet (2h anstelle 30 Min). Your milage may vary und es gibt neben bzip natürlich weitere Kompressionsverfahren in mit unterschiedlichen Kompressionsstärken und Geschwindigkeiten.

Screenshot zeigt Vergleich der tarballs mit und ohne Kompression

Wo liegt das /data Verzeichnis?

Den grössten Vorteil, nicht nur bei der Sicherheit, sondern auch hinsichtlich Performance, erzielt man durch die die richtige Lage des /data-Verzeichnisses. Dieses sollte nach Möglichkeit ausserhalb des Nextcloud-Ordners liegen. Idealerweise auf einer anderen Festplatte.

Das Skript geht vom Nextcloud-Installationsdefault ohne verschobenes /data Verzeichnis aus. Wer dieses woanders liegen hat, muss das Skript um eine zusätzliche Variable NEXTCLOUD_DATA_DIR ergänzen:

# Das Nextcloud /data Verzeichnis
NEXTCLOUD_DATA_DIR="/var/data"

Die Ausnahmeliste muss mit der neuen Variable wie folgt verändert werden:

# Exclude Dateien oder Ordner
EXCLUDE_PATTERN="--exclude='$NEXTCLOUD_DATA_DIR/updater*' --exclude='$NEXTCLOUD_DATA_DIR/*.log'"

Und zuletzt muss natürlich die tar-Zeile um das zusätzlich zu sichernde Verzeichnis ergänzt werden:

# Alles in das Zielverzeichnis mit tar sichern
tar $EXCLUDE_PATTERN -cvpf "$MOUNT_DIR/$DATE_PREFIX-cloud.tar" "$NEXTCLOUD_DIR" "$NEXTCLOUD_DATA_DIR" $THE_DUMP

Parallelisierung

Was ist der Unterschied zwischen

mysqldump $NEXTCLOUD_DB > $THE_DUMP

und

mysqldump $NEXTCLOUD_DB > $THE_DUMP &

Normalerweise werden Anweisungen in Bashskripten nacheinander abgearbeitet. Durch das kaufmännische “&"-Zeichen am Ende der Zeile, wird der Befehl im Hintergrund und damit parallel zum Skript abgearbeitet. Je nach Größe der Datenbank spart man ein paar Minuten Laufzeit.

Das kann gemacht werden, wenn sicher ist, dass die Sicherungszeit der Datenbank kürzer als die der Verzeichnisse ist. In der Regel sollte dies gegeben sein, ich empfehle hier aber ein vorheriges, manuelles Überprüfen.

Kein Backup = kein Mitleid

Für Verantwortungslosigkeit gibt es kein Mitleid und noch weniger eine Entschuldigung. Erst Recht nicht wenn es sich dabei um eine gemeinsam mit anderen genutzte Nextcloud handelt. Auch wenn wir von einer privaten “Familiencloud” reden, so stellt diese in der Regel einen wichtigen Bestandteil des persönlichen Lebens dar, mit allen Bildern, Chats und dem gemeinsamen Datenpool von wichtigen Dokumenten bis hin zu gemeinsamen Erinnerungen.

Dieser Blog-Beitrag zeigt: Eine vollständige und automatisierte Sicherung ist kein Hexenwerk.

In diesem Sinne, viel Spaß und Erfolg!

© 2020 Tomas Jakobs - Impressum und Datenschutzhinweis