Backup und Restore

Server-Backup

(Lokales Dateisystem → ZFS storage →) ZFS-Snapshot → ZFS-Synchronisation.

Rsync – lokal

Um einen lokalen Ordner zwischen zwei Dateisystemen zu sichern, nutzen wir Rsync + Crontab.

Zunächst richten wir das Zielverzeichnis ein, z. B.:

sudo mkdir /storage/backup/local
sudo chown -R USERNAME: /storage/backup/local

Das Backup-Skript speichern wir unter /data/scripts/backup/local_docker.sh und sieht wie folgt aus:

#!/bin/sh

#README: https://niklas-stephan.de/wiki/tutorials/backup-und-restore/

# Set variables
SOURCE_DIR="/data/docker"
BACKUP_DIR="/storage/backup/local"
NTFY_URL="https://notify.handtrixxx.com/backup"

rsync -aX --delete --partial --inplace --timeout=60 \
    "$SOURCE_DIR" "$BACKUP_DIR"
RSYNC_EXIT="$?"
#RSYNC_EXIT="1"

if [ "$RSYNC_EXIT" -ne 0 ]; then
    if [ "$RSYNC_EXIT" -eq 23 ]; then
        MESSAGE="Backup of \"$SOURCE_DIR\" completed with partial errors (exit code 23 - some files could not be read)"
    else
        MESSAGE="Backup of \"$SOURCE_DIR\" failed with exit code $RSYNC_EXIT"
    fi
    curl --max-time 30 -s -o /dev/null\
        -H "Title: Backup failed on $(hostname)" \
        -H "Tags: warning" \
        -d "$MESSAGE" \
        "$NTFY_URL"
fi

Wir machen dieses Skript ausführbar über:

chmod +x /data/scripts/backup/local_docker.sh

Um das Skript manuell auszuführen, gilt folgendes Kommando:

sudo /data/scripts/backup/local_docker.sh

Zur Automatisierung erstellen wir einen Cronjob, der täglich um 02:00 Uhr laufen soll.

sudo crontab -e

Und fügen diese Zeile hinzu:

0 2 * * * /data/scripts/backup/local_docker.sh >> /var/log/backup_local_docker.log 2>&1

Erläuterung:

  • Läuft 02:00 Uhr täglich (0 2 * * *)
  • Läuft als root
  • Erzeugt eine Log-Datei zur Fehleranalyse

ZFS – lokal

Wir nutzen Sanoid zur Erstellung von ZFS-Snapshots.

Wir brauchen 2 Dateien: zunächst eine Konfigurationsdatei für Sanoid in /data/scripts/backup/sanoid.conf mit Inhalt wie:

# Datasets to snapshot
# Add or remove [dataset] blocks to control which datasets are managed

[storage/backup/local]
    use_template = daily

[template_daily]
    frequently = 0
    hourly = 0
    daily = 14
    monthly = 0
    yearly = 0
    autosnap = yes
    autoprune = yes

Dann noch unser eigentliches Backup-Skript /data/scripts/backup/local_zfs.sh:

#!/bin/sh

#README: https://niklas-stephan.de/wiki/tutorials/backup-und-restore/

# Set variables
SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
NTFY_URL="https://notify.handtrixxx.com/backup"

sanoid --configdir="$SCRIPT_DIR" --cron
SANOID_EXIT="$?"

if [ "$SANOID_EXIT" -ne 0 ]; then
    MESSAGE="ZFS snapshot job failed with exit code $SANOID_EXIT"
    curl --max-time 30 -s -o /dev/null \
        -H "Title: ZFS snapshot failed on $(hostname)" \
        -H "Tags: warning" \
        -d "$MESSAGE" \
        "$NTFY_URL"
fi

Wir machen dieses Skript ausführbar über:

chmod +x /data/scripts/backup/local_zfs.sh

Um das Skript manuell auszuführen, gilt folgendes Kommando:

sudo /data/scripts/backup/local_zfs.sh

Zur Automatisierung erstellen wir einen Cronjob, der täglich um 03:00 Uhr laufen soll.

sudo crontab -e

Und fügen diese Zeile hinzu:

0 3 * * * /data/scripts/backup/local_zfs.sh >> /var/log/zfs_snapshot.log 2>&1

Erläuterung:

  • Läuft 03:00 Uhr täglich (0 3 * * *)
  • Läuft als root
  • Erzeugt eine Log-Datei zur Fehleranalyse

ZFS – remote sync

Wir wollen die auf einem Remote-System vorhandenen Snapshots auf einem anderen Server duplizieren, um eine doppelte Sicherung an einem anderen physischen Standort vorweisen zu können. Das ist das Einsatzszenario von Syncoid.

Zuerst erstellen wir auf dem ZIELSYSTEM ein Backup-Skript /data/scripts/backup/remote_zfs.sh:

#!/bin/sh

#README: https://niklas-stephan.de/wiki/tutorials/backup-und-restore/

# Set variables
REMOTE_USER="USER"
REMOTE_HOST="HOST"
REMOTE_PORT="PORT"
SSH_CIPHER="aes128-gcm@openssh.com"
NTFY_URL="https://notify.handtrixxx.com/backup"

DATASETS="
zfsdata/sources:storage/backup/sources
"
FAILED=0
FAILED_DATASETS=""

for ENTRY in $DATASETS; do
    REMOTE_DS="${ENTRY%%:*}"
    LOCAL_DS="${ENTRY##*:}"

    syncoid \
        --sshport "$REMOTE_PORT" \
        --sshoption "Ciphers=$SSH_CIPHER" \
        "$REMOTE_USER@$REMOTE_HOST:$REMOTE_DS" \
        "$LOCAL_DS"

    EXIT="$?"
    if [ "$EXIT" -ne 0 ]; then
        FAILED=1
        FAILED_DATASETS="$FAILED_DATASETS $REMOTE_DS"
    fi
done

if [ "$FAILED" -ne 0 ]; then
    MESSAGE="Syncoid pull from $REMOTE_HOST failed for datasets:$FAILED_DATASETS"
    curl --max-time 30 -s -o /dev/null \
        -H "Title: ZFS sync failed on $(hostname)" \
        -H "Tags: warning" \
        -d "$MESSAGE" \
        "$NTFY_URL"
fi

Wir machen dieses Skript ausführbar über:

chmod +x /data/scripts/backup/remote_zfs.sh

Um das Skript manuell auszuführen, gilt folgendes Kommando:

sudo /data/scripts/backup/remote_zfs.sh

Zur Automatisierung erstellen wir einen Cronjob, der täglich um 01:00 Uhr laufen soll.

sudo crontab -e

Und fügen diese Zeile hinzu:

0 1 * * * /data/scripts/backup/remote_zfs.sh >> /var/log/zfs_remote_snapshot.log 2>&1

Erläuterung:

  • Läuft 01:00 Uhr täglich (0 1 * * *)
  • Läuft als root
  • Erzeugt eine Log-Datei zur Fehleranalyse

Wenn man den Prozess (Stand der Datenübertragung) sehen will, kann man das mit folgendem Kommando:

watch -n 1 'zfs list storage/backup/media'

Das führt das Kommando jede Sekunde aus, damit man den aktuellen Stand sieht.

:::warning Die erste Remote-Synchronisierung kann je nach Datenmenge lange dauern; man sollte darauf achten, den Cronjob für diesen Zeitraum zunächst zu deaktivieren. :::

Server-Restore

ZFS – lokal

Um vorhandene Snapshots im Dateisystem im Ordner .zfs zu sehen, muss dieses zunächst aktiviert werden:

sudo zfs set snapdir=visible zfsdata