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:
- Das Backup-System startet
zfs-autobackupim Pull-Modus - Das Tool verbindet sich per SSH zur Rootconsole auf Open-E (Port 9922)
- In der Rootconsole leitet ein Wrapper-Skript die ZFS-Befehle an den Open-E Host weiter
- Die Snapshots werden per
zfs send | zfs receiveauf 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:
- Das
.upd-Paket von Open-E FTP herunterladen (passend zur installierten JovianDSS-Version) - In der Web-Oberfläche unter System Settings → Update hochladen und installieren
- 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#
| Parameter | Beschreibung |
|---|---|
--ssh-source openeservice-HDD | SSH-Host aus ~/.ssh/config als Quelle |
backup-HDD | Name des autobackup-Properties (muss mit autobackup:backup-HDD übereinstimmen) |
poolBACKUP/backups/openeservice-HDD | Ziel-Dataset auf dem Backup-System |
--other-snapshots | Auch Snapshots übertragen, die nicht von zfs-autobackup erstellt wurden |
--no-snapshot | Keine neuen Snapshots auf der Quelle erstellen (Open-E erstellt eigene) |
--clear-mountpoint | Mountpoint der Ziel-Datasets auf none setzen |
--no-holds | Keine 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-compressed | Komprimierte Übertragung (nutzt ZFS-eigene Kompression) |
--allow-empty | Lauf auch ohne neue Snapshots nicht als Fehler werten |
--buffer 500M | 500 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.
