Wer ZFS nutzt, kennt das Gefühl: Man hat Snapshots, man hat zfs send und zfs recv, und theoretisch ist alles möglich. Praktisch steht man dann vor einer Pipe aus drei Befehlen, fragt sich, ob --verbose vor oder hinter -R gehört, und stellt fest, dass der inkrementelle Sendevorgang um Mitternacht abgebrochen hat, weil irgendein Snapshot auf der Zielseite fehlte.
Genau hier setzt Syncoid an.
Was ist Syncoid?
Syncoid ist Teil des Sanoid-Projekts von Jim Salter und beschreibt sich selbst schlicht als Replikationstool für ZFS. Das klingt bescheidener, als es ist. Tatsächlich löst Syncoid genau die Probleme, die jeden treffen, der ernsthaft ZFS-Daten zwischen Maschinen bewegen will:
- Es findet selbst heraus, welcher Snapshot der letzte gemeinsame ist.
- Es erzeugt bei Bedarf einen neuen Snapshot auf der Quelle.
- Es überträgt inkrementell — nur die Differenz.
- Es funktioniert lokal und remote, als Push und als Pull.
- Es macht das alles mit einem einzigen Befehl.
Wer schon einmal versucht hat, eine ZFS-Replikation mit reinen Shell-Mitteln fehlerresistent aufzuziehen, weiß, dass das keine Kleinigkeit ist. Syncoid nimmt genau diesen Aufwand weg, ohne dabei die Kontrolle zu verlieren.
Die Grundlage: ZFS send und recv
Um zu verstehen, was Syncoid leistet, hilft ein Blick auf das, was es vereinfacht. ZFS bringt mit zfs send und zfs recv bereits ein mächtiges Werkzeug für die Replikation mit. Das Prinzip ist einfach: Ein Snapshot wird serialisiert und auf der anderen Seite wieder eingespielt. Inkrementell geht das auch — man sendet nur die Differenz zwischen zwei Snapshots.
In der Praxis sieht das dann so aus:
zfs send -R data/images/vm@syncoid_2026-04-07:12:00:00 | ssh remotehost "zfs recv backup/images/vm"
Das funktioniert. Bis es nicht mehr funktioniert. Weil ein Snapshot auf der Zielseite gelöscht wurde. Weil die SSH-Verbindung abbricht. Weil man vergessen hat, -I statt -i zu verwenden. Weil die Quellseite keine Snapshots hat, die die Zielseite erwartet.
Syncoid kümmert sich um all diese Fälle. Und das ist der eigentliche Mehrwert: nicht dass es zfs send aufruft — das kann jeder —, sondern dass es die Fehlerfälle abfängt, die im Alltag regelmäßig auftreten.
Loslegen: Einfacher geht es nicht
Die grundlegende Syntax ist so simpel, dass man sie sich kaum merken muss, weil sie offensichtlich ist:
syncoid data/images/vm backup/images/vm
Das repliziert den Dataset data/images/vm nach backup/images/vm — lokal, auf derselben Maschine. Beim ersten Lauf wird alles übertragen, bei jedem weiteren nur die Differenz.
Remote geht es genauso, nur mit dem üblichen SSH-Präfix:
syncoid data/images/vm root@remotehost:backup/images/vm
Das ist Push-Replikation: Die lokale Maschine sendet zum Remote. Pull geht auch:
syncoid root@remotehost:data/images/vm backup/images/vm
Hier zieht die lokale Maschine die Daten vom Remote. Der Unterschied mag marginal wirken, ist aber in der Praxis relevant: Pull bedeutet, dass die Backup-Maschine die Kontrolle hat und keinen SSH-Zugang zur Produktionsmaschine benötigt.
Rekursiv geht es mit -r:
syncoid -r rpool remotehost:tank/backup/rpool
Damit werden alle Child-Datasets unter rpool mit übertragen. Für ein vollständiges Backup ist das genau das, was man braucht.
Ohne Root: ZFS-Rechte delegieren
Einer der häufigsten Fehler bei ZFS-Backups ist, sie als root laufen zu lassen. Es funktioniert, aber es bedeutet, dass man root-SSH-Zugang zwischen Maschinen erlaubt. Das ist ein Sicherheitsrisiko, das sich vermeiden lässt.
Syncoid unterstützt den Betrieb ohne Root über --no-privilege-elevation. Dafür müssen auf beiden Seiten die entsprechenden ZFS-Berechtigungen delegiert werden:
Auf der Quellmaschine:
zfs allow -u syncuser send,hold,mount,snapshot,destroy rpool
Auf der Zielmaschine:
zfs allow -u syncuser compression,mountpoint,create,mount,receive,rollback,destroy tank/backup/rpool
Und dann:
syncoid --no-privilege-elevation -r rpool syncuser@remotehost:tank/backup/rpool
Das ist mehr Aufwand bei der Einrichtung, aber es ist der richtige Weg. Kein root-SSH, keine unnötigen Privilegien. Wenn man mit --use-hold arbeitet, kommt noch die release-Berechtigung dazu. Wer --create-bookmark nutzt, braucht bookmark auf der Quellseite.
Die Optionen, die man tatsächlich braucht
Syncoid hat eine überschaubare, aber nützliche Anzahl an Optionen. Die wichtigsten:
--compress: Kompression während der Übertragung. Unterstützt werden gzip, pigz-fast, pigz-slow, zstd-fast, zstd-slow, lz4, xz, lzo (Standard) und none. Wer über ein LAN synchronisiert, kann none wählen; über WAN ist zstd-fast eine gute Wahl.
--no-sync-snap: Standardmäßig erzeugt Syncoid bei jedem Lauf einen eigenen Snapshot. Wer das nicht möchte — etwa weil Sanoid die Snapshot-Verwaltung übernimmt oder weil man in ein Multi-Target-Setup repliziert —, der schaltet das mit --no-sync-snap ab. Verhindert die Anhäufung von Syncoid-Snapshots auf der Zielseite.
--create-bookmark: Setzt auf der Quelle ein Lesezeichen für den letzten erfolgreich replizierten Snapshot. Das ist besonders nützlich bei unregelmäßiger Replikation: Wenn der letzte gemeinsame Snapshot auf der Quelle bereits gelöscht wurde, kann das Bookmark den Zugriff auf den benötigten Punkt trotzdem ermöglichen. Funktioniert nur zusammen mit --no-sync-snap.
--use-hold: Setzt einen Hold auf den neuesten Snapshot auf Quell- und Zielseite und entfernt ihn erst nach dem nächsten erfolgreichen Lauf. Das verhindert, dass ein Snapshot gelöscht wird, bevor er repliziert wurde. Bei Multi-Target-Setups (A→B, A→C) kann man mit --identifier unterschiedliche Holds pro Ziel setzen.
--no-stream: Statt -I (alle Zwischensnapshots) wird -i (nur der neueste Snapshot) verwendet. Spart Bandbreite, wenn man die Zwischenschritte nicht braucht.
--exclude-datasets=REGEX: Schließt bestimmte Datasets von der Replikation aus. Kann mehrfach angegeben werden.
--source-bwlimit und --target-bwlimit: Bandbreitenlimitierung, falls mbuffer nicht verfügbar ist. Nützlich, wenn man die Übertragung nicht die ganze Leitung blockieren lassen möchte.
Snapshots und Pruning
Ein wichtiger Punkt: Syncoid ist agnostisch gegenüber der Snapshot-Verwaltung. Es löscht keine Snapshots auf der Zielseite, nur weil sie auf der Quelle gelöscht wurden. Das ist kein Fehler, sondern ein Feature — es schützt vor Datenverlust.
Für das Aufräumen alter Snapshots auf der Zielseite empfiehlt sich Sanoid mit einer Konfiguration wie dieser:
[backup/images/vm]
autoprune = yes
autosnap = no
frequently = 0
hourly = 36
daily = 30
monthly = 6
yearly = 0
autosnap = no, weil die Snapshots von Syncoid kommen und nicht von Sanoid erzeugt werden sollen. autoprune = yes, um alte Snapshots nach den definierten Regeln aufzuräumen. Das lässt sich mit Templates auch für viele Datasets gleichzeitig konfigurieren.
Oder, kürzer, mit einem Template:
[template_backup]
autoprune = yes
autosnap = no
hourly = 36
daily = 30
monthly = 6
[backup/images]
use_template = backup
recursive = yes
Die Kombination aus Syncoid für die Replikation und Sanoid für das Pruning ist das, was die meisten produktiven Setups verwenden. Und sie funktioniert genau deshalb gut, weil beide Werkzeuge ihre Zuständigkeit klar abgrenzen.
Praktisches Setup: Ein vollständiges Beispiel
Angenommen, man hat einen Server prod mit dem Pool zdata und einen Backup-Server backup mit dem Pool tank. Ziel: Tägliches inkrementelles Backup aller Datasets.
1. Sanoid auf prod einrichten (für die Snapshot-Erstellung):
[zdata]
use_template = production
[template_production]
frequently = 0
hourly = 36
daily = 30
monthly = 3
yearly = 0
autosnap = yes
autoprune = yes
2. Cron-Job auf backup (Pull-Replikation):
0 2 * * * syncoid --no-sync-snap --compress=zstd-fast -r syncuser@prod:zdata tank/backup/zdata
3. Sanoid auf backup (für das Pruning):
[tank/backup/zdata]
use_template = backup
[template_backup]
autoprune = yes
autosnap = no
hourly = 36
daily = 30
monthly = 6
yearly = 0
Das ist im Grunde das komplette Setup. Drei Konfigurationsschritte, ein Cron-Job, und man hat eine robuste, inkrementelle ZFS-Replikation, die im Hintergrund läuft, ohne dass man sich darum kümmern muss.
Was man beachten sollte
Ein paar Dinge, die in der Dokumentation eher am Rande stehen, aber im Alltag relevant werden:
SSH-Konfiguration: Syncoid baut für jeden Lauf eine neue SSH-Verbindung auf. Bei häufiger Replikation lohnt sich ein Connection Multiplexing in der ~/.ssh/config:
Host backupserver
HostName 192.168.1.50
User syncuser
ControlMaster auto
ControlPath ~/.ssh/sockets/%r@%h-%p
ControlPersist 600
Das spart den Verbindungsaufbau bei jedem Lauf.
mbuffer: Wenn auf beiden Seiten mbuffer verfügbar ist, nutzt Syncoid es automatisch. Das kann die Übertragungsrate deutlich verbessern, weil es die Pipeline puffert und verhindert, dass zfs send auf zfs recv warten muss.
Erstlauf dauert: Der erste Syncoid-Lauf überträgt den kompletten Dataset. Bei mehreren Terabyte bedeutet das: Zeit einplanen. Alle folgenden Läufe sind inkrementell und entsprechend schneller.
Kein Konfigurationsfile: Im Gegensatz zu Sanoid hat Syncoid keine Konfigurationsdatei. Alles wird über Kommandozeilen-Flags gesteuert. Das ist konsistent, bedeutet aber auch, dass man bei komplexeren Setups die Aufrufe entsprechend dokumentieren sollte.
Warum Syncoid und nicht rsync?
Die Frage ist naheliegend. rsync ist etabliert, gut dokumentiert und funktioniert auf jedem System. Aber rsync kennt ZFS nicht. Es kann nicht inkrementell auf Snapshot-Ebene arbeiten, es kann keine Block-Differenzierung nutzen, und es kann nicht garantieren, dass der Zielzustand konsistent ist.
ZFS-Snapshots sind atomar. Ein Snapshot repräsentiert den exakten Zustand eines Datasets zu einem bestimmten Zeitpunkt. Wenn man den repliziert, erhält man auf der Zielseite exakt diesen Zustand — nicht einen Zustand, bei dem einige Dateien schon aus dem Snapshot stammen und andere gerade im Flux sind.
Das ist kein akademischer Unterschied. Wer schon einmal ein Datenbank-Backup mit rsync gemacht hat und feststellen musste, dass die Dateien während der Übertragung verändert wurden, weiß, wovon die Rede ist.
Fazit
Syncoid ist eines dieser Werkzeuge, die man sich früher wünscht. Es nimmt einen wiederkehrenden, fehleranfälligen Prozess — ZFS-Replikation per Hand — und macht ihn zu einem einzelnen Befehl, der funktioniert. Nicht weil er Magie einsetzt, sondern weil er die Randfälle abdeckt, die man selbst immer vergisst: fehlende Snapshots, abgebrochene Verbindungen, falsche Flags.
Wer ZFS einsetzt und nicht bereits ein etabliertes Replikations-Setup hat, sollte Syncoid ausprobieren. Die Einstiegshürde ist minimal, der Nutzen ist sofort spürbar, und falls man doch mehr Kontrolle braucht: Die Optionen sind da, man muss sie nur nutzen.
Und wer Sanoid für die Snapshot-Verwaltung ohnehin schon im Einsatz hat — der hat Syncoid bereits installiert. Es ist Teil desselben Pakets. Man muss es nur nutzen.
Quellen