Verschlüsselte Ubuntu Server Backups mit Borgbackup und Borgmatic

in #deutsch5 years ago

a5kpj6.jpg

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"