"Backup zum Feierabend"

TL;DR

Backup zum festen Zeitpunkt funktioniert nicht regelmäßig? Eine Lösung dafür ist die automatische Datensicherung, wenn das System herunterfährt oder in den Ruhezustand (Hibernate) wechselt.

Über eine Systemd-Unit wird das Backup zum Feierabend einfach zum richtigen Zeitpunkt gestartet:

[Unit]
Description=Run backup before hibernate/poweroff
Before=systemd-hibernate.service
Before=systemd-poweroff.service
Before=systemd-halt.service

[Service]
Type=oneshot
ExecStart=<path to backup program>

[Install]
WantedBy=systemd-hibernate.service
WantedBy=systemd-poweroff.service
WantedBy=systemd-halt.service

Einleitung

Kernpunkt dieses kleinen Projekts ist nicht die Durchführung des Backups an sich, sondern die Wahl des richtigen Zeitpunkts für das Backup.

Aus meiner Erfahrung ist eine Datensicherung zu einem festen Zeitpunkt für PCs und Laptops unzuverlässig, da nicht sicher ist, dass das System zum entsprechenden Zeitpunkt aktiv ist.

Besser ist es die Daten zu sichern, wenn Daten verändert wurden und die Tätigkeit beendet ist - das "Backup zum Feierabend".

Dieses Dokument beschreibt einen alternativen Ansatz der Datensicherung beim Wechseln vom aktiven Zustand in einen Ruhemodus oder ausgeschalteten Zustand.

Dafür wird eine Systemd-Unit konfiguriert, die durch verschiedene Trigger automatisch gestartet wird und so alle Änderungen sichert, bevor das System in einen inaktiven Zustand wechselt.

Als Backupsoftware wird restic genutzt. Es kann auch jede andere Software genutzt werden, die die nachfolgenden Überlegungen unterstützt.

Das erste Vollbackup wird manuell durchgeführt. Alle nachfolgenden Backups sind inkrementelle Backups, die nur die Änderungen zur vorherigen Datensicherung aufzeichnen. Dieses Schema wird auch "Forever Incremental Backup" bezeichnet.

Aufgrund der Funktionsweise von restic und der eingebauten Deduplizierung, spiegelt jedes Backup den kompletten Stand wider.

Das Setup

Das erste Backup wird alle Daten lesen und in das Repository schreiben. In Abhängigkeit von der Datenmenge nimmt dieser Vorgang einige Zeit in Anspruch. Daher wird das erste Backup manuell ausgeführt und anschließend die Systemd-Unit aktiviert. Das verhindert ein scheinbares Hängen, während der PC herunterfährt oder in den Ruhezustand wechselt.

Bei größeren Änderungen ist ein manuelles Backup ebenfalls zu empfehlen.

Beim Aufruf durch Systemd führt das Backup-Skript lediglich ein Backup und keine weiteren Aktionen, wie zum Beispiel eine Prüfung des Repositories, durch. Das minimiert die Laufzeit des Backups und der PC wechselt schneller in den gewünschten Zustand.

Dagegen läuft restic.sh bei einem manuellen Start länger, da das Repository geprüft wird und dabei nicht mehr genutzte Daten wieder freigegeben d.h. gelöscht werden.

Eine Integritätsprüfung der Backupdaten ist im Skript vorgesehen aber nicht aktiviert, um die Laufzeit des Backups so kurz wie möglich zu halten.

Alte Backup-Stände werden ebenfalls nicht automatisch gelöscht. Eine entsprechende Prozedur ist durch den Nutzer selbst zu implementieren, zu testen und anschließend zu aktivieren. Im Skript gibt es Einstellungen, die diesen Vorgang unterstützen können.

Erfahrungswerte aus 69 Läufen über vier Wochen mit rund 1 TiB in 320.000 Dateien und einem DSL-Anschluss mit 50 MBit/s: Bei wenigen MiB Änderungen benötigt restic für das Backup 20 bis 40 Sekunden. Der gesamte Lauf der Systemd-Unit einschließlich Änderungsübersicht und Größenberechnung aller Buckets dauert 1 bis 2,5 Minuten. Größere Änderungen verlängern das Backup abhängig von der komprimiert hochgeladenen Datenmenge: 500 MiB benötigen gut 4 Minuten, 1,5 GiB etwa 11 Minuten.

Das Einrichten eines Repositories wird nicht in diesem Dokument beschrieben. Die Dokumentation von restic enthält eine ausführliche Beschreibung Preparing a new repository.

Anforderungen

  • aktuelle restic-Version, mindestens 0.17.0
  • xargs und jq installiert und über den PATH erreichbar
  • aws (AWS CLI) installiert und über den PATH erreichbar, um die Größe aller Buckets zu berechnen

