Backups mit Borg und Raspberry Pi

  Martin Brodbeck   Lesezeit: 10 Minuten  🗪 8 Kommentare

Der Raspberry Pi als Backup-Server mit nur sporadisch angegeschlossener Festplatte.

backups mit borg und raspberry pi

Wer einen Raspberry Pi am heimischen Router hängen hat, kann diesen ganz einfach als Backup-Server verwenden. Damit nicht zu viel Strom verschwendet wird, wird die Backup-HDD einfach bei Bedarf eingeschaltet und vom System automatisch ein- und ausgehängt.

Hardware

Am Raspberry Pi (in meinem Fall ein Pi 4, aber ein Pi 3 tut es sicherlich auch) ist über USB eine HDD-Dockingstation angeschlossen, die etwas an einen Toaster erinnert. Es ist ein Kästchen mit einem Schacht, in den man z. B. eine 3,5 Zoll Festplatte stecken kann.

Empfehlenswert ist, wenn der Raspberry Pi über ein Ethernetkabel am Router angeschlossen ist.

Betriebssystem

Auf dem Raspberry Pi kann man ein ganz normales Raspberry Pi OS installieren. Ich habe mich für das 64 Bit Raspberry Pi OS Lite entschieden. Zu installieren sind die Pakete borgbackup sowie autofs.

Automount

Wie erwähnt, soll die Backup-Platte nicht ständig in Betrieb sein. Dies würde nur unnötig Strom fressen. Auch wäre die Lärmbelästigung, je nach Festplatte und Standort, unter Umständen unangenehm. Was wir also brauchen, ist ein Mechanismus, der die Platte bei Bedarf ein- und auch wieder aushängt. An das Einschalten der HDD-Dockingstation muss man natürlich selbst denken. Das Paket autofs bietet uns genau diesen Mechanismus.

Zunächst erstellen wir uns das Basisverzeichnis für die Automounts:

mkdir /automnt

Anschließend erstellen wir eine autofs-Masterdatei (/etc/auto.master.d/automnt.autofs) mit folgendem Inhalt:

/automnt /etc/auto.automnt --timeout=10 --ghost

--timeout=10 gibt übrigens an, dass die Platte nach 10 Sekunden Inaktivität wieder ausgehängt werden soll.

Dazugehörig ist die Datei /etc/auto.automnt. In dieser Datei geben wir an, was und wie genau gemountet werden soll:

backup -fstype=ext4,sync :/dev/disk/by-label/Backup

Wenn also auf das Verzeichnis /automnt/backup zugegriffen wird, dann soll die Festplatte bzw. Partition mit dem Label „Backup“, auf der sich ein ext4-Dateisystem befindet, eingehängt werden. Je nach Bedarf können diese Parameter natürlich angepasst werden.

Ein systemctl reload autofs liest die Konfiguration ein.

Ist die Platte in Betrieb, kann man nun etwa als root in das backup-Verzeichnis wechseln, welches dann automatisch eingebunden wird:

cd /automnt/backup

Borg

Als „Besitzer“ für die Backups erstellen wir auf dem Pi einen Benutzer borg:

useradd -m -s /bin/bash borg

Diesem übereignen wir auch gleich das gerade gemountete Backup-Verzeichnis:

chown borg:borg /automnt/backup

Auf den Clients, also auf den Rechnern, für die wir ein Backup erstellen wollen, haben wir für den User root einen SSH-Key erstellt. Hier als Beispiel auf dem Rechner cerana:

[root@cerana ~]# ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa
Your public key has been saved in /root/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:IsWzqIEbmshxQsH2s/kTGL+3XhMGPyzj2P7Htk5jpBg root@cerana
The key's randomart image is:
+---[RSA 3072]----+
|.. |
| o. . |
|... +. |
|.. + o o+ |
|oo..X oES* . |
|+++* ++.* = |
|=.. ..o+ +.+ |
| +... ++. |
| ++o.+o. |
+----[SHA256]-----+

Den öffentlichen Schlüssel hiervon – den wir unter /root/.ssh/id_rsa.pub finden – hinterlegen wir wiederum auf dem Raspberry Pi im Home-Verzeichnis des Users borg. Das hat den Zweck, dass die Anmeldung am Backup-Server ohne Eingabe eines Passworts, das wir für den User borg übrigens gar nicht angelegt haben, funktioniert. Aus Sicherheitsgründen schränken wir die Rechte jedoch so ein, dass andere Aktionen, etwa auch der Zugriff auf fremde Borg-Repositories, nicht möglich sind. Das Hinterlegen des öffentlichen Schlüssels mit diesen Einschränkungen sieht dann in etwa so aus (Datei /home/borg/.ssh/authorized_keys auf dem Pi):

