(Picture by Martin
Spiske)
Beginnen wir mit der guten Reihe Backups. Es gibt ja die Regel:
Kein Backup, kein Mitleid
Kein Backup-Werkzeug ist perfekt für alles. Ich versuche mal verschiedene Techniken für Backups zu zeigen. Jeder muß für sich entscheiden, ob er und wie er eine Technik einsetzt. Ich selbst mische die verschiedensten Methoden, wie Syncthing, btrbk, restic, git-Annex. Meine Strategien, was wo hingespeichert wird, sind dementsprechend auch relativ flexibel.
Heute beginne ich mit restic. Hier handelt es sich eher um eine klassische Backup-Lösung. Das Backup wird in einem Repository abgelegt. Dies kann eine lokale Directory sein oder remote abgelegt werden. Hier gibt es verschiedenste Methoden, wie sftp, ein REST-Server oder Wolkenstorages, wie S3, minio usw.
Backups werden in Snapshots gespeichert, die dann per Hostname, Tags usw. organisiert sind. Snapshots sind incrementell, zudem werden die Dateien dedupliziert (indem sie im Repository mit eineindeutiger SHA-Prüfsumme weggespeichert werden). Ein Snapshot muß nicht unbedingt eine Directory sein, man kann auch Daten per Unix-Pipe wegspeichern. Damit ist es möglich, direkt einen Datenbank-Dump in einen Snapshot zu pumpen.
Restores funktionieren z. B. über eine per fuser eingespiegelte Directory oder mit gezieltem Download.
Ein Beispielszenario
Nehmen wir an, wir haben eine Maschine backup, die die Backups
halten soll. Diese ist per ssh erreichbar und stellt eine
r/w-Directory /srv/restic-repo zur Verfügung.
Initialisierung
Nun kann man ein Repository folgendermaßen inititalisieren:
$ restic -r sftp:user@backup:/srv/restic-repo init
enter password for new backend:
enter password again:
created restic backend f1c6108821 at sftp:user@backup:/srv/restic-repo
Please note that knowledge of your password is required to access the repository.
Losing your password means that your data is irrecoverably lost.
Das Backend-Paßwort wird zur Verschlüsselung des Repositories auf dem Server verwendet. Auch für die Schlüsselverwaltung gibt es natürlich Funktionalitäten, auf die ich hier mal nicht eingehe.
Backup
Machen wir einfach mal ein Backup, auf einer Maschine:
$ restic -r sftp:user@backup:/srv/restic-repo --verbose backup ~/work
open repository
enter password for repository:
password is correct
lock repository
load index files
start scan
start backup
scan finished in 1.837s
processed 1.720 GiB in 0:12
Files: 5307 new, 0 changed, 0 unmodified
Dirs: 1867 new, 0 changed, 0 unmodified
Added: 1.200 GiB
snapshot 40dc1520 saved
Hat der Backup funktioniert?
$ restic -r sftp:user@backup:/srv/restic-repo snapshots
enter password for repository:
ID Date Host Tags Directory
----------------------------------------------------------------------
40dc1520 2015-05-08 21:38:30 kasimir /home/user/work
Macht man nun kurz darauf erneut einen Backup…
$ restic -r sftp:user@backup:/srv/restic-repo --verbose ~/work
open repository
enter password for repository:
password is correct
lock repository
load index files
using parent snapshot d875ae93
start scan
start backup
scan finished in 1.881s
processed 1.720 GiB in 0:03
Files: 0 new, 0 changed, 5307 unmodified
Dirs: 0 new, 0 changed, 1867 unmodified
Added: 0 B
snapshot 79766175 saved
… geht das wesentlich schneller und man sieht, daß in Wirklichkeit keine neuen Daten übertragen wurden. Hier greift das incrementell und deduplizierend konzipierte System. Trotzdem sehen wir nun zwei Snapshots:
$ restic -r sftp:user@backup:/srv/restic-repo snapshots
enter password for repository:
ID Date Host Tags Directory
----------------------------------------------------------------------
40dc1520 2015-05-08 21:38:30 kasimir /home/user/work
79766175 2015-05-08 21:40:19 kasimir /home/user/work
Man kann diese nun auch vergleichen (hier mal als Beispiel ein weiterer Backup, in dem sich was getan hat):
$ restic -r sftp:user@backup://srv/restic-repo diff 40dc1520 2ab627a6
password is correct
comparing snapshot 40dc1520 to 2ab627a6:
C /home/user/work/cmd_diff.go
+ /home/user/work/foo
C /home/user/work/bla
Files: 0 new, 0 removed, 2 changed
Dirs: 1 new, 0 removed
Others: 0 new, 0 removed
Data Blobs: 14 new, 15 removed
Tree Blobs: 2 new, 1 removed
Added: 16.403 MiB
Removed: 16.402 MiB
Restore
Backup ist ja immer nett, netter ist aber, wenn man einen Restore anschmeißen kann und der auch funktioniert. Hier also Restore-Strategien.
Zunächst die klassische Methode: Kopieren des Snapshots.
$ restic -r sftp:user@backup:/srv/restic-repo restore 79766175 --target /tmp/restore-work
enter password for repository:
restoring <Snapshot of [/home/user/work] at 2015-05-08 21:40:19.884408621 +0200 CEST> to /tmp/restore-work
Eine viel schickere Methode ist aber der Mount. Hier wird ein Snapshot oder das Repository in eine Directory gemountet:
$ mkdir /mnt/restic
$ restic -r sctp:user@backup:/srv/restic-repo mount /mnt/restic
Now serving /srv/restic-repo at /mnt/restic
When finished, quit with Ctrl-c or umount the mountpoint.
nun kann man mit einem anderen Terminal durch die Struktur des Repos wandern, bis man obigen Mount mit Ctrl-c beendet.
Vereinfachungen
In unserem Fall wurden bei den Aufrufen immer komplett alle Parameter mitgegeben. Man kann allerdings hier etwas einsparen:
- Setzen der Environment-Variable
RESTIC_REPOSITORYersetzt den Parameter-r. - Das Backend-Paßwort kann man ebenfalls in eine Datei auslagern und
diese per
RESTIC_PASSWORD_FILEdem System bekannt machen. sshsollte man mit öffentlichen Schlüsseln bearbeiten, damit ist man in der Lage, ohne jegliche Paßworte aufs System zugreifen zu können.- Man kann zudem die Backups von einem technischen User durchführen
lassen. Damit die Permissions funktionieren kann man diesem User
per
setcapdie nötigen Rechte geben.
Wo einsetzen?
In meinem Fall sind alle wichtigen Maschinen per btrbk gesichert. Aber es gibt Ausnahmen:
- ein Unifi-Controller auf Raspian-Basis mit ext4-Filesystem
- Datenbankbackups
- Smartphones (sic, geht mit dem richtigen Betriebsystem)
Raspian-System-Backup
hier habe ich im /etc/cron.d/backup eine Anweisung für den Backup
und eine für das Aufräumen alter Sachen eingebaut:
10 3 * * * root restic -p ~/.restic -r sftp:user@backup:/srv/restic-repo backup --exclude "/dev" --exclude "/proc" --exclude "/sys" --exclude "/tmp" --tag wlc -q /
50 3 * * * root restic -p ~/.restic -r sftp:user@backup:/srv/restic-repo forget --keep-daily 3 --keep-weekly 5 --keep-monthly 2 --tag wlc -q
Hier sind natürlich die oben angegebenen Vereinfachungen mit
verwendet. Die keep--Optionen ermöglichen das Vorhalten der letzten
3 Tage, letzen 5 Wochen, letzten 2 Monaten.
Datenbank-Backup
Auch hier gibt es /etc/cron.d-Einträge. Grundsätzlich wird hier der
Datenbankdump über einen Pipe in den restic-Befehl gegeben. Beispiel
MySQL/MariaDB:
mysqldump -u dbuser --password=dbpassword datenbank | restic -p ~/.restic -r sftp:user@backup:/srv/restic-repo backup --tag db --tag mariadb -q --stdin --stdin-filename database.sql
Der Snapshot besteht dann nur aus einer einzelnen Datei, keiner Directory.
SailfishOS
restic ist in Go geschrieben und es existiert in diversen Linux-Distributionen. Allerdings gibt es auf Github auch schon fertige Binaries und das ist hier im Speziellen interessant:
SailfishOS kann in der neuesten Version das Home-Verzeichnis verschlüsseln. Das macht es aber nur rudimentär: Mit der Verschlüsselung wird die Homedirectory gelöscht. Das ist wie ein Datenverlust und man muß sein System neu aufsetzen. Natürlich kann man das Sailfish-Backup verwenden, aber bei mir ist das sogar gescheitert.
Also muß man das System vorher wegspeichern und da bietet sich natürlich an, auf ein funktionierendes Backup-System zu wechseln.
Bei den Restic-Releases gibt es auch eine linux_arm-Version. Die kann man auf
sein Device herunterladen, auspacken und als /usr/local/bin/restic
wegspeichern.
restic hat eine eigene Update-Funktionalität.
devel-su restic self-update
ermöglicht dann eine Aktualisierung.
Weitere Infos
Die gesamte Dokumentation von Restic kann man hier finden.