← Alle Notizen

Nextcloud und Fileserver automatisch abgleichen

Veröffentlicht · zuletzt geändert

NextCloudrcloneBackupLinuxSelf-Hosting

Auch auf: English, español

Eine gehostete Nextcloud ist bequem, solange das Internet funktioniert. Fällt die Verbindung aus, sind die Daten aber nicht erreichbar. Ein Fileserver im Heimnetz, der eine vollständige Kopie der Nextcloud hält, schließt diese Lücke und ist zugleich der ideale Ausgangspunkt für lokale Sicherungen. nc-bisync.sh hält diese Kopie mit rclone bisync automatisch auf dem aktuellen Stand. Es läuft unbeaufsichtigt per Cron und schlägt nur Alarm, wenn etwas auffällig ist.

Download: nc-bisync.sh

Die Ausgangslage

Die Nextcloud ist die zentrale Ablage, der Fileserver spiegelt sie ins Heimnetz:

Laptops, Handys  ⇄  Nextcloud-Client  ⇄  Nextcloud
                                            ⇅   rclone bisync (automatisch)
                                         Fileserver  →  SMB-Freigaben im Heimnetz
                                            │
                                            └─ rsnapshot (täglich, versioniert) → externe Platte

Laptops und Handys synchronisieren sich wie gewohnt mit dem Nextcloud-Client. Der Fileserver gleicht sich regelmäßig mit der Nextcloud ab und ist über seine SMB-Freigaben im Heimnetz erreichbar. Fällt die Internetverbindung aus, liegt dort trotzdem eine vollständige Kopie aller Daten. Weil der Abgleich in beide Richtungen läuft, gelangen auch Dateien, die direkt auf dem Fileserver abgelegt werden, in die Nextcloud. Gesichert wird vom Fileserver aus, unabhängig vom Anbieter.

Für den Abgleich ist rclone bisync gut geeignet: rclone spricht WebDAV direkt an und braucht keinen davfs-Mount. Außerdem bringt es Schutzmechanismen mit, die sonst ein eigenes Wrapper-Skript erfordern würden.

Was das Skript macht

Ein Verzeichnispaar je Freigabe. Jede Freigabe auf dem Fileserver wird mit dem entsprechenden Ordner in der Nextcloud abgeglichen, unabhängig von den anderen. Paare lassen sich einzeln oder in Gruppen starten, auch mit unterschiedlicher Frequenz. Bei Bedarf wird ein einzelner Unterordner, etwa ein großes Projekt, zum eigenen Paar und im übergeordneten Paar automatisch ausgeschlossen.

Archiv nur auf Anforderung. Ein Unterordner archiv innerhalb eines Paares wird im normalen Lauf nie abgeglichen, sondern nur mit --archiv. Er ist intern ein eigenes Paar mit eigenem Zustand. Das ist stabiler als ein Ordner, der per Filter mal ein- und mal ausgeschlossen wird.

Schutz vor Massenschäden. Gegen größere Schäden sichern drei eingebaute Mechanismen ab:

  • --check-access: In jeder Wurzel liegt eine Datei RCLONE_TEST. Fehlt sie auf einer Seite, weil ein Pfad falsch ist oder ein Laufwerk nicht eingehängt ist, bricht der Lauf ab. Das schützt auch davor, dass ein leerer Bind-Mount als „alles gelöscht“ in die Nextcloud übertragen wird.
  • --max-delete 10: Würden mehr als 10 % der Dateien gelöscht, passiert gar nichts.
  • --backup-dir1: Überschriebene und gelöschte Dateien auf dem Fileserver landen in einem Tagesordner und werden nach 30 Tagen aufgeräumt.

Konflikte. Wurde eine Datei auf beiden Seiten geändert, gewinnt die neuere Version (--conflict-resolve newer). Die ältere bleibt umbenannt erhalten.

Robustheit. Mit --resilient und --recover übersteht bisync abgebrochene Läufe meist ohne manuellen --resync. Eine Sperrdatei verhindert überlappende Läufe.

Benachrichtigung. Bei Fehlern kommt eine Nachricht per Mail oder über ntfy. Das Skript unterscheidet dabei, ob ein Resync nötig ist, die Löschgrenze angeschlagen hat oder die Zugriffsprüfung fehlgeschlagen ist. Jeder Lauf wird mit seiner Dauer in summary.log protokolliert.

Filter. Temporärdateien von Office, macOS und Windows werden nie synchronisiert.

Voraussetzungen

Auf dem Fileserver:

  • Linux mit bash ab Version 4 und den Standardwerkzeugen flock (aus util-linux), find und cmp. Auf Debian, Ubuntu und Raspberry Pi OS ist das alles vorinstalliert.
  • rclone 1.66 oder neuer, siehe Schritt 1.
  • Ein Benutzer mit Schreibrechten auf die synchronisierten Verzeichnisse, unter dem das Skript läuft.
  • Optional curl für Push-Nachrichten über ntfy und ein eingerichteter Mailversand für Mail-Benachrichtigungen, siehe Schritt 7.