command="borg serve --restrict-to-path /automnt/backup/cerana",restrict ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDRaRQ75+zjEdOEiHdCDLsJfAomxEOc6WJGYybJ4R+OLjvA7xieRBZClgiuSF2k0V8PSCU+Ue52D121dp//weTdq2o2NCXBlDqFTBNbIwyoQoeO3x5/bu71ENtPofU5ICXcOgyWeKPtZTKZ1WszLHWfgTqRUQ2U+f6y3PKGpbC8bHa9JbGrYscvbyBoTpb/ax8nu4jK7mhLa/1JAeglQC0Hm+tOD4qzmd6+UzaeEQ6/y6JeVZLXbtdTL5Et+h6QhJbbDJPiz+hU0dunVfxH+CqUW9b7aKdmW2/2PEZRPzWn4FhfBxULF+dfZYdqIpne6voFYoOb7BNv/hNCGnkc1r9hqFoP/7h2nZZhXN8s6cJwdEBP8527TdHLPnVWqmRZRm73OU7I5NPjDcdCUHpkmuIhYirbynF3vdaMOpxK00uK1j79W8qU0XGLkXUd3eC9+KcxJHae7r0H+klGL0+H8iPLHiRNoUaF1N1umaPEqDC89+zfONXt4FtaVWRTDTpnTY8= root@cerana

(Falls man das Verzeichnis .ssh und/oder darin die Datei authorized_keys erstellt hat, ist wichtig, dass nur der User borg Schreib-/Lesezugriff darauf hat. Alle anderen müssen keine Berechtigungen haben.)

Als User borg erstellen wir nun das Backup-Repository für den Rechner cerana:

$ sudo su - borg
$ borg init -e repokey /automnt/backup/cerana
Enter new passphrase:
Enter same passphrase again:
[…]

Die Option -e repokey bewirkt, dass das Repository verschlüsselt wird. Wir vergeben dafür ein sicheres Passwort, das wir uns gut merken.

Was fehlt jetzt noch? Genau, ein Backup-Skript, das wir auf dem Rechner cerana und ggf. weiteren Backup-Kandidaten aufrufen können. Hier sind der Fantasie natürlich keine Grenzen gesetzt. Ich greife hierfür auf ein Skript von mir zurück, das sich bewährt hat und den Vorteil von Snapshots auf Systemen mit Btrfs nutzt. Es nimmt an, dass das System sowie /home in separaten Subvolumes liegen. Bei Fedora 38 etwa ist das standardmäßig der Fall. Mit dem Skript könnte man auch einfach auf eine lokal angeschlossene Festplatte Backups machen (Schalter -l). Außerdem muss man vorher die Verzeichnisse /.snapshot, /mnt/backup-system sowie /mnt/backup-home erstellen. Unschön, und beizeiten werde ich das mal ändern :)

#!/usr/bin/env bash

# some helpers and error handling:
info() { printf "\n%s %s\n\n" "$( date )" "$*" >&2; }

backup_home() {
export SNAPSHOT_PATH=/.snapshots/home-$DATETIME
BACKUP_PATH=/mnt/backup-home

info "Starting backup of home dirs"
btrfs subvolume snapshot -r /home $SNAPSHOT_PATH
sync
mount --bind $SNAPSHOT_PATH $BACKUP_PATH

cd $BACKUP_PATH

# Backup the home directories into an archive named after
# the machine this script is currently running on:
borg create \
--progress \
--stats \
--compression zstd \
--exclude-caches \
--exclude '*/.cache/*' \
\
::"home-$DATETIME" \
* \

cd /tmp

#echo "Deleting snapshot"
umount $BACKUP_PATH
btrfs subvolume delete $SNAPSHOT_PATH

info "Pruning repository"

# Use the `prune` subcommand to maintain 7 daily, 4 weekly and 6 monthly
# archives of THIS home backup. The 'home-' prefix is very important to
# limit prune's operation to these archives and not apply to
# other archives also:

borg prune \
--list \
--glob-archives 'home-*' \
--keep-daily 7 \
--keep-weekly 2 \
--keep-monthly 3 \

}

backup_system() {
export SNAPSHOT_PATH=/.snapshots/system-$DATETIME
BACKUP_PATH=/mnt/backup-system

info "Starting backup of system dirs"
btrfs subvolume snapshot -r / $SNAPSHOT_PATH
sync
mount --bind $SNAPSHOT_PATH $BACKUP_PATH

cd $BACKUP_PATH

# Backup the system directories into an archive named after
# the machine this script is currently running on:
borg create \
--progress \
--stats \
--one-file-system \
--compression zstd \
--exclude-caches \
--exclude 'root/.cache' \
--exclude 'dev/*' \
--exclude 'proc/*' \
--exclude 'sys/*' \
--exclude 'var/run/*' \
--exclude 'var/cache/pacman/pkg/*' \
--exclude 'lost+found' \
\
::"system-$DATETIME" \
. /boot \

cd /tmp

#info "Deleting snapshot"
umount $BACKUP_PATH
btrfs subvolume delete $SNAPSHOT_PATH

info "Pruning repository"

# Use the `prune` subcommand to maintain 7 daily, 4 weekly and 6 monthly
# archives of THIS system backup. The 'system-' prefix is very important
# to limit prune's operation to these archives and not apply to
# other archives also:

borg prune \
--list \
--glob-archives 'system-*' \
--keep-daily 7 \
--keep-weekly 2 \
--keep-monthly 3
}

