Eine Anmerkung zum Tutorial: Wir ermutigen unsere Benutzer, Tutorials auszuprobieren, aber sie werden nicht vollständig von unserem Team unterstützt – wir können nicht immer Unterstützung bieten, wenn etwas schief läuft. Prüfe unbedingt, mit welchem Betriebssystem und welcher Version es getestet wurde, bevor du weitermachst.

Im Laufe der Jahre konnte ich verschiedene Backup-Lösungen auf meinem Server testen – aber meine jetzige Lösung gefällt mir am besten, deshalb möchte ich Euch diese in diesem Artikel kurz vorstellen.

Die Kernkomponente meines Backup-Setups ist das Backup-Tool “Borg”, welches sich scheinbar unter den Linux-Admins immer größerer Beliebtheit erfreut – und das auch völlig zu Recht. Das Tool ist recht einfach zu bedienen und ermöglicht im Client-Server Modell sehr effiziente Sicherungen. Sowohl beim Datentransport zum Backup-Storage als auch bezüglich des verbrauchten Speichers.

Installation von Borg

Borg gibt es als fertige Pakete für verschiedene Linux Distributionen wie Debian, Ubuntu oder auch Arch Linux. Neben der Installation über den Paketmanager gibt es auch noch die Installation via pip, oder manuell über ein einzelnes Binary, welches schon alle Abhängigkeiten enthält. Es ist vorteilhaft, auf dem Backupserver und dem zu sichernden Server (im folgenden einfach “Server” genannt) dieselbe Version von Borg zu nutzen, um Probleme durch eventuelle Inkompatibilitäten zu vermeiden. Die verschiedenen Installationsarten sind auchim Borg Guide ausführlich erklärt – ich werde daher nicht darauf eingehen.

Die Konfiguration des Backupservers

Als Backupserver dient ein alter PC daheim, den ich als NAS umgebaut habe. Der NAS läuft durchgängig, und eignet sich nicht nur hervorragend als Archiv- und Backupserver für die heimischen Geräte, sondern auch für meinen Server. Dank 200 MBit/s / 50 MBit/s Glasfaser und des intelligenten Delta-Datenabgleichs sind auch größere Datenmengen relativ zügig zuhause gesichert – und nebenbei ist damit auch noch ein sog. “Off-Site-Backup” gemacht, also ein Backup, welches geografisch getrennt von den Produktivservern gelagert wird.

Auf dem Backupserver habe ich einen eigenen Benutzer borgbackup angelegt, dessen Home-Verzeichnis auf einer eigenen Partition liegt. So wird verhindert, dass Serverbackups (unbeabsichtigt) ausufern und große Teile des verfügbaren Speichers belegen. Meine Server melden sich jeweils als borgbackup-User an, um sich via SSH zu verbinden und die zu sichernden Daten über eine SFTP-Verbindung zu übertragen. Nach Anlegen des neuen Nutzers auf dem Backupserver wird also auf jedem der anderen Server für den jeweiligen root-Nutzer ein SSH-Key generiert, falls noch nicht vorhanden:

ssh-keygen -a 100 -t ed25519

Die Public Keys aller Server werden gesammelt und auf dem Backupserver in die ~/.ssh/authorized_keys Datei eingetragen, etwa so:

ssh-ed25519 AAAAB3NzaC1yc2EAAAADAQABAAABAQDO67aeTjQwIuuqgxEVasVH root@server1
ssh-ed25519 N3Vb3Nfdgdf1yc2gfAAJen4mJQgfhLgefgh4NhbenHGDsdf62mNe root@server2

Eine Verbindung zum Backupserver wäre damit jetzt schon möglich. Doch nehmen wir mal an, der Server wird kompromittiert: Ein Angreifer hätte dann ggf. Zugriff auf den Private Key des Servers und damit auch auf den User des Backupservers. Nichts würde ihn daran hindern, weiteren Schaden anzurichten und z.B. alle Backups auf dem Backupserver zu löschen, bevor der gekaperte Server missbraucht. Es gilt also zu verhindern, dass einer der Server über die SSH-Verbindung etwas anderes tut, als Backups zu übertragen. Daher wird die gerade bearbeitete authorized_keys Datei wie folgt erweitert:

command="borg serve --restrict-to-path /home/serverbackup/backups/server1 --append-only" ssh-ed25519 AAAAB3NzaC1yc2EAAAADAQABAAABAQDO67aeTjQwIuuqgxEVasVH root@server1
command="borg serve --restrict-to-path /home/serverbackup/backups/server2 --append-only" ssh-ed25519 N3Vb3Nfdgdf1yc2gfAAJen4mJQgfhLgefgh4NhbenHGDsdf62mNe root@server2

