Skip to content

Instantly share code, notes, and snippets.

@ginmaster
Forked from rolfn/restic.md
Created March 19, 2022 20:03
Show Gist options
  • Save ginmaster/ee245dfec24ec830eedb76f9a6cd3aaf to your computer and use it in GitHub Desktop.
Save ginmaster/ee245dfec24ec830eedb76f9a6cd3aaf to your computer and use it in GitHub Desktop.
Backup auf Cloud-Speicher mit »restic«

Automatische Backups auf Online-Speicher mit »Restic«

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 Speicherorte ü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.

Installation der benötigten Software

Restic

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.

Rclone

»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

E-Mail-Programm

Um regelmäßig über das Ergebnis der Backup-Abläufe informiert zu werden, muss ein geeignetes Programm zum Verschicken von E-Mails installiert werden.

openSUSE Ubuntu, Linux Mint
sudo zypper in mailx sudo apt install s-nail

Es muss sich um eine mailx-kompatible Programmversion, die die Option -S unterstützt, handeln.

WebDAV-Zugang konfigurieren

»Rclone« geeignet zu konfigurieren:

rclone config

e/n/d/r/c/s/q> n
name> GMX
Storage> 31
url> https://mediacenter.gmx.net
vendor> 4
user> [email protected]
y/g/n> y
password: XXXXXXXXXXXXXX
Confirm the password: XXXXXXXXXXXXXX
bearer_token>
y/n> n
y/e/d> y
e/n/d/r/c/s/q> q

Die zu beantwortenden Fragen sind weitgehend selbsterklärend. Als Name wurde hier »GMX« gewählt; andere Namen sind ebenso möglich. Als Ergebnis der Rclone-Konfiguration entsteht die Konfigurationsdatei ~/.config/rclone/rclone.conf. Weitere allgemeine Hinweise zur Rclone-Nutzung finden sich hier.

