Meine Server-Backups mache ich seit vorgestern über das Tool rdiff-backup, das bereits in den Repositories größerer Linux-Distributionen liegt. Rdiff-backup kann inkrementelle Backups von lokalen oder entfernten Quellen anlegen und verfügt über eine Delta-Synchronisierung, d.h. nur geänderte Bereiche einer Datei werden tatsächlich übertragen. Das macht rdiff-backup besonders effizient und damit zum idealen Werkzeug für Server-Backups.
Zuhause betreibe ich einen kleinen Server, der sich täglich die aktuellen Daten von den Servern im RZ herunterladen soll. Auf dem Server habe ich einen neuen user „serverbackup“ angelegt, unter dem die Backup-Prozesse laufen sollen. Als Home-Directory bekommt der User ein Verzeichnis auf einem großen Software-RAID:
# mkdir /storage/serverbackups # adduser --home /storage/serverbackups --disabled-password serverbackup # chown serverbackup:serverbackup /storage/serverbackups
Als serverbackup-User habe ich mich angemeldet und einen SSH-Schlüssel generiert:
# sudo -i -u serverbackup $ ssh-keygen
Mit dem erzeugten Schlüssel wird sich der serverbackup-User später zu jedem Server verbinden und sämtliche Daten herunterladen können. Um Zugriff auf alle Daten des Servers zu haben, ist es erforderlich, dass sich der Backupserver als root an zu sichernden Server anmeldet (dazu später mehr).
Den Public Key des SSH-Schlüssels habe ich mir zunächst auf den eigenen Rechner kopiert und dann auf den Server („server1“) übertragen, dessen Daten abgesichert werden sollen:
scp root@backupserver:/storage/serverbackups/.ssh/id_rsa.pub /tmp scp /tmp/id_rsa.pub root@server1:/root/
Auf „server1“ dann:
# cat id_rsa >> .ssh/authorized_keys
Zurück auf dem Backupserver kann die Verbindung dann getestet werden (die erste Verbindung zu einem neuen Server muss bestätigt werden)
$ ssh root@server1
Das Tool rdiff-backup muss auf Backup-Server und den zu sichernden Servern installiert werden:
apt install rdiff-backup
Theoretisch könnte an dieser Stelle bereits ein Daten-Backup des Servers angelegt werden (auf dem Backup-Server, eingeloggt als serverbackup-user):
$ rdiff-backup root@server1::/var/www /storage/serverbackups/server1/www
(achtet auf die zwei Doppelpunkte!) Das Kommando würde das /var/www/ Verzeichnis des Servers auf dem Backup-Server unter /storage/serverbackups/server1/www absichern. Das war für mich allerdings noch nicht ausreichend: Teilweise verfügen meine Server auch über MySQL-Datenbanken, deren Dumps ebenfalls gesichert werden sollen. Bevor eine Sicherung des Dateisystems erstellt wird, muss zunächst ein Dump aller Datenbanken generiert werden.
Auf jedem Server mit MySQL-Datenbank befindet sich daher unter /root/backup/ ein Skript „dbdump.sh“, das von den genannten Datenbanken je einen Dump in /root/backups/dbdumps/ erstellt.
Das Skript:
#!/bin/bash DBUSER="backup" DBPASSWD="passwort" DBBAKPATH="/root/backup/dbdumps/" DBS="owncloud vmail" for DBNAME in $DBS; do echo "Creating backup for database $DBNAME" && mysqldump -u $DBUSER -p$DBPASSWD $DBNAME > $DBBAKPATH"$DBNAME.sql"; done
Die zu sichernden Datenbanken werden durch ein Leerzeichen getrennt in „DBS“ aufgelistet. Außerdem wird für die DB-Dumps ein eigener MySQL-user „backup“ genutzt, den ich so angelegt habe:
# mysql -u root -p create user 'backup'@'localhost' identified by 'passwort'; grant select, show view, reload, replication client, event, trigger, lock tables on *.* to 'backup'@'localhost'; quit;
Das Skript wird unter „/root/backup/dbdump.sh“ abgespeichert und ausführbar gemacht. Außerdem wird das Verzeichnis „dbdumps“ erstellt, in dem die fertigen Dumps abgespeichert werden:
# chmod u+x /root/backup/dbdump.sh # mkdir /root/backup/dbdumps
Nun zurück zum Backup-Server. Auch hier habe ich ein kleines Skript unter „/storage/serverbackups/backup.sh“ erstellt, das auf dem Server (server1) zuerst die DB-Dumps erstellt und dann alle Daten mit rdiff-backup herunterlädt:
#!/bin/bash ROOTDIR="/storage/serverbackup/server1/" LOG=${ROOTDIR}backup.log # copy script output to logfile exec > >(tee -i ${LOG}) exec 2>&1 echo "###### Backup on $(date) ######" # Create DB dumps at remote server before copying them echo "###### Creating DB dump ######" ssh root@server1 'dbdump' echo "###### Downloading files from server ######" rdiff-backup root@server1::/root/backup/dbdumps ${ROOTDIR}dbdumps rdiff-backup root@server1::/var/www ${ROOTDIR}www # Remove old versions (older than 1 month) echo "###### Removing old versions ######" rdiff-backup --remove-older-than 1M ${ROOTDIR}dbdumps rdiff-backup --remove-older-than 1M ${ROOTDIR}www echo "###### Backup Finished! ######"
Das Verzeichnis „server1“ muss vor dem ersten backup natürlich noch angelegt werden:
$ mkdir ~/server1
Nachdem die DB-Dumps erzeugt wurden und die Daten aus /root/backup/dbdumps und /var/www heruntergeladen wurden, werden alte Backup-Versionen entfernt. Euch fällt vielleicht auf, dass beim dumpen der Datenbanken das Kommando „dbdump“ via ssh auf dem entfernten Server ausgeführt wird. Das Kommando gibt es noch nicht, aber wir führen das jetzt ein – zusammen mit einem Mechanismus, der für mehr Sicherheit sorgt. Damit der Backup-Server sämtliche Daten auf server1 lesen kann, habe ich ihm root-Rechte gegeben. Das hat den Nachteil, dass bei einem gekaperten Backup-Server auch alle anderen Server betroffen sind, zu denen der Backup-User vollen Zugriff hatte. Das sollte man so nicht stehen lassen; deshalb werden nun Zugangsbeschränkungen eingeführt.
In der Datei /root/.ssh/authorized_keys, in die zu Beginn der Public Key vom User „serverbackup“ kopiert wurde, kann mittels
command="date" ssh-rsa AAAAB3NzaC1yc2EAAA [...] serverbackup@backupserver
… beispielsweise festgelegt werden, dass der Besitzer des Keys AAAAB […] nur das Kommando „date“ ausführen darf. Ein Kommando ist in meinem Fall allerdings zu wenig – schließlich will ich zwei Kommandos ausführen können: dbdump und rdiff-backup (das wird automatisch auch auf dem Server ausgeführt). Leider kann in „command“ nur ein einziges Kommando angegeben werden, sodass an dieser Stelle ein kleiner Trick nötig ist. Für command= wird ein kleines Script angegeben:
command="/bin/bash /root/backup/backup-commands.sh" ssh-rsa [...]
In dem genannten Skript wiederum findet eine Überprüfung des gesendeten Kommandos statt: Ist das vom SSH-Client gesendete Kommando bekannt, wird es ausgeführt – andernfalls nicht. Der Inhalt dieses Skripts lautet wie folgt:
#!/bin/bash case $SSH_ORIGINAL_COMMAND in "dbdump") /bin/bash /root/backup/dbdump.sh ;; "rdiff-backup --server") rdiff-backup --server --restrict-read-only / ;; *) echo "Unknown command" esac
Als gültige Kommandos werden „dbdump“ (das führt dann letztendlich /root/backup/dbdump.sh aus) und „rdiff-backup –server“ zugelassen (welches dann ein rdiff-backup –server –restrict-read-only / ausführt). Gleichzeitig werden durch die Option „–restrict-read-only“ Schreibzugriffe durch rdiff-backup verhindert.
Ein Backup anlegen
Um ein Backup von server1 anzulegen, genügt es, auf dem Backup-Server einfach das Skript „backup.sh“ auszuführen: (ggf. vorher ausführbar machen: chmod u+x backup.sh)
$ ./backup.sh
Ein Cron-Job führt das Skript jede Nacht um 1:00 Uhr aus:
$ crontab -e
Zeile hinzufügen:
0 1 * * * /bin/bash ~/backup.sh > /dev/null 2>&1
… und fertig ist der Backup-Server.
Sollte die MySQL DB etwas größer sein, kannst du dir mal mydumper ansehen für das logische Backup der Datenbank.
mydumper ist wesentlich schneller wie mysqldump und hat auch mehr Funktionen.
http://www.loggn.de
Wir nutzen für MySQL / MariaDB Datenbank, in TB Niveau, erfolgreich seit 5 Monaten „xtrabackup“ von Percona.
Warum benutzt du kein rsync ?
rdiff-backup basiert soweit ich weiß auf rsync. Allerdings gibt es einen wesentlichen Funktionsunterschied: rdiff-backup legt die Backups inkrementell an d.h. es ist möglich auf vorige Versionen des Backups zurückzugreifen. So gehen irrtümlich gelösche Dateien nicht verloren und eine rudimentäre Versionierung ist vorhanden.
lg Florian
http://www.loggn.de
Hi Thomas,
was hältst du von BackupPC in Verbindung mit einen MySQL-Backup-Skript über „DumpPreUserCmd“? Nutzen wir schon seit Jahren, klappt über SSH und RSYNC echt super und die Wiederherstellung ist auch zügig.
Gruß Nico
https://legacy.thomas-leister.de/ueber-mich-und-blog/
Hi _nico,
Dazu habe ich noch keine Meinung, aber vielleicht probiere ich das auch mal aus.
Zum hantieren mit SSH-publickeys gibt es das eigene Tool ssh-copy-id!
https://legacy.thomas-leister.de/ueber-mich-und-blog/
Hi Sebastian,
das Tool kenne ich. Nützt mir aber nicht viel, wenn ich Passwort-Authentifizierung auf meinen Servern komplett verbiete ;) Dann funktioniert ssh-copy-id nämlich nicht. Daher der Umweg.
https://codehat.de
Hi,
war mal wieder sehr hilfreich!
Danke dir ;)