Installation

  1. Annahmen für diese Installation

    • das Repository ist eingerichtet und konfiguriert. Der Zugang wurde erfolgreich getestet
    • das Skript zur Steuerung des Backups ist ~/bin/restic.sh
    • eine Kopie von restic wird in ~/bin/ installiert
    • die Datei mit den zu sichernden Basisverzeichnissen ist ~/bin/backup.incl
    • die Datei zum Ausschluss von Dateien und Verzeichnissen von der Sicherung ist ~/bin/backup.excl

    Die Annahmen können an die eigenen Bedürfnisse angepasst werden.

  2. Eigene Kopie von restic anlegen

     # cp -p <path to restic> ~/bin
     # chmod 700 ~/bin/restic
    
  3. Benötigte Konfigurationen und Skripte nach ~/bin kopieren

     # cp -p restic.sh ~/bin
     # chmod 700 ~/bin/restic.sh
     # cp -p backup.incl backup.excl ~/bin
     # chmod 600 ~/bin/backup.incl ~/bin/backup.excl
    
  4. Capabilities setzen, um restic ohne Root-Rechte ausführen und dennoch alle Dateien lesen zu können

     # ~/bin/restic.sh --setcap
    
  5. Konfiguration in ~/bin/backup.incl und ~/bin/backup.excl anpassen, um Dateien und Verzeichnisse in das Backup ein- und auszuschließen

     # $EDITOR ~/bin/backup.incl
     # $EDITOR ~/bin/backup.excl
    
  6. Backup-Skript ~/bin/restic.sh konfigurieren

     # $EDITOR ~/bin/restic.sh
    
  7. Erstes vollständiges Backup durchführen

     # ~/bin/restic.sh --backup
    
  8. Nutzer, Gruppe und Pfade in der Systemd-Unit anpassen

     # $EDITOR restic_before_shutdown.service
    
  9. Systemd-Unit installieren und aktivieren

     # sudo cp -p restic_before_shutdown.service /etc/systemd/system
     # sudo systemctl daemon-reload
     # sudo systemctl enable restic_before_shutdown
     # sudo systemctl status restic_before_shutdown
    
  10. Wechseln Sie in den Ruhezustand und zurück oder starten Sie neu, um restic.sh zu testen

Update

  1. Service-Unit restic_before_shutdown.service erneuern und aktivieren

  2. Backup-Skript restic.sh erneuern und konfigurieren

  3. restic aktualisieren und Capabilities setzen

     # cp -p <path to restic> ~/bin
     # chmod 700 ~/bin/restic
     # ~/bin/restic.sh --setcap
    
  4. Backup testen: restic.sh --help und restic.sh --backup

Anwendung

Syntax

$ ./restic.sh --help
Usage: restic.sh <option>
Perform a backup with restic.

If this is started from Systemd, fewer actions are executed than if the
script is started from the command line. This is intended to shorten the
runtime for the backup during the suspend process.

Actions if the backup is triggered by Systemd:
 CHECK BACKUP SHOWDELTA SHOWSIZEALLBUCKETS
Actions if the backup is not triggered by Systemd:
 CHECK BACKUP SHOWDELTA PRUNE SHOWSIZEALLBUCKETS

Options
=======
  -b|--backup    perform a backup

  -a|--read-all  read all packs to verify the overall integrity of all
                 backup data
                 action: READALL
  -c|--check     do a check if the restic binary is available, has the
                 right capabilities and the repository is accessible
                 action: CHECK
  -f|--forget    remove old snapshots
                 settings to keep snapshots: --keep-tag forever --keep-tag ewig --keep-within 30d --keep-daily 90 --keep-weekly 100 --keep-yearly 20 --prune
                 action: FORGET
  -p|--prune     removes data that is not referenced and therefore not
                 needed any more
                 action: PRUNE
  -s|--shell     open shell with restic settings for manual restic calls
  --setcap       set capabilities on the restic binary to read all files
                 (requires sudo)
                 action: SETCAP
  -u|--unlock    remove stale locks
  -h|--help      shows this message
  -v|--version   shows the version number of this script

Protokoll anzeigen

Das Protokoll der über Systemd gestarteten Backups lässt sich mit journalctl anzeigen:

# journalctl -u restic_before_shutdown.service