Das vorangestellte command=" [...] " sorgt dafür, dass via SSH nur noch die gewünschten Borg-Kommandos ausgeführt werden können – und zwar nur “hinzufügend” (--append-only). Außerdem wird das Verzeichnis festgelegt, innerhalb dessen sich der verbundene Server aufhalten darf (--restrict-to-path). Amok laufende Server stellen dann keine Gefahr mehr für die Backups dar.

Die angegebenen Verzeichnisse für die Backups der Server im serverbackup-Homeverzeichnis müssen selbstverständlich noch angelegt werden. Damit Borg die Backupverzeichnisse als solche erkennt, muss noch ein borg init ausgeführt werden:

mkdir -p /home/serverbackup/backups/server1
borg init /home/serverbackup/backups/server1

mkdir /home/serverbackup/backups/server2
borg init /home/serverbackup/backups/server2

Die Eingabe einer Passphrase wird mit 2x [ENTER] übersprungen. Damit ist der Backupserver vorbereitet.

Konfiguration des zu sicherenden Server

Kommen wir nun zu den Server, von denen regelmäßig Sicherungen angelegt werden sollen. Borg sollte hier bereits installiert sein. Die Backups werden vom root-User durchgeführt, da in den meisten Fällen nur er Zugriff auf alle wichtigen Daten hat.

Der Backup-Prozess wird durch einen Cronjob ausgelöst und von einem einfachen Bash-Script ausgeführt, welches Vorbereitungen durchführt und letztendlich Borg nutzt, um das Backup auf Dateiebene zu starten. Jede Nacht soll ein Backup um 00:00 Uhr starten. Der Cronjob kann beispielsweise folgendermaßen eingetragen werden (Cronjob-Editor öffnen via crontab -e als root.):

@daily /root/backup/backup.sh > /dev/null 2>&1

Das Backup-Script, was unter /root/backup/backup.sh abgelegt wurde,  sieht wie folgt aus:

#!/bin/bash

##
## Save backup to directory named after hostname
##

LOG="backup.log"
HOST=`hostname`
REPOSITORY="ssh://serverbackup@backupserver.tld:22/~/backups/"$HOST

##
## Write output to logfile
##

exec > >(tee -i ${LOG})
exec 2>&1

echo "###### Starting backup on $(date) ######"


##
## Create list of installed software
##

dpkg --get-selections > /root/backup/software.list


##
## Create database dumps
##

echo "Creating database dumps ..."
/bin/bash /root/backup/dbdump.sh


##
## Sync backup data
##

echo "Syncing backup files ..."
borg create -v --stats                                  \
    $REPOSITORY::'{now:%Y-%m-%d_%H:%M}'                 \
    /root/backup                                        \
    /etc                                                \
    /var/www                                            \
    /var/vmail                                          \
    /storage


echo "###### Finished backup on $(date) ######"


##
## Send mail to admin
##

mailx -a "From: "$HOST" Backup <"$HOST"@meinedomain.tld>" -s "Backup | "$HOST webm@meinedomain.tld < $LOG

Folgende Daten werden gesichert:

  • Liste aller installierten Softwarepakete
  • Ein Dump aller Datenbanken, die in dbdump.sh definiert sind (dazu gleich mehr)
  • Dateien aus den angegebenen Verzeichnissen (/etc, /var/www, … )

Sämtliche Ausgaben, die während des Backupprozesses entstehen, werden in eine Log-Datei geschrieben und als E-Mail an den Administrator geschickt. Das funktioniert freilich nur, wenn ein funktionierender Mailserver auf dem System installiert ist.

MySQL Datenbanken sichern

Die Sicherung der MySQL-Datenbanken übernimmt ein eigenes Script, was unter /root/backup/dbdump.sh abgelegt wurde:

#!/bin/bash

DBUSER="backup"
DBPASSWD="backupuserpassword"
DBBAKPATH="/root/backup/dbdumps/"

DBS="nextcloud vmail spamassassin"

for DBNAME in $DBS; do echo "Creating backup for database $DBNAME" && mysqldump -u $DBUSER -p$DBPASSWD $DBNAME > $DBBAKPATH"$DBNAME.sql"; done

Damit das Script auch reibungslos funktioniert, muss im /root/backup Verzeichnis ein Unterverzeichnis “dbdumps” existieren. Nur die in “DBS” definierten Datenbanken werden vom Backup erfasst. Auf dem MySQL-Server muss ein spezieller Backup-User “backup” mit dem dazugehörigen Passwort angelegt werden. Dieser hat lesenden Zugriff auf alle Datenbanken und Tabellen:

