Server Backup mit rsnapshot
Posted on So 21 April 2019 in Computer & Electronics
Ich habe einen kleinen Home-Server. Der dient mir als Fileserver zum synchronisieren meines Laptops, dito für den Windows Rechner meiner Frau, er hostet ein paar Datenbanken (mariadb) und es läuft ein Wiki drauf. Die Spiegelung meiner Dateien via unison Synchronisation plus das RAID System im Server sind ja schon mal ein Sicherheitsfaktor, falls das Laptop geklaut wird oder schlapp macht, aber ein Backup ersetzt das nicht, denn wenn ich nicht rechtzeitig merke, wenn was schief läuft, dann synchronisiert sich das beschädigte System ggf. treu und brav, so dass dann auch die Kopie auf dem Server in Eimer ist. Auch ist es kein Fehler ältere Archiv-Versionen aufzuheben. Wer weiß ob die Uralt-Version eines Dokuments nicht doch nochmal wichtig wird.
Wiki und mariadb
sind ohnehin nur auf dem Server und da ist ein Backup Pflicht.
Backup!
Also muss eine Backup-Strategie her. Ganz früher hatte ich halt so hin und wieder von Hand meine Daten auf eine externe Festplatte kopiert und später mit diversen Backup-Programmen experimentiert. Die Auswahl an Programmen darf mit Fug und Recht als uferlos bezeichnet werden, wie eine Google-Suche nach "LINUX backup" demonstriert. Also was nehmen?
Im Vorfeld hatte ich erstmal mit bekannteren Werkzeugen wie Mondo Rescue, Amanda oder Bacula gespielt, aber irgendwie gefiel mir nichts davon – zu groß, zu grafisch zu wenig elegant. Ja – alles total subjektiv, aber bisher lag mein Instinkt bei solchen Dingen meist richtig.
Richtig interessant fand ich drei Tools, die meinen Vorstellungen von einer schlanken, robusten und GUI-losen Lösung entsprachen:
Alle drei sind reine Kommandozeilen Werkzeuge (teils mit optionalem GUI), was ich gerade für eine Server-Backup sehr wichtig finde, denn so kann man Backups leicht skripten und automatisieren und versteht anhand des config Files auf einen Blick, was es alles tut – und was nicht.
Am besten gefiel mir letztlich rsnapshot
es beherrscht saubere und zugleich
platzsparende inkrementelle Backups und ist sehr flexibel konfigurierbar.
Zudem verwendet es kein komplexes Archivformat, sondern speichert den Dateibaum
einfach nur ab. Tatsächlich verwendet es dann Hardlinks, um unveränderte
Dateien in den verschiedenen Backup Zweigen zu repräsentieren. Das spart Platz
und macht es trivial, eine Datei im Backup zu finden.
Ein Medium muss her!
Als nächstes ist zu entscheiden, wo die Sicherung überhaupt gespeichert werden soll.
- CD/DVD – im Ernst? In 2019? Wohl kaum. Und auch früher war das Mist, denn so eine glitzernde Scheibe verliert ihre Daten schneller, als ein Rodeo-Bulle seinen Reiter.
- Bänder? Tatsächlich auch heute eine sehr aktuelle und sinnvolle Variante, aber Bandlaufwerke und Bänder sind preislich seit vielen Jahren endgültig im Profi-Sektor zuhause.
- Cloud? Wäre eine Möglichkeit – zumindest wenn Datenmenge und Internet-Bandbreite in einem sinnvollen Verhältnis stehen. Erfordert aber einen brauchbaren Cloud-Speicher-Anbieter. Vielleicht mache ich das irgendwann, aber momentan war es mir zu teuer.
- NAS? Warum nicht. Aber extra als Backup Medium wollte ich mir keines kaufen. Und wenn man mal off-site Kopien haben will ist das auch eher nix.
- Festplatte? Aktuell das Medium meiner Wahl, denn externe USB-Platten sind günstig und in großen Kapazitäten zu haben.
Also externe USB Platten. Zwei WD-Elements Disks mit je 1.5TB in meinem Fall.
Was sichere ich bloß?
Bevor ich mir tiefere Gedanken um die Software gemacht habe stellte sich die Frage, was ich eigentlich alles sichern will und das ist garnicht so trivial, wie es klingt. Will ich den kompletten Rechner aus dem Backup wieder auferstehen lassen können? Oder nur meine Daten? Was ist mit dem Wiki? Reicht da die Datenbank? Oder speichert das noch irgendwo sonst erhaltenswerte Daten? etc., etc.
Letztlich habe ich beschlossen, dass es sich nicht lohnt, ein komplett-Image zu machen, oder das Betriebssystem anderweitig zu sichern. Eine Debian Installation geht einfach und sehr schnell – vorausgesetzt man weiß, welche packages installiert werden sollen und die Konfigs erhalten sind. Darüber hinaus sind noch ein paar Infos schützenswert:
D.h. ich sichere automatisch die Liste installierter packages und unterscheide
dabei zwischen manueller und automatischer Installation. Auch halte ich fest,
welche packages den Status hold
haben, denn das mach ich für besonders
wichtige Applikationen, bei denen ich automatische Updates verhindern will.
Die folgenden Kommandos liefern diese Info:
apt-mark showmanual
apt-mark showauto
apt-mark showhold
Und für den Fall, dass ich unbedingt wissen will/muss, welche Version eines Pakets installiert war nehme ich auch noch ein
dpkg-query -l
Dafür habe ich mir ein kleines Skript gebastelt, das diese Info speichert (save-package-states.sh
):
#!/bin/bash
# save package states
# this script is meant to be executed by rsnapshot
APT_MARK=/usr/bin/apt-mark
DPKG_QUERY=/usr/bin/dpkg-query
# save manual vs. automatic installation and hold state
$APT_MARK showmanual > pkgs_manual.lst
$APT_MARK showauto > pkgs_auto.lst
$APT_MARK showhold > pkgs_hold.lst
# Also provide detailed version and ARCH information in case of problems.
$DPKG_QUERY -l > pkgs-state.txt
Darüber hinaus kommt noch /etc
ins backup, denn das eine oder andere File
habe ich an meine Bedürfnisse angepasst. Also kommt dies in /etc/rsnapshot.conf
:
backup /etc/ hal/etc/
Das sagt dem Programm, dass wir ein Backup wollen und zwar vom Pfad /etc/
und
das soll dann im Folder hal/
auf das Backup-medium geschrieben werden – hal
ist der Name meines Servers.
Wichtig ist /home/
, denn dort leben meine User-Daten. Bei mir tatsächlich noch
mehr, denn ich habe die user homes unter /home/users/
, Projektdaten unter
/home/data
und Web Sachen unter /home/www
. Also:
backup /home/ hal/home/
Nicht vergessen sollte man auch /srv
. Bei mir liegt da nur ein Verzeichnis
für den FTP-Server, den ich im Intranet habe, aber grundsätzlich findet sich dort ggf.
alles mögliche andere Zeug, das verschiedene Dienste nach außen anbieten.
backup /srv/ hal/srv/
Bleibt noch die Datenbank. Da führen viele Wege nach Rom – welcher sinnvoll ist hängt davon ab, welche Datenmengen zu sichern sind und auch wie stark diese über die Zeit zunehmen.
Oft wird empfohlen, den Datenbank-Pfad (z.B. /var/lib/mysql/
) zu sichern.
Damit das keine Probleme macht muss man aber sicherstellen, dass grade keine
Schreibaktivität stattfindet. Außerdem kann ich es verschmerzen ggf. die
Datenbank-Indizes neu aufzubauen. Wichtig sind mir nur die Daten. mariadb
bietet eigene Bordmittel für inkrementelle Backups (mariabackup
). Sollte ich
irgendwann mal eine schnell wachsende Datenbank haben, werde ich das nutzen. Im
Augenblick ist das aber nicht der Fall und so habe ich mich für den Weg über
mysqldump
entschieden und überlasse das inkrementelle Sichern rsnapshot
.
Das ist simpel und transparent. rsnapshot
erlaubt es neben Pfaden auch
backup-scripts zu definieren – also externe Programme, die sich darum kümmern
die zu sichernden Daten irgendwo zu extrahieren:
backup_script /etc/rsnapshot/save-package-states.sh deb-packages/
backup_script /usr/bin/mysqldump mysql > mysql.sql mariadb/mysql/
backup_script /usr/bin/mysqldump xwiki > xwiki.sql mariadb/xwiki/
Das Xwiki hat auch noch lokale Daten:
backup /var/lib/xwiki/data hal/
Und wenn man das alles zusammenfügt ergibt sich folgender Auszug aus der Konfig-Datei:
# File server
backup /etc/ hal/etc/
backup /srv/ hal/srv/
backup /home/ hal/home/
exclude /home/lost+found/
# debian package states
backup_script /etc/rsnapshot/save-package-states.sh deb-packages/
# xwiki
backup /var/lib/xwiki/data hal/xwiki/
# mariadb
backup_script /usr/bin/mysqldump xwiki > xwiki.sql mariadb/xwiki/
backup_script /usr/bin/mysqldump mysql > mysql.sql mariadb/mysql/
Wie oft soll ich sichern?
Das schöne an einem inkrementellen Backup ist, das es nur dann wirklich
Speicherplatz verbraucht, wenn auch Daten hinzugekommen sind. D.h. es schadet
nicht, häufige Backups zu machen. Ich habe mich für täglich entschieden und
behalte die letzen 7 Versionen. Zusätzlich speichere ich wöchentliche (4
Stück) und monatliche (max 12) snapshots, so dass ich im Notfall ganz flexibel
auf Kopien unterschiedlichen Alters zurückgreifen kann. Im rsnapshot.conf
sieht das dann so aus:
retain daily 7
retain weekly 4
retain monthly 12
Zum Verständnis: die Labels daily
, weekly
und monthly
sind total
willkürlich. rsnapshot
ist es völlig wurscht, wie die heißen und es kümmert
sich auch nicht darum, wie oft sie ausgeführt werden – das wird alles extern
geregelt (cron). Was sollen die Einträge also? Das ist so: man ruft
rsnapshot
mit einem Label Argument auf und es nennt das jeweilige Backup dann
auch so (daily.0/
... daily.6/
). Also lasse ich jede Nacht dies laufen:
rsnapshot daily
Sonntags noch zusätzlich
rsnapshot weekly
Und immer am 1. des Monats
rsnapshot monthly
rsnapshot
schaut dann jeweils nach, wieviele daily
, weekly
oder monthly
backups schon auf dem Medium liegen und löscht ggf. alte Versionen, wenn es
mehr werden, als im Konfig File angegeben. Mit anderen Worten, es hebt immer
die letzten 7 daily backups auf.
Die Reihenfolge der verschiedenen Backups signalisiert, dass weekly
längerfristig ist, als 'daily' und monthly
am längsten.
Wenn nun mein weekly
backup läuft macht rsnapshot
gar kein richtiges
Backup, sondern schnappt sich einfach das siebte (=älteste) daily
backup
(daily.6
) und nennt es weekly
– somit ist dieser Stand archiviert. Das könnt
Ihr nun beliebig tief/komplex schachteln, je nach Euren Bedürfnissen.
Nach einem Jahr schicke ich die Platte dann aufs Altenteil – sprich sie kommt ins Archiv und wird durch eine neue ersetzt. Zu diesem Zeitpunkt beinhaltet sie dann 12 Monats-, 4 Wochen- und 7 Tages-Snapshots.
Und damit mein Backup nicht von der Gesundheit einer einzigen USB-Platte abhängt
habe ich zwei davon, die ich im Wechsel anschließe. Streng genommen müsste ich
nun die Konfig anpassen, weil rsnapshot
ja nicht weiß, was z.B. daily
bedeutet, sondern die letzten 7 dieses Typs aufhebt, aber das war mir zu
stressig – soll es doch mehr Kopien halten.
Tipp: rsnapshot
will tabs als Delimiter zwischen den verschiedenen
Argumenten – das hat mich erstmal verwirrt, bis ich es kapiert hatte...
Verschlüsselung
Falls so eine Backup Platte mal in falsche Hände geraten sollte, ist es eine gute Idee, sie zu verschlüsseln. Ich nehme dafür Linux Bordmittel (LUKS). D.h. ich bereite die Platte so vor:
# Generate a key file
dd if=/dev/urandom of=/root/backup.key bs=1k count=4
# create encrypted disk with predefined UUID (generated w/uuidgen)
cryptsetup luksFormat --uuid 56895370-b479-4541-ae57-74fc957fcaa3 /dev/sdX /root/backup.key
# attach the crypto disk
cryptsetup -d /root/backup.key open /dev/sdX backup
# create file system
mkfs.ext4 -m 1 /dev/mapper/backup
# detach disk
cryptsetup close backup
Ihr könnt statt eines key files natürlich auch eine Passphrase nehmen, aber keyfile ist sicherer – vorausgesetzt Ihr denkt daran, dieses gut zu schützen und ein separates Backup des Keyfiles zu machen und an einem sicheren Ort aufzubewahren, denn sonst nützt euch das schönste Backup nix, wenn Ihr es selber nicht mehr entschlüsseln könnt!
Ich erzwinge oben, dass meine Backup Platte eine bestimmte UUID bekommt. Ich gebe diese allen meinen Backup Platten, d.h. sie haben alle die gleiche UUID. Das erlaubt die automatische Verarbeitung im nächsten Abschnitt, ist aber etwas unorthodox. Also überlegt Euch, ob Ihr das für Euch so sinnvoll findet.
auto-mount
Im simpelsten Fall könnte ich nun meine Platte an den Server stöpseln und der nutzt sie allnächtlich für das Backup. Das birgt ein paar Risiken:
- Wenn irgendwas auf dem Server amok läuft (Virus, Verschlüsselungstrojaner, Hack, schlechtes Karma) dann ist die externe Platte ggf. ebenfalls kompromittiert oder gelöscht.
- Dito im Falle von Feuer oder Einbruch
Dagegen habe ich zwei Gegenmaßnahmen:
- Zwei Festplatten, die im Wechsel (idealerweise täglich, aber ich bin dafür zu träge) angeschlossen werden
- Die angeschlossene Platte wird nur direkt vor dem Backup gemountet und danach wieder unmounted. Das hilft natürlich nur begrenzt, aber besser, als nix...
Dazu habe ich mir ein kleines Wrapper-Skript (/etc/rsnapshot/backup.sh
) gebastelt:
#!/bin/bash
# Wrapper around rsnapshot
# takes care of mounting and unmounting the backup disk
MAPPERDEV=/dev/mapper/backup
BACKUPPATH=/media/backup
UUID=56895370-b479-4541-ae57-74fc957fcaa3
KEYFILE=/root/backup.key
# does the mapper device already exist?
if [ ! -e $MAPPERDEV ]; then
/sbin/cryptsetup --key-file $KEYFILE open /dev/disk/by-uuid/$UUID backup
else
echo $MAPPERDEV already exists
fi
# is it mounted?
if [ "$(findmnt -o TARGET -n $MAPPERDEV)" == "$BACKUPPATH" ] ; then
echo $MAPPERDEV already mounted at $BACKUPPATH
else
/bin/mount $MAPPERDEV $BACKUPPATH
fi
/usr/bin/rsnapshot $1
# unmount the backup disk
/bin/umount $BACKUPPATH
/sbin/cryptsetup close backup
# put disk in standby mode
# use grep to suppress the SG_IO warning
/sbin/hdparm -q -y /dev/disk/by-uuid/$UUID 2>&1 >/dev/null | grep -v 'SG_IO: bad/missing sense data, sb\[\]:'
Das mounted die Disk, führt das Backup durch und unmountet am Ende wieder. Und
als Sahnehäubchen fährt es die Disk mit hdparm
runter.
Automatisierung
Nun müssen wir das ganze nur noch in den gewünschten Abständen laufen lassen und das geht mit cron
.
In /etc/cron.d/
habe ich ein File namens rsnapshot
, das diesen Inhalt hat:
# crontab for rsnapshot
# m h dom mon dow user command
07 2 * * * root /etc/rsnapshot/backup.sh daily
07 3 * * 1 root /etc/rsnapshot/backup.sh weekly
07 4 1 * * root /etc/rsnapshot/backup.sh monthly
Und damit Ihr Euch das nicht alles von Hand zusammenfummeln müsst, könnt Ihr Euch meine diversen Files hier herunterladen und dann nach Herzenslust modifizieren:
/etc/cron.d/rsnapshot
/etc/rsnapshot/backup.sh
/etc/rsnapshot/save-package-states.sh
/etc/rsnapshot/rsnapshot.conf
Viel Spaß mit dem Backup und auf dass Ihr es niemals brauchen werdet.