Anlegen und Editieren diverser Konfigurationsdateien

  • ~/.config/backup/backup-env.txt

    RESTIC_REPOSITORY='rclone:GMX:backup'
    RESTIC_PASSWORD='???????????'
    RCLONE_TPSLIMIT=4
    MAIL_TO='[email protected]'

    Erklärung: Die hier definierte Umgebungsvariable RESTIC_REPOSITORY legt fest, wie »Restic« das Verzeichnis zum Speichern der Backups erreichen kann. Es ist das Verzeichnis backup auf dem von »Rclone« erreichbaren Online-Speicher mit Namen »GMX«. RESTIC_PASSWORD legt das zum Ver- und Entschlüsseln zu benutzende Passwort fest. Dieses Passwort sollte möglichst kompliziert sein und zusätzlich an einem sicheren Ort aufbewahrt werden.

    Tests hatten ergeben, dass der Server des 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=xxx lässt sich verwenden, um diesen Fehler zu unterdrücken. Die Umgebungsvariable RCLONE_TPSLIMIT ist äquivalent zu diesem Flag. Der Wert »4« ergibt sich aus 15000 / 1h = 15000 / 3600s ≈ 4/s.

    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 als einzige Angabe das gesamte HOME-Verzeichnis ausgewählt.

  • ~/.config/backup/backup-exclude.txt

    /home/mustermann/.cache
    /home/mustermann/Download
    "/home/mustermann/VirtualBox VMs"
    

    Erklärung: Angabe der Verzeichnisse (eins pro Zeile), die von »Restic« von der Sicherung ausgenommen werden sollen.

  • ~/.config/systemd/user/backup.timer

    [Unit]
    Description=Backup (Timer)
    
    [Timer]
    OnCalendar=19:30
    Persistent=false
    
    [Install]
    WantedBy=default.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 Angabe Persistent=false sorgt dafür, dass ein versäumter Aufruf von backup.service nach Wiedereinschalten des Rechners nicht nachgeholt wird.

  • ~/.config/systemd/user/backup.service

    [Unit]
    Description=Backup on %H
    Documentation=https://restic.readthedocs.io/en/latest/
    
    [Service]
    Type=oneshot
    Nice=15
    EnvironmentFile=-/etc/environment
    EnvironmentFile=%h/.config/backup/backup-env.txt
    ExecStartPre=/bin/bash -lc "restic unlock --remove-all"
    ExecStart=/bin/bash -lc "restic backup \
      --files-from   %h/.config/backup/backup-include.txt \
      --exclude-file %h/.config/backup/backup-exclude.txt \
      --one-file-system --exclude-caches"
    ExecStopPost=/bin/bash -lc '%h/.config/systemd/user/backup-email.sh "%N"'
    ExecStopPost=/bin/bash -lc "restic unlock --remove-all"

    Erklärung: backup.service beinhaltet die Abläufe, die von backup.timer zeitgesteuert gestartet werden. Mit Nice=15 wird deren Priorität auf einen unterdurchschnittlichen Wert gesenkt (siehe auch: man nice). Der eigentliche Backup-Aufruf geschieht in ExecStart. In ExecStopPost wird die Benachrichtigungs-E-Mail versendet.

  • ~/.config/systemd/user/backup-forget-prune.timer

    [Unit]
    Description=Purge backup snapshots (Timer)
    
    [Timer]
    OnCalendar=Mon 20:00:00 
    Persistent=true  
    
    [Install]
    WantedBy=default.target
    

    Erklärung: Es wird angenommen, dass einmal wöchentlich die von »Restic« gespeicherten Backups bereinigt werden sollen. Die Angabe Persistent=true sorgt dafür, dass ein versäumter Aufruf von backup-forget-prune.service nach Wiedereinschalten des Rechners nachgeholt wird.

  • ~/.config/systemd/user/backup-forget-prune.service

    [Unit]
    Description=Forget/Prune/Check Snapshots (%H)
    Documentation=https://restic.readthedocs.io/en/latest/
    
    [Service]
    Type=oneshot
    Nice=15
    EnvironmentFile=-/etc/environment
    EnvironmentFile=%h/.config/backup/backup-env.txt
    ExecStart=/bin/bash -lc "restic unlock --remove-all"
    ExecStart=/bin/bash -lc "restic forget --prune \
      --keep-daily 7 --keep-weekly 4 --keep-monthly 12"
    ExecStart=/bin/bash -lc "restic unlock --remove-all"
    ExecStart=/bin/bash -lc "restic check"
    ExecStopPost=/bin/bash -lc '%h/.config/systemd/user/backup-forget-prune-email.sh "%N"'  
    ExecStopPost=/bin/bash -lc "restic unlock --remove-all"

    Erklärung: backup-forget-prune.service beinhaltet die Abläufe, die von backup-forget-prune.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.

  • ~/.mailrc

    account "backup" {
      localopts yes
      set from="Backup Daemon <[email protected]>"
      set smtp-auth=login
      set ssl-verify=ignore
      set smtp-use-starttls
      set smtp-auth-user="[email protected]"
      set smtp-auth-password="???????????"
      set smtp="smtps://mail.gmx.de:465"
    }

    Erklärung: Enthält Angaben zu dem E-Mail-Account, der unter dem Namen »backup« in den Skripten backup-email.sh und backup-forget-prune-email.sh verwendet wird.

  • ~/.config/systemd/user/backup-email.sh

    #!/bin/bash
    
    # $1 = Unit (short)
    
    if [ -z "${MAIL_TO}" ]; then exit 0; fi
    
    MAILX=$(which s-nail 2>/dev/null || which mailx) || exit $?
    
    HOST=$(hostname)
    
    LAST=$(restic snapshots --host $HOST --compact | tail -3 | head -1 | awk '{print $1}')
    PREV=$(restic snapshots --host $HOST --compact | tail -4 | head -1 | awk '{print $1}')
    if [[ ${PREV:0:1} == '-' ]]; then PREV=${LAST}; fi
    
    MESSAGE1=$(systemctl --user status -l -n 30 $1.service)
    MESSAGE2=$(restic diff "$PREV" "$LAST" | grep -ve '^.*\/\..*$') # ignore */.*/* 
    SUBJECT="$SERVICE_RESULT: $1 ($HOST)"
    
    cat <<EOF | $MAILX > /dev/null \
    -s "$SUBJECT" \
    -A backup \
    -S sendwait \
    "$MAIL_TO"
    $MESSAGE1
    ------------------------------------------------------------------------
    $MESSAGE2
    EOF
    
    # '-A  backup': defined in ~/.mailrc
    
    exit 0

    Zusätzlich muss das Skript ausführbar gemacht werden:

    chmod ugo+x  ~/.config/systemd/user/backup-email.sh

    Erklärung: Wird von backup.service genutzt, um im Erfolgsfall wie auch im Fehlerfall eine E-Mail mit einem Bericht zu verschicken.

  • ~/.config/systemd/user/backup-forget-prune-email.sh

    #!/bin/bash
    
    # $1 = Unit (short)
    
    if [ -z "${MAIL_TO}" ]; then exit 0; fi
    
    MAILX=$(which s-nail 2>/dev/null || which mailx) || exit $?
    
    HOST=$(hostname)
    
    MESSAGE=$(systemctl --user status -l -n 30 $1.service)
    SUBJECT="$SERVICE_RESULT: $1 ($HOST)"
    
    cat <<EOF | $MAILX > /dev/null \
    -s "$SUBJECT" \
    -A backup \
    -S sendwait \
    "$MAIL_TO"
    "$MESSAGE"
    EOF
    
    # '-A  backup': defined in ~/.mailrc
    
    exit 0

    Erklärung: Wird von backup-forget-prune.service genutzt, um im Erfolgsfall wie auch im Fehlerfall eine E-Mail mit einem Bericht zu verschicken.

    Mit

    eval $(cat $HOME/.config/backup/backup-env-vaclab.txt) \
      ./backup-email.sh backup
    
    eval $(cat $HOME/.config/backup/ ./backup-env-vaclab.txt) \
      ./backup-forget-prune-email.sh backup-forget-prune

    lässt sich das Funktionieren der E-Mail-Benachrichtigungen testen. Misslingt das E-Mail-Verschicken, müssen ggf. die Angaben in ~/.mailrc angepasst werden. Soll das Verschicken von E-Mails verhindert werden, muss in ~/.config/backup/backup-env.txt der Variablem MAIL_TO ein Leerstring zugewiesen oder die Zeile ganz gelöscht werden.