In der Nextcloud:

  • Ein Konto mit WebDAV-Zugriff und einem App-Passwort.
  • Die Zielordner; fehlende legt --init selbst an.

Setup

Das Skript läuft nicht als root, sondern als der Benutzer, dem die Dateien auf dem Fileserver gehören. Sonst gehörten neu aus der Nextcloud geholte Dateien root und wären für die anderen Benutzer der Freigabe nicht mehr beschreibbar. sudo ist nur für die Installation nötig.

1. rclone installieren

Das Skript braucht rclone 1.66 oder neuer. Die Pakete vieler Distributionen sind älter, deshalb besser das offizielle Installationsskript verwenden:

curl https://rclone.org/install.sh | sudo bash
rclone version

2. Nextcloud-Remote einrichten

Lege in der Nextcloud unter Einstellungen → Sicherheit ein App-Passwort an. Richte dann als der Benutzer, unter dem das Skript später läuft, den Remote ein (ohne sudo):

rclone config
# n) New remote
# name> nc
# Storage> webdav
# url> https://cloud.example.com/remote.php/dav/files/BENUTZERNAME/
# vendor> nextcloud
# user> BENUTZERNAME
# pass> (App-Passwort)

Zum Test:

rclone lsd nc:

3. Skript installieren und anpassen

sudo install -m 755 nc-bisync.sh /usr/local/bin/nc-bisync.sh
sudo install -d -o BENUTZER /var/lib/nc-bisync /var/log/nc-bisync
sudo install -d -o BENUTZER -m 700 /mnt/USB-Crucial/.bisync-backup

Der Modus 755 macht das Skript für alle Benutzer ausführbar, verändern kann es aber nur root. Die zweite Zeile legt das Status- und das Log-Verzeichnis an und übergibt sie dem Benutzer, unter dem das Skript läuft. Die dritte legt das Backup-Verzeichnis (BACKUP_ROOT) an; Modus 700, weil dort überschriebene Dateien aus allen Freigaben landen und nur der Benutzer des Skripts sie sehen soll.

Im Konfigurationsblock am Anfang trägst du die Paare ein, je Zeile Name, lokaler Pfad und Pfad in der Nextcloud:

PAIRS=(
    "administration|/mnt/shares/administration|nc:Administration"
    "bibliothek|/mnt/shares/bibliothek|nc:Bibliothek"
    "dokumente|/mnt/shares/dokumente|nc:Dokumente"
    "fotos|/mnt/shares/fotos|nc:Fotos"
    "projekte|/mnt/shares/projekte|nc:Projekte"
    "unternehmen|/mnt/shares/unternehmen|nc:Unternehmen"
)

Weitere Einstellungen:

Variable Bedeutung Beispiel
ARCHIVE_SUBDIR Unterordner, der nur mit --archiv läuft archiv
BACKUP_ROOT Ablage für überschriebene Dateien /mnt/USB-Crucial/.bisync-backup
MAX_DELETE Löschgrenze in Prozent 10
NOTIFY_MAIL Empfänger für Fehlermeldungen (optional) admin@example.com
NTFY_URL ntfy-Topic für Push-Nachrichten (optional) https://ntfy.sh/mein-topic

Achte darauf, dass BACKUP_ROOT außerhalb aller Paare liegt. Mit nc-bisync.sh --list prüfst du, welche Paare konfiguriert sind und welche einen Archiv-Unterordner haben.

4. Gruppenrechte auf dem Fileserver

Das Skript legt neue Dateien mit umask 002 an, damit sie für die Gruppe beschreibbar bleiben. Damit sie auch die richtige Gruppe bekommen und nicht die primäre Gruppe des Benutzers, sollten die synchronisierten Verzeichnisse das setgid-Bit haben. Das setgid-Bit an einem Verzeichnis bewirkt, dass darin neu angelegte Dateien und Unterordner automatisch dessen Gruppe erben, statt die primäre Gruppe ihres Erstellers zu bekommen.

Für die Paare aus dem Beispiel oben setzt du es so auf allen vorhandenen Verzeichnissen:

for d in administration bibliothek dokumente fotos projekte unternehmen; do
    sudo find "/mnt/shares/$d" -type d -exec chmod g+s {} +
done

Ob es gesetzt ist, erkennst du an einem s in den Gruppenrechten:

$ ls -ld /mnt/shares/dokumente
drwxrws--- 10 stefan familie 4,0K 21. Jul 13:19 /mnt/shares/dokumente

5. Erstabgleich

Teste zuerst mit --dry-run, dann führe den Erstabgleich aus:

nc-bisync.sh --init --dry-run
nc-bisync.sh --init

