Das Programm »Restic« ist ein modernes Backup-Programm, welches als Speicherort sowohl lokale Verzeichnisse als auch per Netzwerk erreichbare Speicher (Online-Speicher) nutzen kann. Der Autor von »Restic« zeigt in anschaulicher Weise in zwei Videos viele Details zur Arbeitsweise seines Programms: »FOSDEM 2015« (2015-01-28) und »CCCCologne« (2016-01-29).
Im Folgenden soll gezeigt werden, wie man unter Linux automatische Backups mit »Restic« einrichten kann. Als Speicherort wird per WebDAV-Protokoll erreichbarer Online-Speicher genutzt. Sinngemäß können die Hinweise aber auch auf andere Netzwerkprotokolle übertragen werden. Getestet wurde unter »openSUSE« und »Linux Mint« (»Ubuntu«), wobei aber auch alle anderen systemd-basierten Linux-Distributionen in derselben Art oder mit geringfügigen Änderungen geeignet sind.
openSUSE | Ubuntu, Linux Mint | |
---|---|---|
sudo zypper up |
sudo apt update |
|
sudo zypper in restic fuse |
sudo apt install restic fuse |
Ab Version »0.9.3« kann man »Restic« auch unabhängig vom Paketmanager der Linux-Distribution per
sudo restic self-update
auf den aktuellen Stand bringen.
»Restic« unterstützt nicht selbst den Zugriff auf Online-Speicher per WebDAV-Protokoll, kann aber die Fähigkeiten des Programms »Rclone« dafür nutzen. »Rclone« bietet sehr einfach die Möglichkeit, auf eine Vielzahl von Online-Speicher zuzugreifen.
openSUSE | Ubuntu, Linux Mint | |
---|---|---|
sudo zypper in rclone |
sudo apt install rclone |
Per
sudo rclone selfupdate
kann »Rclone« auch unabhängig vom Paketmanager der Linux-Distribution auf den aktuellen Stand gebracht werden.
Um regelmäßig über das Ergebnis der Backup-Läufe informiert zu werden, muss ein geeignetes Programm zum Verschicken von E-Mails installiert werden. Dem gezielten Zugriff auf Informationen im json-Datenformat dient jq
.
openSUSE | Ubuntu, Linux Mint | |
---|---|---|
sudo zypper in msmtp jq |
sudo apt install msmtp jq |
-
~/.config/backup/backup-env.txt
RCLONE_CONFIG_MYGMX_TYPE=webdav RCLONE_CONFIG_MYGMX_URL="https://mediacenter.gmx.net" RCLONE_CONFIG_MYGMX_VENDOR=other RCLONE_CONFIG_MYGMX_USER='[email protected]' RCLONE_CONFIG_MYGMX_PASS='????????????????????????????????????????' RCLONE_TPSLIMIT=4 RCLONE_TPSLIMIT_BURST=10 RCLONE_RETRIES=100 RCLONE_LOW_LEVEL_RETRIES=100 RESTIC_REPOSITORY='rclone:MyGMX:backup' RESTIC_PASSWORD='??????????????' RESTIC_COMPRESSION=max MAIL_TO='[email protected]'
Erklärung: Die mit
RCLONE_CONFIG_
beginnenden Variablen definieren den Namen (»MyGMX«) sowie Art und Eigenschaften des per »Rclone« bereit gestellten Online-Speichers. Das fürRCLONE_CONFIG_MYGMX_PASS
angegebene Passwort ist die von »Rclone« benötigte »getarnte« Version des originalen Passworts, also ein Ergebnis des Aufrufsrclone obscure ORIGINALPASSWORT
. Man könnte statt derRCLONE_CONFIG_
-Variablen auch auf Definitionen aus der Rclone-Konfigurationsdatei (~/.config/rclone/rclone.conf
) zurückgreifen. So ergibt sich aber der Vorteil, sämtliche Konfigurationsangaben in einer einzigen Datei zusammenfassen zu können. Vorheriges Konfigurieren von »Rclone« könnte so völlig entfallen, wenn es nicht für andere Zwecke benötigt wird. Einige Netzwerkprotokolle (z.B.S3
) werden von »Restic« direkt unterstützt und würden keine Rclone-Definitionen benötigen. Weitere Hinweise zur allgemeinen Rclone-Nutzung finden sich hier.Die Variable
RESTIC_REPOSITORY
legt fest, wie »Restic« den Ort zum Speichern der Backups erreichen kann. Es handelt sich um das Verzeichnisbackup
auf dem per »Rclone« erreichbaren Online-Speicher mit Namen »MyGMX«, wie er gerade definiert wurde.RESTIC_PASSWORD
legt das zum Ver- und Entschlüsseln der Backups zu benutzende Passwort fest. Dieses Passwort sollte möglichst kompliziert sein und zusätzlich an einem sicheren Ort aufbewahrt werden.Tests ergaben, dass der WebDAV-Server des hier als Beispiel gewählten Online-Speichers gelegentlich Fehler der Art
CLIENT_USER has exceeded the limit of 15000.0 requests per Hours for this client.: 429 Too Many Requests
meldete. Das Rclone-Flag
--tmplimit
lässt sich verwenden, um diesen Fehler zu unterdrücken. Die UmgebungsvariableRCLONE_TPSLIMIT
ist äquivalent zu diesem Flag. Der Wert »4« ergibt sich aus 15000 / 1h = 15000 / 3600s ≈ 4/s. Die aufRETRIES
endenden Angaben dienen ebenfalls der besseren Stabilität der Übertragung.Mit
chmod go-rw ~/.config/backup/backup-env.txt
sollte die Konfigurationsdatei als nur für ihren Eigentümer lesbar gekennzeichnet werden.
-
~/.config/backup/backup-include.txt
/home/mustermann
Erklärung: Angabe der Verzeichnisse (eins pro Zeile), die von »Restic« gesichert werden sollen. In diesem Beispiel wird das gesamte HOME-Verzeichnis ausgewählt.
-
~/.config/backup/backup-exclude.txt
/home/mustermann/.cache /home/mustermann/.mozilla /home/mustermann/.local/share/Trash /home/mustermann/.thunderbird /home/mustermann/Download /home/mustermann/tmp /home/mustermann/VirtualBox VMs /home/mustermann/logs
Erklärung: Beispielhafte Angabe der Verzeichnisse (eins pro Zeile), die von »Restic« von der Sicherung ausgenommen werden sollen. Es ist zu beachten, dass Quotes anders als beim Kommando-Interpreter relevant sind, hier also im Allgemeinen vermieden werden müssen.
-
~/.config/systemd/user/backup.timer
[Unit] Description=Backup (Timer) [Timer] OnCalendar=19:30 Persistent=false [Install] WantedBy=timers.target
Erklärung: Es wird angenommen, dass einmal täglich von »Restic« ein Backup-Lauf gestartet werden soll.
OnCalendar
bestimmt den Zeitpunkt (siehe auch: »Time and date specifications«). Die AngabePersistent=false
sorgt dafür, dass ein versäumter Aufruf vonbackup.service
nach Wiedereinschalten des Rechners nicht nachgeholt wird, d.h. der nächste Backup-Lauf findet erst zum nächsten regulären Zeitpunkt statt. -
~/.config/systemd/user/backup.service
[Unit] Description=Restic backup -- service (%H) Documentation=https://restic.readthedocs.io/en/latest/ [Service] Type=oneshot Nice=15 IOSchedulingClass=best-effort IOSchedulingPriority=7 EnvironmentFile=-/etc/environment EnvironmentFile=%E/backup/backup-env.txt # ExecStartPre=/bin/bash -lc "restic --no-lock unlock --remove-all --cleanup-cache" # ExecStart=/usr/bin/systemd-cat -- echo '*** RESTIC BACKUP (begin) ***' ExecStart=/bin/bash -lc "restic backup \ --files-from %E/backup/backup-include.txt \ --exclude-file %E/backup/backup-exclude.txt \ --one-file-system --exclude-caches || ( e=$?; [ $e -eq 3 ] || exit $e )" # ignore "error 3" (some source data could not be read) ExecStart=/usr/bin/systemd-cat -- echo '*** RESTIC BACKUP (end) ***' # ExecStopPost=/bin/bash -lc "restic --no-lock unlock --remove-all --cleanup-cache" # ExecStopPost=/usr/bin/systemd-cat -- echo '*** EMAIL (begin) ***' ExecStopPost=/bin/bash -lc 'backup-email.sh "%N"' ExecStopPost=/usr/bin/systemd-cat -- echo '*** EMAIL (end) ***'
Erklärung: backup.service
beinhaltet die Abläufe, die von backup.timer
zeitgesteuert gestartet werden. Mit Nice=15
und IOSchedulingClass
/IOSchedulingPriority
werden die Prozessprioritäten auf unterdurchschnittliche Werte gesenkt (siehe auch: man systemd.exec
). Der eigentliche Backup-Aufruf geschieht in ExecStart
. In ExecStopPost
wird eine Benachrichtigungs-E-Mail versendet. backup.service
enthält, anders als viele der sonstigen .service
-Dateien, keinen [Install]
-Abschnitt, womit gewährleistet ist, dass ausschließlich die Angaben in backup.timer
für den Prozess-Start verantwortlich sind.
-
~/.config/systemd/user/backup-cleanup.timer
[Unit] Description=Restic backup (clean up snapshots) -- timer (%H) Documentation=https://restic.readthedocs.io/en/latest/ [Timer] OnCalendar=Mon *-*-* 19:30:00 Persistent=false [Install] WantedBy=timers.target
Erklärung: Es wird angenommen, dass einmal wöchentlich die von »Restic« gespeicherten Backups bereinigt werden sollen. Die Angabe
Persistent=false
sorgt dafür, dass ein versäumter Aufruf vonbackup-cleanup.service
nach Wiedereinschalten des Rechners nicht nachgeholt wird. -
~/.config/systemd/user/backup-cleanup.service
[Service] Type=oneshot Nice=15 IOSchedulingClass=best-effort IOSchedulingPriority=7 EnvironmentFile=-/etc/environment EnvironmentFile=%E/backup/backup-env.txt # ExecStartPre=/bin/bash -lc "restic --no-lock unlock --remove-all --cleanup-cache" # ExecStart=/usr/bin/systemd-cat -- echo '*** RESTIC FORGET / PRUNE (begin) ***' ExecStart=/bin/bash -lc "restic forget --compact --prune --max-unused 10% \ --tag 'timer' --keep-daily 7 --keep-weekly 4 --keep-monthly 12" ExecStart=/usr/bin/systemd-cat -- echo '*** RESTIC FORGET / PRUNE (end) ***' # ExecStart=/usr/bin/systemd-cat -- echo '*** RESTIC CHECK (begin) ***' ExecStart=/bin/bash -lc "restic check" ExecStart=/usr/bin/systemd-cat -- echo '*** RESTIC CHECK (end) ***' # ExecStart=/usr/bin/systemd-cat -- echo '*** CLEAN TRASH (begin) ***' ExecStart=/bin/bash -lc "rclone cleanup $REMOTE_REPOSITORY --verbose" ExecStart=/usr/bin/systemd-cat -- echo '*** CLEAN TRASH (end) ***' # ExecStopPost=/bin/bash -lc "restic --no-lock unlock --remove-all --cleanup-cache" # ExecStopPost=/usr/bin/systemd-cat -- echo '*** EMAIL (begin) ***' ExecStopPost=/bin/bash -lc 'backup-cleanup-email.sh "%N"' ExecStopPost=/usr/bin/systemd-cat -- echo '*** EMAIL (end) ***'
Erklärung:
backup-cleanup.service
beinhaltet die Abläufe, die vonbackup-cleanup.timer
zeitgesteuert gestartet werden. Es werden ältere Backups nach einer sinnvollen Strategie gelöscht. Die Angaben--keep-daily 7
,--keep-weekly 4
und--keep-monthly 12
haben folgende Bedeutung: Hebe monatlich ein Backup 12 Monate rückwirkend auf und hebe wöchentlich ein Backup 4 Wochen rückwirkend auf und hebe täglich ein Backup 7 Tage rückwirkend auf. Die AngabeAfter=backup.service
gewährleistet, dass »backup-cleanup« zwar entsprechend des inbackup-cleanup.timer
eingetragenen Zeitpunkts zum Start vorgesehen wird, aber tatsächlich erst gestartet wird, wenn der Prozessbackup.service
beendet wurde. Dazu ist die AngabeType=oneshot
inbackup.service
zwingend.backup-cleanup.service
enthält, anders als viele der sonstigen.service
-Dateien, keinen[Install]
-Abschnitt, womit gewährleistet ist, dass ausschließlich die Angaben inbackup-cleanup.timer
für den Prozess-Start verantwortlich sind. -
~/.msmtprc
defaults port 465 # Always use TLS. tls on tls_starttls off set_from_header on account gmx host mail.gmx.de # Envelope-from address from [email protected] add_missing_date_header on add_missing_from_header on auth on user [email protected] password "???????????????" account default: gmx
Erklärung: Enthält Angaben zu einem beispielhaften E-Mail-Account (E-Mail-Provider »GMX«). Das E-Mail-Programm
msmtp
greift auf diese Informationen zu. -
~/.local/bin/backup-email.sh
#!/bin/bash # $1 = Unit (short) # Rolf Niepraschk, 2024-12-11 if [ -z ${MAIL_TO} ]; then exit 0; fi HOST=$(hostname) SNAPSHOT=$(restic snapshots --host ${HOST} --json latest 2>/dev/null) LAST=$(echo ${SNAPSHOT} | jq -r '.[-1].id') PREV=$(echo ${SNAPSHOT} | jq -r '.[-1].parent') if [ ${PREV} = 'null' ]; then PREV=${LAST}; fi InvocationID=$(systemctl show --property=InvocationID --value --user $1.service) MESSAGE1=$(journalctl --quiet _SYSTEMD_INVOCATION_ID=${InvocationID}) MESSAGE2=$(restic diff ${PREV} ${LAST} 2>/dev/null) if [ ${SERVICE_RESULT} == "success" ]; then SUBJECT="Success: $1 (${HOST})" elif [ ${SERVICE_RESULT} == "exit-code" ]; then SUBJECT="Error ${EXIT_STATUS}: $1 (${HOST})" else SUBJECT="${SERVICE_RESULT}: $1 (${HOST})" fi cat <<EOF | msmtp -t > /dev/null \ To: ${MAIL_TO} Subject: ${SUBJECT} Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit MIME-Version: 1.0 ${MESSAGE1} ${MESSAGE2} EOF exit 0
Das Skript muss ausführbar gemacht werden:
chmod ugo+x ~/.local/bin/backup-email.sh
Erklärung: Wird von
backup.service
genutzt, um im Erfolgsfall wie auch im Fehlerfall eine E-Mail mit einem Bericht zu dem Systemd-Aufruf zu verschicken. -
~/.local/bin/backup-cleanup-email.sh
#!/bin/bash # $1 = Unit (short) HOST=$(hostname) InvocationID=$(systemctl show --property=InvocationID --value --user $1.service) MESSAGE=$(journalctl --quiet _SYSTEMD_INVOCATION_ID=${InvocationID}) if [ ${SERVICE_RESULT} == "success" ]; then SUBJECT="Success: $1 (${HOST})" elif [ ${SERVICE_RESULT} == "exit-code" ]; then SUBJECT="Error ${EXIT_STATUS}: $1 (${HOST})" else SUBJECT="${SERVICE_RESULT}: $1 (${HOST})" fi cat <<EOF | msmtp -t > /dev/null \ To: ${MAIL_TO} Subject: ${SUBJECT} Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: Quoted-Printable Content-Encoding: UTF8 MIME-Version: 1.0 ${MESSAGE} EOF exit 0
Das Skript muss ausführbar gemacht werden:
chmod ugo+x ~/.local/bin/backup-cleanup-email.sh
Erklärung: Wird von
backup-cleanup.service
genutzt, um im Erfolgsfall wie auch im Fehlerfall eine E-Mail mit einem Bericht zu dem Systemd-Aufruf zu verschicken.Mit
( set -a ; source ~/.config/backup/backup-env.txt; \ ~/.config/systemd/user/backup-email.sh backup ) ( set -a ; source ~/.config/backup/backup-env.txt; \ ~/.config/systemd/user/backup-cleanup-email.sh backup-cleanup )
lässt sich das Funktionieren der E-Mail-Benachrichtigungen testen. Misslingt das E-Mail-Verschicken, müssen ggf. die Angaben in
~/.msmtprc
angepasst werden. Soll das Verschicken von E-Mails verhindert werden, muss in~/.config/backup/backup-env.txt
der VariablenMAIL_TO
ein Leerstring zugewiesen oder die Zeile ganz gelöscht werden.
( set -a ; source ~/.config/backup/backup-env.txt; rclone mkdir MyGMX:backup )
Der folgende Aufruf
( set -a ; source ~/.config/backup/backup-env.txt; restic init )
ist einmalig nötig, um die Dateistruktur zur Aufnahme der Backups anzulegen.
Die folgenden Aufrufe starten die Systemd-Timer und legen fest, dass sie nach jedem Einloggen automatisch gestartet werden:
systemctl --user enable backup.timer
systemctl --user start backup.timer
systemctl --user enable backup-cleanup.timer
systemctl --user start backup-cleanup.timer
Mit
systemctl --user list-timers
kann überprüft werden, ob und wann die neu gestarteten Timer ihre nächste Aktion ausführen werden.
Unabhängig von dem automatischen Ablauf, kann ein einzelner Backup-Lauf folgendermaßen gestartet werden:
systemctl --user start backup.service
Dies empfiehlt sich insbesondere beim ersten Backup-Lauf, der naturgemäß relativ lange dauert. In einem zweiten Terminal-Fenster kann per
journalctl -f --user-unit backup.service
der Ablauf beobachtet werden. Ein erfolgreicher Backup-Lauf beginnt mit »Starting Backup
« und endet mit »Finished Backup
«. Die Hinweise
ERROR : index: error listing: directory not found
ERROR : snapshots: error listing: directory not found
beim ersten Backup-Lauf können ignoriert werden. Die Ursache ist die noch unvollständige Datei-Struktur unterhalb des Zielverzeichnisses.
Der Aufruf
( set -a ; source ~/.config/backup/backup-env.txt; restic snapshots --no-lock --compact )
zeigt eine Liste der Einzel-Backups (auch »snapshots« genannt).
Mit Anlegen der Datei ~/.config/systemd/user/backup-mount.service
folgenden Inhalts
[Unit]
Description=Mounting the backup
Documentation=https://restic.readthedocs.io/en/latest/
[Service]
Type=simple
Environment=mp="%h/mnt/backup"
EnvironmentFile=%h/.config/backup/backup-env.txt
ExecStartPre=/bin/bash -c 'mkdir -p "$mp"'
ExecStart=/bin/bash -lc 'if $(mountpoint -q "$mp"); then true; else \
restic mount "$mp"; fi'
ExecStop=/bin/bash -c 'if ! $(mountpoint -q "$mp"); then true; else \
fusermount -zu "$mp"; fi'
[Install]
WantedBy=default.target
und durch die Aufrufe
systemctl --user enable backup-mount.service
systemctl --user start backup-mount.service
werden die entschlüsselten Backups über ~/mnt/backup
sofort und nach jedem neuen Einloggen automatisch zugänglich. Unabhängig davon kann der Mount-Prozess per
systemctl --user stop backup-mount.service
beendet werden.
Sollen nur einzelne Dateien aus dem letzten oder einem früheren Backup wiederhergestellt werden, ist der Zugang über ~/mnt/backup
gut geeignet. Will man dagegen den gesamten Inhalt wiederherstellen, weil z.B. die Festplatte mit dem HOME-Verzeichnis defekt ist, geht man folgendermaßen vor:
( set -a ; source ~/.config/backup/backup-env.txt; \
restic restore latest --target )
Es wird davon ausgegangen, dass das HOME-Verzeichnis auf der neuen Festplatten nahezu leer neu angelegt wurde und komplett durch die im zuletzt erzeugten Backup gespeicherten Daten ersetzt werden soll. Der gezeigte Aufruf setzt natürlich voraus, dass die genutzte Datei backup-env.txt
bereits vorhanden ist. Es ist daher nötig, sie oder besser gleich das gesamte Verzeichnis ~/.config
unabhängig von den Backups an einem sicheren Ort zu speichern und vor dem Restore-Aufruf wiederherzustellen.
Soll, anders als hier gezeigt, die System-Installation des Rechners als Backups gesichert werden, müssen die gezeigten Abläufe mit Root-Rechten gestartet werden, d.h. --user
muss bei den systemctl-Aufrufen entfallen und die Systemd-Dateien müssen an andere Plätze kopiert werden.
Weitergehende Hinweise zu »Restic« findet man hier.
Ein Artikel im »Fedora Magazine« unter dem Titel »Automate backups with restic and systemd« behandelt das hier dargestellte Thema in ähnlicher Weise.
Rolf Niepraschk, 12/2024, Lizenz: MIT (siehe Quelltext dieser Datei)
Vielen Dank für die Hinweise.
Zu
.mailrc
: Ich habe den Text oben korrigiert. Ich selbst verwende allerdings jetzt stattmailx
msmtp
, wobei mir der Grund der Änderung gar nicht mehr einfällt. Vielleicht war es wegen der besseren Verfügbarkeit auf unterschiedlichen Linux-Systemen. Zusätzlich habe ich auch noch die beiden E-Mail-Skripte angepasst. Beispielsweise wird jetztjournalctl
stattsystemctl --user status
verwendet und sichergestellt, dass sämtliche Informationen des betreffenden Systemd-Laufes ausgegeben werden (wichtig, wenn sich das Backup über Mitternacht hinzieht).Die Tests zu den E-Mail-Skripten sind tatsächlich falsch. Allerdings funktionieren die von Dir korrigierten Aufrufe bei mir auch nicht, obwohl sie es früher taten. Keine Ahnung, was da los ist. Mittlerweile verwende ich dafür und für die anderen Tests nicht mehr
eval
sondern mache es robuster so:Vorerst habe ich den Text oben, so wie von Dir angegeben, korrigiert.
Ich müsste eigentlich den ganzen Text auf den neuesten Stand bringen. Mal sehen.
Rolf