Backup und Restore

Veröffentlicht: 07.06.2026 | Aktualisiert: 07.06.2026

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 script speichern wir unter /data/scripts/backup/local_docker.shund sieht wie folgt aus:

#!/bin/sh

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

# 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 Script ausführbar über:

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

Um das Script manuell auszuführen gilt folgendes Kommando:

sudo /data/scripts/backup/local_docker.sh

Zur Automatisierung erstellen wir einen Cronjob der täglich 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 brauche 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 script /data/scripts/backup/local_zfs.sh:

#!/bin/sh

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

# 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 Script ausführbar über:

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

Um das Script manuell auszuführen gilt folgendes Kommando:

sudo /data/scripts/backup/local_zfs.sh

Zur Automatisierung erstellen wir einen Cronjob der täglich 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 anderem physischen Standort vorweisen zu können. Das ist das Einsatzszenario von Syncoid.

Als erstes erstellen wir auf dem ZIELSYSTEM ein Backup Script /data/scripts/backup/remote_zfs.sh :

#!/bin/sh

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

# 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 Script ausführbar über:

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

Um das Script manuell auszuführen gilt folgendes Kommando:

sudo /data/scripts/backup/remote_zfs.sh

Zur Automatisierung erstellen wir einen Cronjob der täglich 03: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