Ort der künftigen Backups auf Web-Speicher anlegen

rclone mkdir GMX:backup

Initialisierung der Backup-Struktur

Der folgende Aufruf

eval $(cat $HOME/.config/backup/backup-env.txt) restic init

ist einmalig nötig, um die Dateistruktur zur Aufnahme der Backups anzulegen.

Starten der nötigen Prozesse

Die folgenden Aufrufe starten die Systemd-Timer und legen fest, dass bei jedem Einloggen automatisch gestartet wird:

systemctl --user enable backup.timer
systemctl --user start  backup.timer
systemctl --user enable backup-forget-prune.timer
systemctl --user start  backup-forget-prune.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, welches 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 on ...« und endet mit »Started Backup on ...«. Die beiden Hinweise

ERROR : index: error listing: directory not found
ERROR : snapshots: error listing: directory not found

beim ersten Backup-Lauf können ignoriert werden, da die Datei-Struktur unterhalb des Zielverzeichnisses noch unvollständig ist.

Liste der bereits durchgeführten Backups

Der Aufruf

eval $(cat $HOME/.config/backup/backup-env.txt) restic snapshots 

zeigt eine Liste der Einzel-Backups (auch »snapshots« genannt).

Einbinden der entschlüsselten Backups ins Dateisystem

Mit Anlegen der Datei ~/.config/systemd/user/backup-mount.service folgenden Inhalts

[Unit]
Description=Mount 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.

Wiederherstellen des gesamten Inhalts eines Backups

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:

eval $(cat $HOME/.config/backup/backup-env.txt) restic restore latest --target /

Es wird davon ausgegangen, dass das HOME-Verzeichnis auf einer 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 unter Root-Rechten ablaufen, 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 sehr ähnlicher Weise.

Rolf Niepraschk (Neufassung, 11/2019 ff.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment