Zum Hauptinhalt springen

ZFS Snapshots von Open-E JovianDSS per Pull replizieren

Wim Bonis
Storage ZFS Open Source
Autor
Stylite AG
Spezialisten in ZFS storage solutions, security. Docker containerization for enterprise environments.
Inhaltsverzeichnis

Open-E JovianDSS bietet zwar eigene Replikationsmechanismen, aber manchmal sollen Snapshots auf ein externes ZFS-System gezogen werden – als unabhängiges Backup-Ziel. Das Backup-System kann dabei ein beliebiges Linux mit ZFS sein, z. B. TrueNAS SCALE, Debian oder Ubuntu mit OpenZFS. Mit zfs-autobackup lässt sich das elegant lösen: Das Tool markiert Datasets per ZFS-Property und repliziert sie automatisch über SSH.

In diesem Artikel wird gezeigt, wie die Replikation von Open-E JovianDSS auf ein externes Backup-System eingerichtet wird – im Pull-Modus, bei dem das Backup-System die Snapshots aktiv vom Open-E abholt.

Übersicht: Architektur
#

┌─────────────────────┐         SSH (Port 9922)          ┌──────────────────────┐
│   Backup-System     │ ◄─────────────────────────────── │  Open-E JovianDSS    │
│   (Linux mit ZFS)   │        zfs send/receive          │  (open-e cluster)    │
│                     │                                  │                      │
│  zfs-autobackup     │    ┌──────────────────────┐      │  Rootconsole (LXC)   │
│  (Pull-Modus)       │───►│  Rootconsole (SSH)   │─────►│  /usr/local/sbin/zfs │
│                     │    │  Port 9922           │      │  → xcadmin@host      │
│  pool/BACKUP        │    └──────────────────────┘      │  → sudo zfs ...      │
└─────────────────────┘                                  └──────────────────────┘

Der Ablauf:

  1. Das Backup-System startet zfs-autobackup im Pull-Modus
  2. Das Tool verbindet sich per SSH zur Rootconsole auf Open-E (Port 9922)
  3. In der Rootconsole leitet ein Wrapper-Skript die ZFS-Befehle an den Open-E Host weiter
  4. Die Snapshots werden per zfs send | zfs receive auf das Backup-System übertragen

Voraussetzungen
#

  • Open-E JovianDSS mit installierter Rootconsole (ab UP33 standardmäßig dabei)
  • Backup-System: Ein beliebiges Linux mit ZFS (z. B. TrueNAS SCALE, Debian, Ubuntu) mit Shell-Zugriff und installiertem zfs-autobackup
  • Netzwerkverbindung zwischen beiden Systemen (SSH-Zugriff)

Schritt 1: Rootconsole auf Open-E einrichten
#

Die Rootconsole ist ein privilegierter LXC-Container auf Basis von Debian 12, der Open-E JovianDSS um eine vollwertige Linux-Umgebung erweitert. Ab UP33 ist die Rootconsole standardmäßig enthalten. Für ältere Versionen kann sie als Small Update nachinstalliert werden:

  1. Das .upd-Paket von Open-E FTP herunterladen (passend zur installierten JovianDSS-Version)
  2. In der Web-Oberfläche unter System Settings → Update hochladen und installieren
  3. JovianDSS neu starten

Nach der Installation ist die Rootconsole über https://<IP>:4200/rootconsole-d12/ erreichbar. Alternativ kann sie über Console tools → Add-ons in der Konsole gestartet werden. Eine ausführliche Installationsanleitung bietet die Open-E Knowledge Base .

Die Rootconsole verhält sich wie ein eigenständiges Linux-System (vergleichbar mit einer VM oder einem Container), mit dem Unterschied, dass die ZFS-Pools des Open-E Hosts eingebunden sind. Es lässt sich beliebige Software installieren – Pakete, Dienste, Konfigurationen – ohne das eigentliche Open-E System zu beeinflussen.

SSH-Server in der Rootconsole installieren
#

Für den Fernzugriff muss OpenSSH in der Rootconsole selbst installiert und konfiguriert werden – es ist kein SSH-Server vorinstalliert:

# Login in die Rootconsole als admin/PASSWORD_OF_ADMIN_USER
sudo -s
apt-get update
apt-get install openssh-server

Anschließend den SSH-Port und weitere Einstellungen in /etc/ssh/sshd_config nach Bedarf anpassen – Port, erlaubte Authentifizierungsmethoden und Zugriffsbeschränkungen sind frei wählbar:

