Hetzner S3 Bucket mit Restic und Rclone sichern
Kürzlich habe ich für einen Kunden den S3-Storage für eine Mastodon Instanz von Minio S3 auf ein extern gehostetes Hetzner S3 umgestellt. Das bringt auch eine Änderung bei der Datensicherung mit sich: Statt einfach nur das lokale Minio-Dateisystem zu sichern, muss sich für das Hetzner S3 Bucket eine andere Lösung überlegt werden. Im Folgenden will ich meine Lösung dafür aufzeigen.
Ein S3 Bucket in die Restic-Sicherung einbinden? Nicht so einfach!
Die Sicherung des Minio-Dateisystems war einfach und bequem. Restic musste an dieser Stelle nicht anders eingestellt werden, als für die übliche Datensicherung auf dem Linux-Server. Da Minio nicht mit einer Datenbank arbeitet, sondern einzig und allein mit dem Dateisystem, muss bei der Datensicherung über Restic nichts besonderes beachtet werden.
Da die Medien für die fragliche Mastodon Instanz nun aber nicht mehr lokal gehostet, sondern über ein Hetzner S3 Bucket bereitgestellt werden, stellt sich die Frage, wie mit dem Restic-basierten Backupmechanismus damit umgegangen werden soll. Eine Lösung könnte sein, das Produktiv-Bucket einfach in einem readonly-Modus zu einem weiteren Bucket zu kopieren und diese Buckets beispielsweise täglich zu synchronisieren. Allerdings hätte man damit keine inkrementellen, täglichen Sicherungen und kann höchstens auf den Stand des vorherigen Tages zurückspringen. Zudem arbeitet diese Lösung an Restic vorbei - ich hätte gerne alle Daten an einem Ort.
Das S3 Bucket mit rclone als virtuelles Dateisystem einbinden
Eine zweite Lösung kann sein, das Hetzner S3 Bucket mit einem Tool wie z.B. rclone lokal als virtuelles Filesystem zu mounten und dieses dann von dort zu sichern. Das mag umständlich und nicht sehr schnell sein, sorgt aber dafür, dass ich sämtliche Mediendateien in den gewohnten Restic Vorhaltezeiten gesichert habe und entsprechend auch wieder einfach herstellen kann, wenn es nötig sein sollte.
Mein Backup-Script sieht nun in etwa so aus:
#!/bin/bash
### Restic Passwort und Speicherort einlesen
source /opt/backup/resticenv.sh
### Mount S3 bucket
rclone mount \
--daemon \
--read-only \
--vfs-cache-mode full \
--vfs-cache-max-size 20G \
--vfs-cache-max-age 24h \
--dir-cache-time 72h \
--poll-interval 15s \
--checkers 128 \
--transfers 64 \
--multi-thread-streams 4 \
--timeout 1m \
--retries 10 \
--use-mmap \
--s3-chunk-size 64M \
hetzner-s3:mastodon-media /mnt/hetzner-s3/mastodon-media
### Restic ausführen
restic backup \
--exclude-file /opt/backup/exclude.list \
/home \
/etc \
/root \
/mnt/hetzner-s3/mastodon-media/accounts \
/mnt/hetzner-s3/mastodon-media/custom_emojis \
/mnt/hetzner-s3/mastodon-media/media_attachments \
/mnt/hetzner-s3/mastodon-media/site_uploads
# /mnt/hetzner-s3/mastodon-media/cache/accounts \
# /mnt/hetzner-s3/mastodon-media/cache/custom_emojis
restic forget --prune \
--keep-last 7 \
--keep-daily 14 \
--keep-weekly 8 \
--keep-monthly 4
restic check
# Unmount S3 bucket
fusermount -u /mnt/hetzner-s3/mastodon-media
Das rclone
Kommando zu Beginn des Scripts mountet das S3 bucket als virtuelles Dateisystem unter /mnt/hetzner-s3/mastodon-media
. Das restic backup
Kommando kann sich in diesem Verzeichnis bedienen und die Inhalte sichern. Weitere Einstellungen:
--daemon
sorgt dafür, dass rclone im Hintergrund läuft. Andernfalls würde das Script blockieren.--read-only
stellt sicher, dass das Mountpoint readonly ist, um das eingehängt S3 Bucket nicht zu verändern.--vfs-cache-max-size 20G
erlaubt rclone, bis zu 20 GB als Cache zu nutzen. Ich hoffe auf eine schnellere Ausführung.--checkers 128
erlaubt rclone bis zu 128 “checker” Instanzen. Das sind die Teile von rclone, die das Bucket nach Dateien durchsuchen. Die Anpassung hat in meinem Fall dafür gesorgt, dass die Sicherung durch restic deutlich schneller funktioniert hat als vorher. Allerdings sollte geprüft werden, ob so nicht die maximale Anzahl von Anfragen / Verbindungen an das Bucket überschritten werden kann, wenn nebenher auch noch andere Prozesse auf die Daten zugreifen.
Die beiden letzten Pfade unter cache/
habe ich vorerst ausgeklammert. Dort speichert Mastodon gecachte Versionen von Medien fremder Instanzen. Diese sollten nach dem Einspielen eines Backups eigentlich von Mastodon selbst wieder bei den fremden Instanzen angefragt werden, wenn sie fehlen sollten. Ich sichere sie deshalb aktuell nicht mit. Allerdings bleibt das noch ein Punkt, der noch weiter untersucht werden muss - denn in der Vergangenheit hat das erneute Herunterladen schon einmal Schwierigkeiten gemacht und nicht wie gedacht funktioniert. Insbesondere fehlende Avatare unter cache/accounts/
wären ärgerlich. Auf der anderen Seite ist die Datenmenge besonders groß und es tummeln sich u.U. hunderttausende kleinste Dateien in diesem Verzeichnis. Das ist für den Backupprozess besonders belastend und führt dazu, dass Backups sehr sehr lange dauern können.
Mit fusermount
wird das S3 Bucket nach dem Backup schließlich wieder ausgehängt.
Vorsicht mit alten Softwareversionen!
Ein Hinweis noch zu verwendeten Softwareversionen: Ich hatte anfangs während des Restic-Backups Fehlermeldungen wie
error: NodeFromFileInfo: xattr.list /mnt/hetzner-s3/7de24bcbedb9b634.jpg: input/output error
Die Lösung für meine Probleme bestand darin, sowohl Restic als auch Rclone auf aktuellere Versionen zu aktualisieren, welche von meiner Debian-Distribution noch nicht angeboten wurden. Siehe auch Thread im Restic Forum: “Creating a Restic backup of a S3 bucket”. Für restic Version 0.18.1 und Version 1.71.1 kann ich aber bestätigen, dass die Sicherungen auf die oben beschriebene Art und Weise funktionieren.
cache/
bringt den Mechanismus wegen der extrem vielen Dateien ans Limit. Es kann dann durchaus länger als 24 Stunden dauern, bis alle Dateien gesichert sind.