--init legt die RCLONE_TEST-Dateien in jedem Paar und jedem vorhandenen Archiv-Unterordner an und gleicht alles mit --resync ab. Bei Unterschieden gewinnt die neuere Datei. Bei vielen Daten bietet es sich an, die Paare einzeln einzurichten, zum Beispiel nc-bisync.sh --init fotos.

Im Probelauf ändert das Skript nichts: Es legt auch keine RCLONE_TEST-Dateien an und überspringt deshalb die Zugriffsprüfung.

6. Zeitplan

Trage die Cronjobs mit crontab -e in die Crontab des Benutzers ein, unter dem das Skript läuft. Weil jedes Paar eine eigene Sperre hat, können häufig geänderte Freigaben öfter laufen als selten geänderte:

# häufig geändert: alle 2 Stunden
0 */2 * * *  /usr/local/bin/nc-bisync.sh dokumente fotos projekte unternehmen administration
# selten geändert: nachts
30 2 * * *   /usr/local/bin/nc-bisync.sh bibliothek

Bei vielen Dateien bremst nicht die Übertragung, sondern das Auflisten über WebDAV, und das passiert bei jedem Lauf vollständig. Starte deshalb mit zwei Stunden und lies nach ein paar Tagen die Laufzeiten ab:

tail /var/log/nc-bisync/summary.log

Als Faustregel sollte das Intervall etwa dreimal so lang sein wie ein Lauf. Allzu häufig solltest du nicht abgleichen, denn manche Anbieter drosseln viele WebDAV-Anfragen.

7. Benachrichtigungen einrichten (optional)

Bleiben NOTIFY_MAIL und NTFY_URL leer, schreibt das Skript Fehler nur in summary.log. Für einen unbeaufsichtigten Betrieb solltest du mindestens einen der beiden Wege einrichten; beide lassen sich auch kombinieren.

Mail (NOTIFY_MAIL). Das Skript verschickt die Nachricht mit dem Befehl mail. Dafür muss ein entsprechendes Paket installiert sein, etwa mailutils oder bsd-mailx, und der Server muss Mails nach außen zustellen können. Am einfachsten gelingt das mit msmtp-mta, das die Mails über das SMTP-Konto deines Mailanbieters verschickt. Ob es funktioniert, prüfst du als der Benutzer des Skripts:

echo "Test" | mail -s "Test von nc-bisync" admin@example.com

Fehlt der Befehl mail, überspringt das Skript den Mailversand ohne Fehlermeldung.

Push-Nachricht (NTFY_URL). Dafür braucht der Server curl. Installiere die ntfy-App auf dem Handy und abonniere dort ein Topic. Auf dem öffentlichen Server ntfy.sh ist kein Konto nötig, dafür kann jeder mitlesen, der den Namen des Topics kennt. Wähle deshalb einen langen, zufälligen Namen, zum Beispiel https://ntfy.sh/nc-bisync-7f3k9x2q. Zum Test:

curl -d "Test von nc-bisync" https://ntfy.sh/nc-bisync-7f3k9x2q

Ein eigener ntfy-Server funktioniert genauso. Topics, die eine Anmeldung oder ein Zugriffstoken verlangen, unterstützt das Skript in der jetzigen Form nicht.

Verwendung im Alltag

Befehl Wann
nc-bisync.sh alle Paare abgleichen, ohne Archiv
nc-bisync.sh fotos dokumente nur die genannten Paare abgleichen
nc-bisync.sh --archiv projekte nachdem in projekte Dateien archiviert wurden
nc-bisync.sh --dry-run fotos vorher anzeigen, was passieren würde
nc-bisync.sh --archiv --force projekte wenn beim Archivieren die Löschgrenze angeschlagen hat
nc-bisync.sh --list konfigurierte Paare anzeigen

rclone-Optionen mit Wert gibst du immer in der Form --option=wert an, sonst hält das Skript den Wert für den Namen eines Paares.

Dateien archivieren

Verschiebe die Dateien innerhalb der Freigabe in den Unterordner archiv und starte dann den Abgleich für diese Freigabe:

nc-bisync.sh --archiv projekte

Das Skript gleicht zuerst das Archiv ab und erst danach den Rest der Freigabe. So liegen die Dateien schon im Archiv der Nextcloud, bevor sie dort aus dem Rest der Freigabe verschwinden. Schlägt der Archiv-Lauf fehl, wird der Rest der Freigabe gar nicht angefasst.

Verschiebst du sehr viele Dateien auf einmal, kann die Löschgrenze greifen. Prüfe dann kurz das Log und starte mit --force.

Ein Archiv richtest du nachträglich ein, indem du lokal den Ordner archiv anlegst und einmal nc-bisync.sh --init NAME ausführst.

Einzelne Unterordner als eigenes Paar