# Beispiel: SSH auf Port 9922 konfigurieren, nur Schlüssel-Auth
sed -i 's/^#Port 22/Port 9922/' /etc/ssh/sshd_config
sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
sed -i 's/^#*KbdInteractiveAuthentication.*/KbdInteractiveAuthentication no/' /etc/ssh/sshd_config
systemctl restart ssh
systemctl enable ssh
# für zfs send/receive benötigt man mbuffer (falls angegeben)
apt-get install mbuffer

💡 Hinweis: Die Rootconsole läuft in einem eigenen LXC-Container; dort ist /dev/zfs nicht verfügbar, ZFS-Befehle laufen nur über Shell-Aliase. Im nächsten Schritt wird daher ein Wrapper-Skript benötigt, das die ZFS-Befehle an den Open-E-Host weiterleitet.

Der gewählte SSH-Port (hier 9922) wird später in der SSH-Konfiguration auf dem Backup-System hinterlegt.

Schritt 2: ZFS-Wrapper auf Open-E erstellen
#

Da in der Rootconsole kein direkter Zugriff auf die ZFS-Binaries besteht, werden Wrapper-Skripte erstellt, die die Befehle über xcadmin an den Host weiterleiten.

Warum ein Wrapper nötig ist
#

In der Rootconsole sind ZFS-Befehle nicht als echte Binaries vorhanden, sondern nur als Shell-Aliases definiert. Ein alias in der Rootconsole zeigt das deutlich:

# output von "alias"
alias zfs='ssh xcadmin@host sudo zfs'
alias zpool='ssh xcadmin@host sudo zpool'
alias zdb='ssh xcadmin@host sudo zdb'
# ... und viele weitere (sg_*, smbstatus, iostat, htop, ...)

Jeder Befehl ist ein SSH-Aufruf, der über den Benutzer xcadmin an den Open-E Host weitergeleitet wird – teilweise mit sudo für Root-Rechte, teilweise mit -t für interaktive Programme wie htop oder top.

Das Problem: Shell-Aliases funktionieren nur in einer interaktiven Shell. Wenn zfs-autobackup per SSH einen Befehl wie zfs list ausführt, wird keine interaktive Shell gestartet – die Aliases existieren in diesem Kontext nicht. Deshalb werden stattdessen Wrapper-Skripte unter /usr/local/sbin/ erstellt, die im $PATH liegen und auch in nicht-interaktiven Sessions gefunden werden.

/usr/local/sbin/zfs erstellen:

#!/bin/sh
exec ssh xcadmin@host sudo zfs $*

/usr/local/sbin/zpool erstellen:

#!/bin/sh
exec ssh xcadmin@host sudo zpool $*

Beide Skripte ausführbar machen:

chmod +x /usr/local/sbin/zfs /usr/local/sbin/zpool

Kurzer Test direkt in der Rootconsole:

/usr/local/sbin/zfs list -t filesystem | head -5

Wenn eine Liste der Datasets erscheint, funktioniert der Wrapper korrekt.

Schritt 3: SSH-Key auf dem Backup-System erstellen
#

Auf dem Backup-System wird ein SSH-Schlüssel für die passwortlose Authentifizierung erstellt:

ssh-keygen -t ed25519

Den öffentlichen Schlüssel anschließend in der Open-E Rootconsole hinterlegen:

# In der Open-E Rootconsole:
mkdir -p /root/.ssh
# Den Inhalt von ~/.ssh/id_ed25519.pub (Backup-System) hier einfügen:
nano /root/.ssh/authorized_keys

Optional kann die command-Option einen Wrapper verwenden, der nur die für Pull-Replikation mit zfs_autobackup nötigen Befehle erlaubt: zfs list, zfs get, zfs send (kein destroy, create, receive usw.), zpool list/get/status sowie in Pipelines mbuffer. Der SSH-Key ist dann nicht mehr für beliebige Befehle nutzbar.

Wrapper-Skript (z. B. /root/.ssh/zfs-zpool-wrapper.sh auf der Open-E Rootconsole):

#!/bin/sh
cmd="$SSH_ORIGINAL_COMMAND"
allow=1
check_segment() {
  seg="$1"
  first=$(echo "$seg" | sed 's/^[ 	]*//;s/[ 	].*//')
  rest=$(echo "$seg" | sed 's/^[ 	]*[^ 	]*[ 	]*//')
  second=$(echo "$rest" | sed 's/^[ 	]*//;s/[ 	].*//')
  case "$first" in
    zfs)   case "$second" in list|get|send) ;; *) return 1 ;; esac ;;
    zpool) case "$second" in list|get|status) ;; *) return 1 ;; esac ;;
    mbuffer) ;;
    *) return 1 ;;
  esac
  return 0
}
IFS='|'
set -f
for seg in $cmd; do
  check_segment "$seg" || { allow=0; break; }
done
set +f
if [ "$allow" = 1 ]; then
  exec sh -c "$cmd"
else
  echo "$(date -Iseconds) from=${SSH_CLIENT:-unknown} cmd=$cmd" >> /root/ssh-zfs-wrapper-denied.log
  echo "Permission denied"; exit 1
fi

Abgelehnte Befehle werden in /root/ssh-zfs-wrapper-denied.log protokolliert.

Nach chmod +x /root/.ssh/zfs-zpool-wrapper.sh in authorized_keys eintragen:

command="/root/.ssh/zfs-zpool-wrapper.sh" ssh-ed25519 AAAA...

Schritt 4: SSH-Konfiguration auf dem Backup-System
#

Auf dem Backup-System wird eine SSH-Konfiguration angelegt, die die Verbindungen zu den Open-E Systemen vereinfacht und (optional) über ControlMaster persistent hält:

~/.ssh/config erstellen:

Host openenode1
    hostname 10.10.0.21
    port 9922
    user root

Host openenode2
    hostname 10.10.0.22
    port 9922
    user root

# Die Cluster IP vom pool HDD
Host openeservice-HDD
    hostname 10.10.0.24
    port 9922
    user root
# Die Cluster IP vom pool NVME1
Host openeservice-NVME
    hostname 10.10.0.23
    port 9922
    user root

# optional:
Host *
    ControlPath ~/.ssh/control-master-%r@%h:%p
    ControlMaster auto
    ControlPersist 3600

(Optional: Die ControlMaster-Einstellungen sorgen dafür, dass SSH-Verbindungen wiederverwendet werden – zfs-autobackup öffnet mehrere SSH-Sessions pro Lauf, und ohne ControlMaster würde jede Session einen neuen Verbindungsaufbau erfordern.)

Verbindung testen:

ssh openeservice-HDD zfs list

Bei Erfolg werden die ZFS-Datasets des Open-E Systems ausgegeben.

Schritt 5: Datasets für Backup markieren
#

Auf dem Open-E System werden die zu sichernden Datasets mit einem ZFS-Property markiert. zfs-autobackup nutzt dieses Property, um automatisch die richtigen Datasets zu erkennen.

Über die Rootconsole auf dem Open-E:

zfs set autobackup:backup-HDD=true poolHDD/share1
zfs set autobackup:backup-HDD=true poolHDD/share2

Der Name backup-HDD ist frei wählbar – er muss später beim Aufruf von zfs-autobackup übereinstimmen. Alle Datasets mit autobackup:backup-HDD=true werden automatisch in die Replikation aufgenommen, inkl. aller Child-Datasets.

Schritt 6: Pull-Skript erstellen
#

Auf dem Backup-System wird ein Skript erstellt, das die Replikation auslöst. flock verhindert, dass mehrere Instanzen gleichzeitig laufen:

/root/pull-openeservice-hdd.sh erstellen:

#!/bin/sh

flock -n /tmp/openeservice-hdd.lock \
  /usr/local/bin/zfs-autobackup \
    --ssh-source openeservice-HDD \
    backup-HDD \
    poolBACKUP/backups/openeservice-HDD \
    --other-snapshots \
    --no-snapshot \
    --clear-mountpoint \
    --no-holds \
    --keep-target="10,1h4d,1d4w,1w3m" \
    --zfs-compressed \
    --allow-empty \
    --buffer 500M \
    --verbose
chmod +x /root/pull-openeservice-hdd.sh
#
# Ziel-Dataset auf dem Backup-System erstellen
zfs create poolBACKUP/backups/openeservice-HDD

Parameter erklärt
#