Okt 07 15:41:18 saturn bash[571703]: -= restic.sh - Backup with restic =-
Okt 07 15:41:18 saturn bash[571703]: -= Version 6, (c) 2023-2026 Carsten Grohmann, Lizenz: MIT =-
Okt 07 15:41:18 saturn bash[571703]: -= restic 0.19.1 compiled with go1.26.4 on linux/amd64 =-
Okt 07 15:41:18 saturn bash[571703]: Run script with these actions: CHECK BACKUP SHOWDELTA SHOWSIZEALLBUCKETS
Okt 07 15:41:18 saturn bash[571703]: Initial check ...
Okt 07 15:41:18 saturn bash[571703]: Restic binary /home/carsten/bin/restic found and executable
Okt 07 15:41:18 saturn bash[571703]: Correct file capabilities set on /home/carsten/bin/restic
Okt 07 15:41:19 saturn bash[571703]: Repository s3:https://<s3 host>/<repo> found and accessible
Okt 07 15:41:19 saturn bash[571703]: Start restic backup ...
Okt 07 15:41:19 saturn bash[571746]: open repository
Okt 07 15:41:20 saturn bash[571746]: using parent snapshot 33643f76
Okt 07 15:41:20 saturn bash[571746]: load index files
Okt 07 15:41:22 saturn bash[571746]: start scan on [/home /etc /root]
Okt 07 15:41:22 saturn bash[571746]: start backup on [/home /etc /root]
Okt 07 15:41:29 saturn bash[571746]: scan finished in 8.851s: 323442 files, 1.009 TiB
Okt 07 15:41:48 saturn bash[571746]: Files:          10 new,    20 changed, 323412 unmodified
Okt 07 15:41:48 saturn bash[571746]: Dirs:            4 new,    32 changed, 40826 unmodified
Okt 07 15:41:48 saturn bash[571746]: Data Blobs:     22 new
Okt 07 15:41:48 saturn bash[571746]: Tree Blobs:     35 new
Okt 07 15:41:48 saturn bash[571746]: Added to the repository: 2.355 MiB (447.162 KiB stored)
Okt 07 15:41:48 saturn bash[571746]: processed 323442 files, 1.009 TiB in 0:28
[...]
Okt 07 15:42:05 saturn bash[571772]: Files:          10 new,     2 removed,    17 changed
Okt 07 15:42:05 saturn bash[571772]: Dirs:            4 new,     1 removed
Okt 07 15:42:05 saturn bash[571772]: Others:          0 new,     0 removed
Okt 07 15:42:05 saturn bash[571772]: Data Blobs:     24 new,    16 removed
Okt 07 15:42:05 saturn bash[571772]: Tree Blobs:     35 new,    31 removed
Okt 07 15:42:05 saturn bash[571772]:   Added:   2.435 MiB
Okt 07 15:42:05 saturn bash[571772]:   Removed: 1.783 MiB
Okt 07 15:42:05 saturn bash[571703]: Show size of all buckets ...
Okt 07 15:42:22 saturn bash[571793]: Size of bucket <repo>:           961 GiB  changed: 2026-10-07 15:41:48
Okt 07 15:43:06 saturn bash[571793]: Size of bucket <other repo>:     343 GiB  changed: 2026-10-07 15:37:37
Okt 07 15:43:14 saturn bash[571793]:                                =========
Okt 07 15:43:14 saturn bash[571793]: Overall storage usage:          1305 GiB

Änderungsprotokoll

10. Oktober 2026 - Version 6

  • Mindestvoraussetzung: restic 0.17.0
  • Unveränderte Backups erzeugen keine Snapshots mehr
  • Buckets werden mit Größe und Zeitpunkt der letzten Änderung angezeigt
  • Capabilities setzen mit restic.sh --setcap
  • Kleine Korrekturen und Verbesserungen

19. Juli 2024 - Version 5

  • Umleitung der Ausgabe in eine Logdatei ist möglich
  • Funktionsvariablen als "local" deklarieren

30. März 2024 - Version 4

  • Berechnung der Größe aller Buckets hinzugefügt

14. Dezember 2023 - Version 3

  • Kommandozeilenoptionen für den Zugriff auf einzelne Funktionen hinzugefügt
  • Ausschlussmuster erweitert
  • Regeln zum Aufbewahren der Snapshots erweitert

25. Oktober 2023 - Version 2

  • Versionsnummer zum Skript hinzugefügt
  • Skriptname, Copyright/Lizenz und Versionsnummer beim Start anzeigen

20. Oktober 2023 - Version 1

  • Initiale Version

Projektseite und Feedback

Die Projektseite ist unter https://www.carstengrohmann.de/backupzumfeierabend.html zu finden.

Der Quellcode befindet sich unter https://sr.ht/~carstengrohmann/BackupZumFeierabend.

Kommentare, Vorschläge und Patches sind willkommen und erwünscht. Bitte mailen Sie mir.

Lizenz

Diese Software unterliegt der MIT-Lizenz.

Copyright (c) 2023-2026 Carsten Grohmann mail@carstengrohmann.de

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.