Wird eine Freigabe zu groß für häufige Läufe, kann ein Unterordner ein eigenes Paar bekommen:

"tango|/mnt/shares/projekte/Tango|nc:Projekte/Tango"

Das Skript schließt Tango dann im Paar projekte automatisch aus. Weil sich dadurch dessen Filter ändert, ist einmal nc-bisync.sh --init projekte tango nötig. Der Unterordner muss in der Nextcloud an der entsprechenden Stelle liegen, sonst bricht das Skript mit einer Meldung ab.

Wenn eine Benachrichtigung kommt

  • Resync nötig: Lies die Ursache im genannten Log nach. Danach behebt meist nc-bisync.sh --init NAME den Zustand, vorher am besten mit --dry-run.
  • Zu viele Löschungen: Prüfe, ob die Löschungen gewollt sind. Wenn ja, starte mit --force.
  • Zugriffsprüfung fehlgeschlagen: Eine RCLONE_TEST-Datei fehlt. Prüfe, ob der Pfad stimmt, die Nextcloud erreichbar ist und das Laufwerk gemountet ist.

Fehlerbehebung

Verbindungsabbrüche bei großen Übertragungen

Symptome. Vor allem beim Erstabgleich großer Datenmengen tauchen im Log bei einzelnen Dateien Fehler wie dieser auf:

ERROR : 2014/…/IMG_0929.PNG: Failed to copy: unchunked simple update failed: Put "https://…":
http2: Transport: cannot retry err [http2: Transport received Server's graceful shutdown GOAWAY]
after Request.Body was written; define Request.GetBody to avoid this error

Der Lauf bricht dabei nicht ab, sondern überträgt die übrigen Dateien weiter. Am Ende eines Erstabgleichs meldet bisync trotzdem Bisync aborted. Must run --resync to recover., denn beim --resync genügt schon eine einzige fehlgeschlagene Datei. In der Zusammenfassung stehen dann zum Beispiel 100 % übertragen, aber mehrere Fehler.

Was bei HTTP/2 nicht klappt. HTTP/2 schickt viele Anfragen gleichzeitig über eine einzige Verbindung. Der Server oder ein vorgeschalteter Proxy beendet diese Verbindung irgendwann geordnet mit einem GOAWAY, etwa nach einer festen Zahl von Anfragen oder bei einem Neustart. Anfragen, die noch nicht begonnen haben, kann der Client problemlos über eine neue Verbindung schicken. Bei Uploads, deren Daten schon unterwegs waren, gelingt das nicht: Der Dateiinhalt ist bereits abgeschickt und kann an dieser Stelle nicht ein zweites Mal gesendet werden. Die Datei schlägt fehl.

Was bei HTTP/1.1 anders ist. Hier läuft jede Anfrage über eine eigene Verbindung. Schließt der Server eine davon, betrifft das nur diese eine Übertragung, und rclone wiederholt sie mit seinen normalen Wiederholungsversuchen über eine neue Verbindung. Weil rclone ohnehin mehrere Dateien parallel überträgt, ist HTTP/1.1 in der Praxis kaum langsamer.

Workaround für einen einzelnen Lauf. Meist reicht es schon, den Lauf einfach zu wiederholen: Die Abbrüche treten nur sporadisch auf, und beim nächsten Versuch werden die fehlgeschlagenen Dateien in der Regel doch noch übertragen. Bereits übertragene Dateien werden dabei nur verglichen, nicht erneut hochgeladen. Andernfalls bleibt das Ausweichen auf HTTP/1.1. Alle Optionen, die das Skript nicht selbst kennt, reicht es an rclone weiter. So wiederholst du einen gescheiterten Erstabgleich mit HTTP/1.1:

nc-bisync.sh --init fotos --disable-http2

Dauerhaft abschalten. Jede rclone-Option lässt sich auch als Umgebungsvariable RCLONE_<OPTION> setzen. Trag dazu im Konfigurationsblock des Skripts diese Zeile ein:

export RCLONE_DISABLE_HTTP2=true

Damit nutzen alle rclone-Aufrufe des Skripts HTTP/1.1, auch die im Cronjob.

Grenzen

rclone bisync ist kein Backup. Der Abgleich überträgt auch versehentliche Änderungen, nur Massenlöschungen werden abgefangen. Verschlüsselt etwa Ransomware Dateien auf einem Laptop, landen sie über den Nextcloud-Client in der Nextcloud und per bisync auch auf dem Fileserver, denn dabei wird überschrieben, nicht gelöscht. Die überschriebenen Fassungen liegen dann zwar noch 30 Tage im Backup-Verzeichnis, den eigentlichen Schutz bilden aber die versionierten rsnapshot-Sicherungen und die Dateiversionen der Nextcloud. Die Aufbewahrungszeit sollte länger sein als die Zeit, bis man einen Schaden bemerkt.