usage() {
echo "usage: backup_borg.sh [-l] [-t [home | system]] | [-h]"
}

## MAIN
# See the section "Passphrase notes" for more infos.
export BORG_PASSPHRASE='MeinSuperGeheimesPasswort'
DATETIME=`date +%Y%m%d-%H%M%S`
bkuptype=""
is_local=false
while [ "$1" != "" ]; do
case $1 in
-l | --local ) is_local=true
;;
-t | --type ) shift
bkuptype=$1
;;
-h | --help ) usage
exit
;;
* ) usage
exit 1
esac
shift
done

# Setting this, so the repo does not need to be given on the commandline:
if [ $is_local == true ]; then
export BORG_REPO=/run/media/$SUDO_USER/Backup/`hostname`
else
export BORG_REPO=ssh://borg@myraspi:22/automnt/backup/`hostname`
fi

if [ "$bkuptype" == "home" ]; then
backup_home
elif [ "$bkuptype" == "system" ]; then
backup_system
else
usage
fi

Das Skript wird also mittels sudo auf dem Client aufgerufen (etwa sudo backup_borg.sh -t home). Auf diesem muss natürlich auch borgbackup installiert sein. Das Backup sollte nun durchgeführt werden.

Weil die Backup-Festplatte zentral am Raspberry Pi hängt, könnte man parallel auch von weiteren Rechnern den Backup-Prozess starten. In jedem Fall erspart man sich das Umhertragen und Umstöpseln der Dockingstation. Denn es sind oft Kleinigkeiten, die einen vom Backup erstellen abhalten. Ist man mit der Prozedur fertig, kann man die Festplatte (nach kurzer Wartezeit) einfach ausschalten.

Quelle: https://borgbackup.readthedocs.io/en/stable/

Tags

backup, borg, raspberry

Jo
Geschrieben von Jo am 15. Mai 2023 um 12:08

Wäre es nicht schön, über die GPIOs die Stromversorgung der Festplatten anzusteuern, man könnte um den Automount sozusagen die Festplatten ein und nach dem umount wieder ausschalten.

Ulf
Geschrieben von Ulf am 15. Mai 2023 um 13:03

eine nette Idee, das geht bestimmt per Relais-Board ganz gut! Allerdings "sollte eigentlich" die Hardware der Festplatte (Dockingstation) dies übernehmen und im Tiefschlaf den Energieverbraucht stark reduzieren?

Mitleser
Geschrieben von Mitleser am 24. Mai 2023 um 06:30

Wenn die Docking-Station einen Einschalt-Schalter (und keinen Taster) hat, könnte man alternativ eine mit Tasmota betriebene WLAN-Steckdose vor ihr Netzteil hängen und diese per curl vom Raspi aus automatisch ein- und ausschalten.

Ulf
Geschrieben von Ulf am 15. Mai 2023 um 13:16

Danke Martin für den Anstoß endlich eine Backup-HDD an meinen Pi zu hängen.

Eine Frage dazu: systemD kann z.B. per "x-systemd.automount,x-systemd.idle-timeout=1min" (in fstab) Laufwerke/Partitionen automatisch mounten und wieder unmounten. Welche Vorteile habe ich durch Autofs? Danke im Voraus!

Gruß Ulf

Martin
Geschrieben von Martin am 15. Mai 2023 um 14:40

Hallo Ulf, es spricht gar nichts dagegen, das systemd machen zu lassen. Mit autofs hast du meines Wissens nach keine Vorteile – außer vielleicht, dass es auch auf Systemen funktioniert, die eben kein systemd verwenden. Wahrscheinlich bin ich einfach ein älteres Semester, sodass ich nicht an die modernere systemd-Variante gedacht habe. ;)

chris
Geschrieben von chris am 15. Mai 2023 um 17:13

Im Vergleich zu borg bietet restic die gleichen oder sogar bessere Features. Und ist extrem schnell. Wenn ich nicht rsync nutze, dann restic.

https://restic.net/

Martin
Geschrieben von Martin am 16. Mai 2023 um 07:35

Hast du damit Erfahrungen auf einem Raspberry Pi? Ich meine gelesen zu haben, dass restic relativ viel RAM benötigt, insbesondere im Vergleich zu borg.

Jane Doe
Geschrieben von Jane Doe am 15. Mai 2023 um 21:34

borgmatic wäre an dieser Stelle auch sehr zu empfehlen :)