Verschlüsselte Ubuntu Server Backups mit Borgbackup und Borgmatic
In diesem Eintrag gibt es für mich oder auch für dich eine kleine Zusammenfassung, wie es mit dem BorgBackup-Wrapper Borgmatic, natürlich auch Open-Source (GPLv3), möglich ist, einen lokalen Ubuntu-Server, auf einen File-Server, verschlüsselt abzusichern und wie man das erstellte Backup auch wieder fein wiederherstellen kann.
Warum BorgBackup
Weil BorgBackup ein, vom Betriebssystem unabhängiges, Open-Source (BSD) Backup System ist, das sehr effizient, verschlüsselt und performant, deduplizierende Backups erstellen kann. Nebenher wird es kräftig weiterentwickelt und die Dokumentation ist aller erste Sahne.
Warum Borgmatic
Weil man hiermit BorgBackup um einiges leichter, schicker und schneller steuern kann. Es ist auch möglich, verschiedene Backup-Profile anzulegen, die dann nur bestimmte Applikationen wie z. B. den Webserver oder die Datenbank absichern.
Ausgangsszenario
Für dieses Unterfangen nehme ich aus meinem Heim-Netz einen Ubuntu-Server, den ich über eine SMB-/CIFS-Freigabe auf meinem Backup-Server backuppe. Natürlich wäre es auch möglich, die Backups über eine sichere SSH-Verbindung auf einen Remote-Server zu schieben, was ich bei Servern, die nicht in einem Privaten Netz hängen, auch wärmstens empfehlen würde.
Vorgaben:
# Backup-Programme: BorgBackup und Borgmatic
# Backup-Patient: Ubuntu-18.04 Webserver (IP: 10.10.3.100 | hostname: betzi.int)
# Backup-Server: Ubuntu-18.04 Samba-Fileserver (IP: 10.10.3.5 | hostname: fillissima.int)
# Samba-Fileserver SMB-Share-User: betzi
# Samba-Fileserver SMB-Share-Pfad: //10.10.3.5/backup/borg
# Backup-Patient Ordnerstruktur:
- /root/skripte/shell/ # Mysql-Backup-Skript
- /data/sicherungen/db/ # Mysql-Backups
- /mnt/backup/$(hostname -f) # Mount-Point für die Backups auf dem SMB-Share
# Backup-Methode: Verschlüsselte Backups auf dem gemounteten SMB-Share des internen Backup-Server.
Installation Borgbackup
BorgBackup wird über das Offizielle BorgBackup-PPA-Repository installiert.
apt install software-properties-common
add-apt-repository ppa:costamagnagianfranco/borgbackup
aptitude update && aptitude install borgbackup liblz4-tool
Installation Borgmatic
apt install python3-pip python3-setuptools
pip3 install --upgrade borgmatic
SMB-Share des Backup-Server einbinden
# SMB-/CIFS-Client auf der Betzi (Webserver) installieren
aptitude install cifs-utils
# Mount-Point auf dem zu backuppenden System (Betzi) anlegen
mkdir -p /mnt/backup/$(hostname -f)
# Mount-Point persisten in die "/etc/fstab" eintragen
//10.10.3.5/borg /mnt/backup cifs credentials=/root/.smb 0 0
# Die Zugangsdaten für den Samba-Server Freigabe (Credential-Datei) in "/root/.smb"
username=betzi
password=supp@-lekka_do3n3rT3ll3r..
# Samba-Server Mount-Point auf der guten alten Betzi mounten
mount -a
Ordnerstruktur anlegen und Borgmatic-Konfiguration erstellen
# Ordner für die Borgbackup-Skripte erstellen
mkdir -p /root/skripte/shell/borg
# Ordner für die Datenbank Backups erstellen
mkdir -p /data/sicherungen/db
# BorgBackup Logfile-Ordner erstellen
mkdir -p /var/log/borg
# Berechtigung setzen
find /root -type d | xargs -I {} chmod -v 700 {}
find /data/sicherungen -maxdepth 1 -type d | xargs -I {} chmod -v 700 {}
# Borgmatic-Konfig-Datei estellen
generate-borgmatic-config && cd /etc/borgmatic/
Borgmatic konfigurieren
In der Borgmatic-Konfiguration, hier „borgmatic-smb-backup.yaml„ (da ja für interne Backups auf den SMB-Share), sollte man zumindest den „repositories„-Ordner, die zu sichernden „source_directories„-Odner und unter „storage“ einen eigenen „encryption_passphrase“ setzen.
# Borgmatic borgmatic-smb-backup.yaml
location:
# Repository Path. Hier würde man auch die SSH-Verbindung eintragen
repositories:
- /mnt/backup/og.doenerteller.tr
# Backup Sources
source_directories:
- /etc
- /usr
- /opt
- /srv
- /var
- /root
- /home
# Exclude Sources
exclude_patterns:
- /run
- /sys
- /dev
- /tmp
- /mnt
- /proc
- /var/run
- /lost+found
- /var/lib/lxcfs
- /var/spool/dma
exclude_caches: true
storage:
encryption_passphrase: "zum-g0ld3nen.Spu<kn@pF!"
compression: lz4
archive_name_format: '{fqdn}-{now:%Y-%m-%d_%H-%M}'
# Prune Zeitraum
retention:
keep_daily: 7
keep_weekly: 4
keep_monthly: 6
prefix: '{fqdn}-'
# Backup-Validierung
consistency:
checks:
- repository
- archives
check_last: 2
prefix: '{fqdn}-'
output:
color: false
hooks:
before_backup:
- echo "Start des sexy Borgbackup-Backups: `date +'%Y-%m-%d_%H-%M-%S'`"
- ping -q -c 1 10.10.3.5 > /dev/null || exit 75
- findmnt /mnt/backup > /dev/null || exit 75
- /root/skripte/shell/db_dump_mysql.sh
before_prune:
- echo "Starting pruning: `date +'%Y-%m-%d_%H-%M-%S'`."
before_check:
- echo "Starting Backup checks: `date +'%Y-%m-%d_%H-%M-%S'`"
after_backup:
- echo "Finished the backup. Respect dude!."
after_prune:
- echo "Finished pruning. Sauwa."
after_check:
- echo "Finished checks du grasser Checker."
mysql_databases:
- name: all
umask: 0077
Das „mysql_databases“ könnten man sich hier spraren da das „db_dump_mysql.sh“ Skript schon die DB’s in einzelne SQL-Files ablegt aber ein komplettes Backup in ein SQL-File kann nicht schaden 🙂
Mysql Datenbank Skript
#!/bin/bash
# Version: 0.9
# Date: 13.03.2019
# Modified: 10.02.2020
# Scriptname: db_dump_mysql.sh
# Author: https://hackspoiler.de
# Description: Backup der DB's in separaten SQL-Files. Das DB-Passwort wird straight aus dem "/root/.my.cnf" File gezogen.
# Set Bash-Defaults
set -uo pipefail
IFS=$'\n\t'
# Set Variables
USER="root"
RM="$(which rm)"
TEE="$(which tee)"
GREP="$(which grep)"
FIND="$(which find)"
MKDIR="$(which mkdir)"
MYSQL="$(which mysql)"
MYSQLDUMP="$(which mysqldump)"
LOGDIRECTORY="/var/log/mysql"
LOGFILE="${LOGDIRECTORY}/mysql_db_dump.log"
TIMESTAMP=$(date +'%Y-%m-%d-%H-%M-%S')
OUTPUTDIR="/data/sicherungen/db/${TIMESTAMP}"
# Create Backup and Logfile Directory structure
[[ ! -d "${OUTPUTDIR}" ]] && "${MKDIR}" -p "${OUTPUTDIR}"
[[ ! -d "${LOGDIRECTORY}" ]] && "${MKDIR}" -p "${LOGDIRECTORY}"
## Logging starten
exec > >("${TEE}" -i "${LOGFILE}")
exec 2>&1
# Start creating Database Backup
DATABASES=$("$MYSQL" --user="$USER" --batch --skip-column-names -e "SHOW DATABASES;" | "$GREP" -E -v '^mysql$|^sys$|*_schema$')
for database in ${DATABASES[@]}; do
"${MYSQLDUMP}" \
--user="${USER}" \
--force \
--quote-names --dump-date \
--opt --single-transaction \
--events --routines --triggers \
--databases "${database}" \
--result-file="${OUTPUTDIR}/${database}.sql"
echo "Backup ${database}"
done
# Logging
[[ $? == 0 ]] && printf "DB-Backup on %s succesfull in %s created\n" "$(date +'%Y-%m-%d-%H-%M-%S')" "${OUTPUTDIR}" | "${TEE}" -a "${LOGFILE}" || printf "Database Backup on %s successfully fucked up\n" "$(date +'%Y-%m-%d-%H-%M-%S')" | "${TEE}" -a "${LOGFILE}"
# Datenbanken älter als 1 Tag löschen
"${FIND}" /data/sicherungen/db/ -maxdepth 1 -type d -mtime +1 -print0 | xargs -0 -I {} "${RM}" -rf {} 2>> "${LOGFILE}"
Borgmatic Konfiguration validieren und Backupverzeichnis initialisieren
validate-borgmatic-config
borgmatic init --encryption repokey-blake2
Erstes Initialales Backup erstellen
borgmatic --verbosity 1
Backup verifizieren
borgmatic list
borgmatic info
Cronjob einrichten
# vim /etc/cron.d/borgmatic
0 1 * * * root /usr/local/bin/borgmatic --config /etc/borgmatic/borgmatic-smb-backup.yaml --syslog-verbosity 1
Backups wiederherstellen – Extract Version
# Erstellen des Restore-Ordners
mkdir -p /tmp/$(hostname -f)
# Restore des aktuellsten kompletten Backups in das angegeben /tmp-Verzeichnis
borgmatic extract --archive latest --destination /tmp/$(hostname -f)
# Restore des angegebenen kompletten Backups in das /tmp-Verzeichnis
borgmatic extract --archive <_ARCHIV_NAME_> --destination /tmp/$(hostname -f)
# Restore der angegebenen Pfade (/etc und /usr) in das /tmp-Verzeichnis
borgmatic extract --archive <_ARCHIV_NAME_> --destination /tmp/$(hostname -f) --restore-path /etc/ /usr/
Backups wiederherstellen – Mount Version
# Alle vorhandenen Archive mounten
borgmatic mount --mount-point /mnt
# Zuletzt erstelles Backup-Archiv unter /mnt/restore mounten
borgmatic mount --archive latest --mount-point /mnt/restore
# Mount des angegebenen kompletten Backups unter /mnt/restore
borgmatic mount --archive <_ARCHIV_NAME_> --mount-point /mnt/restore
# Nur einen speziellen Pfad mounten
borgmatic mount --archive latest --mount-point /mnt/restore --path etc/apache2/
# Backup-Mounts wieder entmounten
borgmatic umount --mount-point /mnt
Backups entfernen
# Repository-Pfad setzen
REPOSITORY="/mnt/backup/$(hostname -f)"
# Alles vorhandenen Backups auflisten
borgmatic list
# Gewünschtes Backup löschen
borg delete ${REPOSITORY}::'<_ARCHIV_NAME_>'
# Will man das ganze Repository endgültig entfernen (bei der Bestätigung "YES" groß schreiben!)
borg delete ${REPOSITORY}
Repository Passwort ändern
# Repository Pfad setzen
REPOSITORY="/mnt/backup/$(hostname -f)"
# Repository-Passwort ändern
borg key change-passphrase -v /mnt/backup/$(hostname -f)
Samba Server SMB-Share Einstellung
So könnte zum Beispiel eine Samba-Fileserver-Konfiguration aussehen
# Globale Samba-Einstellung
[global]
security=user
local master=no
smb encrypt=force
max protocol=SMB3
min protocol=SMB2_10
winbind enum users=yes
workgroup=bauchbeinepo
realm=bauchbeinepo.int
passdb backend=smbpasswd
log file = /var/log/samba/log.%m
# Borgbackup SMB-Share Freigabe
[backup]
writeable=yes
browseable=no
mediaindex=no
win share=yes
path=/srv/backup
hide unreadable=yes
read list=nobody,nobody
write list=betzi,chucknorris
valid users=betzi,chucknorris
invalid users=guest,usersm nobody
comment="Borgbackup Ordner"