ParameterBeschreibung
--ssh-source openeservice-HDDSSH-Host aus ~/.ssh/config als Quelle
backup-HDDName des autobackup-Properties (muss mit autobackup:backup-HDD übereinstimmen)
poolBACKUP/backups/openeservice-HDDZiel-Dataset auf dem Backup-System
--other-snapshotsAuch Snapshots übertragen, die nicht von zfs-autobackup erstellt wurden
--no-snapshotKeine neuen Snapshots auf der Quelle erstellen (Open-E erstellt eigene)
--clear-mountpointMountpoint der Ziel-Datasets auf none setzen
--no-holdsKeine ZFS Holds setzen (vermeidet Berechtigungsprobleme)
--keep-target="10,1h4d,1d4w,1w3m"Aufbewahrungsrichtlinie: 10 neueste, stündlich für 4 Tage, täglich für 4 Wochen, wöchentlich für 3 Monate
--zfs-compressedKomprimierte Übertragung (nutzt ZFS-eigene Kompression)
--allow-emptyLauf auch ohne neue Snapshots nicht als Fehler werten
--buffer 500M500 MB Buffer für stabilere Übertragung (buffer-Paket erforderlich)

Erster Test
#

/root/pull-openeservice-hdd.sh

Die Ausgabe zeigt den Fortschritt der Replikation: Welche Snapshots erkannt, übertragen und auf dem Ziel bereinigt werden.

Schritt 7: Automatisierung per Cron
#

Für regelmäßige Replikation einen Cron-Job auf dem Backup-System einrichten:

crontab -e

Beispiel – alle 30 Minuten:

*/30 * * * * /root/pull-openeservice-hdd.sh >> /var/log/zfs-backup-hdd.log 2>&1

Durch flock im Skript ist sichergestellt, dass ein laufender Replikationsvorgang nicht durch den nächsten Cron-Lauf unterbrochen wird.

Auf TrueNAS SCALE kann man den Cron-Job über die Web-GUI einrichten.

Mehrere Open-E Systeme sichern
#

Für jedes Open-E System bzw. jeden Pool wird ein eigenes Pull-Skript erstellt – die Struktur bleibt identisch:

# pull-openeservice-hdd.sh    → poolBACKUP/backups/openeservice-HDD
# pull-openeservice-nvme.sh   → poolBACKUP/backups/openeservice-NVME

Jedes Skript nutzt ein eigenes Lock-File, sodass die Replikationen parallel laufen können.

Fazit
#

Die Kombination aus zfs-autobackup, SSH und den ZFS-Wrapper-Skripten ermöglicht eine zuverlässige Snapshot-Replikation von Open-E JovianDSS auf ein beliebiges Linux-System mit ZFS – ohne dass auf dem Open-E System zusätzliche Software installiert werden muss (abgesehen von SSH und mbuffer im Rootconsole). Der Pull-Ansatz hat den Vorteil, dass das Backup-System die volle Kontrolle über Zeitpunkt und Aufbewahrung der Snapshots behält.

Für Fragen zur Implementierung oder spezifischen Anwendungsfällen bei der ZFS-Replikation stehe ich gerne zur Verfügung.


Wim Bonis ist CTO bei Stylite AG und beschäftigt sich schwerpunktmäßig mit Storage-Lösungen und IT-Infrastruktur.

Verwandte Artikel

Open-E JovianDSS mit Checkmk überwachen
Wim Bonis
Monitoring Storage Open Source
Stoßgebete aus dem Rechenzentrum: Was sich jeder Storage-Admin wirklich wünscht
Wim Bonis
Storage ZFS Security Monitoring
Hot Spares in ZFS: Warum ein Hot-Spare oft mehr Risiko als Nutzen bringt
Wim Bonis
Storage ZFS RAID Open-E TrueNAS
ZFS Snapshot-Replikation in TrueNAS SCALE: Remote Backup mit Push und Pull
Wim Bonis
Storage ZFS TrueNAS Backup Replikation
OpenZFS Virtualisierung: Storage-Lösungen für moderne Infrastrukturen
Wim Bonis
Storage Tools ZFS
Ransomware: Geschichte, Schutzmaßnahmen und ZFS als Verteidigungslinie
Wim Bonis
Storage Security ZFS
TrueNAS Fans aufgepasst: Neue Features und Updates
Wim Bonis
Storage News ZFS
FreeNAS, TrueNAS Core und OpenZFS: Ein Überblick
Wim Bonis
Storage Tools ZFS
Sonderzeichen in Dateinamen: Probleme mit SMB, WebDAV und Nextcloud
Wim Bonis
Storage ZFS Tools Samba Linux TrueNAS