mysql -u root -p
create user 'backup'@'localhost' identified by 'backupuserpassword';
grant SELECT, RELOAD, LOCK TABLES, REPLICATION CLIENT, SHOW VIEW, EVENT, TRIGGER on *.* to 'backup'@'localhost';
quit;

Das war’s auch schon!

Jetzt testen wir noch das Bash Script:

chmod u+x /root/backup/backup.sh
./root/backup/backup.sh

Wenn alles klappt, wäre das Thema “Backup” ist fürs erste erledigt. Im Grunde müssen jetzt nur noch die eintreffenden E-Mails regelmäßig kontrolliert werden.

Alte Backups automatisch entfernen

Wir haben aber noch was Wichtiges vergessen! Mit der Zeit werden die Backups langsam aber sicher die zugewiesene Partition auf dem Backupserver füllen. Damit das nicht passiert, macht es Sinn alte BackUps regelmäßig zu löschen.

Für diese Aufgabe habe ich mir auf dem Backupserver ein weiteres Script /home/serverbackup/prune-backup.sh angelegt:

#!/bin/bash

ROOTDIR="/home/serverbackup/backups/"
LOG="prune-backup.log"

# copy all output to logfile
exec > >(tee -i ${LOG})
exec 2>&1

echo "###### Pruning backup for server1 on $(date) ######"

borg prune -v ${ROOTDIR}server1 \
--keep-daily=7 \
--keep-weekly=4 \
--keep-monthly=6

echo "###### Pruning backup for server2 on $(date) ######"

borg prune -v ${ROOTDIR}server2 \
--keep-daily=7 \
--keep-weekly=4 \
--keep-monthly=6


echo "###### Pruning finished ######"

# Send logfile to serveradmin
mailx -r backup@meinserver.tld -s "Backup | Prune" admin@meinserver.tld < $LOG

Auch dieses Script wird von einem Cronjob ausgelöst – und zwar erst, wenn alle Serverbackups durchgeführt sind. Andernfalls kann es zu Konflikten kommen. Ich lasse das Script zum “Stutzen” des Backups daher erst um 2:00 Uhr täglich laufen.

Auf dem Backupserver:

su - serverbackup
chmod u+x ~/prune-backup.sh
crontab -e

Neuer Cronjob:

0 2 * * *  ~/prune-backup.sh

Nach einem “prune” bleibt von den Backups nur folgendes übrig:

  • 7 tägliche Backups aus den letzten Tagen
  • 4 wöchentliche Backups aus den letzten 4 Wochen
  • 6 monatliche Backups aus den letzten 6 Monaten

Das heißt: Ich behalte nur so viele Daten, dass ich die täglichen Stände der letzten Woche wiederherstellen kann, oder die wöchentlichen Stände der letzten 4 Wochen, oder die monatlichen Stände des letzten halben Jahres. Länger als 6 Monate wird kein Backup aufbewahrt.

Backups wiederherstellen

 Im Notfall soll es schließlich schnell und routiniert funktionieren. Daher hier die notwendigsten Kommandos:

Liste der vorhandenen Backups einsehen

Entweder auf dem Backupserver: (in den meisten Fällen weniger komfortabel)

cd /home/serverbackups/backups/server1
borg list

Oder direkt auf dem betroffenen Server (als root):

borg list ssh://serverbackup@backupserver.tld:22/~/backups/server1

Die Ausgabe kann z.B. so aussehen:

2017-04-07_00:04                     Fri, 2017-04-07 00:01:18
2017-04-08_00:04                     Sat, 2017-04-08 00:00:56

Ein Verzeichnis wiederherstellen

Um eine spezielle Version eines Verzeichnisses oder einer Datei aus dem Backup-Archiv zu extrahieren, wird das borg extract Kommando genutzt. Beispiel: Das Verzeichnis /var/www vom 08.04.2017 soll vom Server aus wiederhergestellt und nach /backup-extracted/www geschrieben werden:

mkdir -p /backup-extracted/www
cd /backup-extracted/www
borg extract ssh://serverbackup@backupserver.tld:22/~/backups/server1::2017-04-08_00:04 var/www
Eine Anmerkung: Der borg extract Befehl extrahiert die Daten in das aktuelle Verzeichnis: Daher erst in das Zielverzeichnis navigieren – dann borg extract absetzen!

Der entsprechende Wiederherstellungsbefehl auf dem Backupserver könnte beispielsweise lauten:

borg extract ~/backups/server1::2017-04-08_00:04 var/www

Je nach Netzwerkverbindung und Systemleistung kann das Wiederherstellen eines Backups einige Zeit in Anspruch nehmen. In den meisten Fällen muss es nämlich zuerst aus mehreren inkrementellen Backups zusammengesetzt werden.

Ich hoffe ich konnte euch wenig helfen, dann auf gutes BackUpen.