← Back to posts
comparison guide self-hosted · · 11 min read

Sanoid vs ZnapZend vs Syncoid: Best ZFS Snapshot Tools 2026

Compare Sanoid, ZnapZend, and Syncoid for ZFS snapshot management and replication. Learn which tool best fits your backup strategy with installation guides, config examples, and feature comparisons.

OS
Editorial Team

If you run a self-hosted server on ZFS, the single most important thing you can do to protect your data is take regular snapshots — and make sure those snapshots get replicated offsite. ZFS itself provides the building blocks: zfs snapshot, zfs send, and zfs receive. But managing retention policies, scheduling, and remote replication by hand quickly becomes unmanageable.

This guide compares three open-source tools that automate ZFS snapshot lifecycle management: Sanoid, ZnapZend, and Syncoid. Each takes a different approach to the same problem, and understanding their differences will help you pick the right one for your infrastructure.

For readers evaluating broader backup strategies, our Restic vs Borg vs Kopia comparison covers file-level backup tools that complement ZFS snapshot management. If you are setting up a NAS from scratch, the self-hosted NAS solutions guide covers TrueNAS (which bundles Sanoid/Syncoid by default) alongside OpenMediaVault and Rockstor.

Why ZFS Snapshots Matter for Self-Hosted Infrastructure

ZFS snapshots are instantaneous, space-efficient, read-only copies of a filesystem at a point in time. Unlike traditional backups, they are:

  • Near-zero overhead — snapshots use copy-on-write; only changed blocks consume additional space
  • Instantaneous — creating a snapshot takes milliseconds regardless of dataset size
  • Crash-consistent — no need to stop services or flush buffers before snapshotting
  • Rollback-ready — restore individual files or entire datasets in seconds

However, snapshots alone are not a backup strategy. They live on the same pool as the original data. If the pool fails, all snapshots go with it. You need replication — sending snapshots to a separate system or offsite location. That is where these three tools come in: they automate both the snapshot lifecycle (creation and pruning) and the replication to remote targets.

Tool Overview at a Glance

FeatureSanoidZnapZendSyncoid
Primary purposeSnapshot management + policy engineSnapshot + replication combinedReplication-only (remote send/recv)
Repositoryjimsalterjrs/sanoidoetiker/znapzendPart of Sanoid repo
GitHub stars3,738672Bundled with Sanoid
LanguagePerlPerlPerl
Last updatedFeb 2026Apr 2026Feb 2026
Config formatTOML (/etc/sanoid/sanoid.conf)ZFS properties (dataset-level)CLI arguments
Schedulingsystemd timer or cronBuilt-in daemoncron or manual
Encryption in transitVia SSH (same as ZFS send)Via SSH with mbuffer supportVia SSH
Remote replicationVia Syncoid (separate tool)Built-inYes (the core function)
Docker supportNo official imageOfficial DockerfileNo official image
Best forPolicy-driven local snapshot managementAll-in-one snapshot + remote replicationFast remote replication between ZFS hosts

Sanoid: Policy-Driven Snapshot Management

Sanoid is the most widely adopted ZFS snapshot management tool in the open-source community. Its core strength is a simple, human-readable TOML configuration file that defines retention policies per dataset — and even per-dataset overrides of those policies.

How Sanoid Works

Sanoid runs as a cron job (typically every minute). On each invocation, it:

  1. Reads /etc/sanoid/sanoid.conf
  2. Checks each configured dataset against its assigned template
  3. Creates new snapshots if needed (hourly, daily, weekly, monthly, yearly)
  4. Prunes old snapshots that exceed retention limits
  5. Optionally runs Syncoid to replicate snapshots to remote hosts

Sanoid Installation on Debian/Ubuntu

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# Install prerequisites
sudo apt install -y debhelper libcapture-tiny-perl libconfig-inifiles-perl \
  pv lzop mbuffer build-essential git

# Clone and build the package
cd /tmp
git clone https://github.com/jimsalterjrs/sanoid.git
cd sanoid
git checkout $(git tag | grep "^v" | tail -n 1)
ln -s packages/debian .
dpkg-buildpackage -uc -us
sudo apt install ../sanoid_*_all.deb

# Enable the systemd timer
sudo systemctl enable --now sanoid.timer

Sanoid Configuration Example

The configuration file at /etc/sanoid/sanoid.conf uses templates that datasets inherit:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# Datasets using the production template
[data/home]
    use_template = production

[data/www]
    use_template = production
    recursive = yes
    process_children_only = yes

[data/www/app]
    # Override: keep more hourly snapshots for this critical dataset
    hourly = 48

#################################
# Template definitions
#################################

[template_production]
    frequently = 4        # Every 15 minutes (4 per hour)
    hourly = 36           # Keep 36 hourly snapshots
    daily = 30            # Keep 30 daily snapshots
    weekly = 4            # Keep 4 weekly snapshots
    monthly = 3           # Keep 3 monthly snapshots
    yearly = 1            # Keep 1 yearly snapshot
    autosnap = yes        # Auto-create snapshots via cron
    autoprune = yes       # Auto-delete expired snapshots

Sanoid’s TOML config is easy to read and modify. The template system means you define policies once and apply them to dozens of datasets, with per-dataset overrides when needed.

Replication with Syncoid

Sanoid does not handle remote replication itself. Instead, it works alongside Syncoid — which ships in the same repository. Syncoid performs efficient zfs send | zfs receive over SSH:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Replicate a dataset to a remote host
syncoid root@source-host:data/home root@backup-host:pool/backups/home

# Recursive replication of all child datasets
syncoid -r root@source-host:data root@backup-host:pool/backups

# Compressed and encrypted replication over SSH
syncoid --compress=lz4 root@source-host:data/www root@backup-host:pool/www-backup

# Dry run — see what would be transferred
syncoid --dry-run root@source-host:data/home root@backup-host:pool/backups/home

Syncoid automatically determines which snapshots already exist on the target and only sends incremental differences. It also supports mbuffer for smoother streaming over high-latency links.

ZnapZend: All-in-One Snapshot and Replication

ZnapZend takes a fundamentally different approach. Instead of a separate config file, it stores backup policies directly as ZFS dataset properties. This means the backup configuration travels with the dataset — if you clone or move a filesystem, its backup policy comes with it.

How ZnapZend Works

ZnapZend runs as a daemon (znapzend) that continuously monitors configured datasets. Each dataset has properties like:

  • znapzend:enable — turn backup on or off
  • znapzend:plan — a predefined retention plan (e.g., 1month=>1d,1week=>1h,1day=>15min)
  • znapzend:dst_0 — the first destination (local or remote)
  • znapzend:dst_1 — an optional second destination (for offsite)

ZnapZend Installation

ZnapZend can be installed from packages or built from source. For Docker environments, an official image is available:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# From source (Debian/Ubuntu)
sudo apt install -y build-essential autoconf automake perl mbuffer
cd /tmp
git clone https://github.com/oetiker/znapzend.git
cd znapzend
./bootstrap.sh
./configure --prefix=/opt/znapzend
make && sudo make install

# Create symlinks
sudo ln -s /opt/znapzend/bin/znapzend /usr/bin/znapzend
sudo ln -s /opt/znapzend/bin/znapzendzetup /usr/bin/znapzendzetup

ZnapZend Docker Setup

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
version: "3.8"

services:
  znapzend:
    image: oetiker/znapzend:latest
    privileged: true
    volumes:
      - /dev/zfs:/dev/zfs
      - /etc/zfs:/etc/zfs
      - /root/.ssh:/root/.ssh:ro
    environment:
      - TZ=UTC
    command: znapzend --logto=/dev/stdout
    restart: unless-stopped

Note that ZFS requires privileged access and host device mounts, so running ZnapZend in Docker requires careful volume and device configuration. For most production setups, installing directly on the host is simpler.

ZnapZend Configuration

ZnapZend uses its znapzendzetup CLI to configure dataset properties:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# Create a backup plan for a dataset
# Format: znapzendzetup create <plan> <destination> <source-dataset>
sudo znapzendzetup create --recursive \
  '1year=>1month,3month=>1week,4week=>1day,7day=>4hour,1day=>15min' \
  root@backup-server:pool/backups \
  pool/data/home

# View the configured plan
znapzendztatz pool/data/home

# Enable the daemon
sudo systemctl enable --now znapzend

The plan syntax is compact: retention_count=>retention_interval. The example above keeps snapshots for 1 year (1 per month), 3 months (1 per week), 4 weeks (1 per day), 7 days (1 every 4 hours), and 1 day (1 every 15 minutes).

You can also add a second destination for offsite replication:

1
2
3
4
5
sudo znapzendzetup create --recursive \
  '1year=>1month,3month=>1week,4week=>1day,7day=>4hour,1day=>15min' \
  root@backup-server:pool/backups \
  root@offsite-server:pool/offsite \
  pool/data/home

Direct Feature Comparison

Retention Policy Management

AspectSanoidZnapZend
Config locationCentral TOML fileZFS dataset properties
Template systemYes — reusable templatesPlans with interval syntax
Per-dataset overridesYes — inline in configYes — set property per dataset
Config backupFile can be versioned in gitProperties stored in ZFS metadata
Ease of auditSingle file to reviewMust query each dataset

Sanoid’s central config file is easier to review at a glance — you can see every dataset’s policy in one file. ZnapZend’s property-based approach means you need to query each dataset individually (zfs get all <dataset>), but the configuration is inherently portable with the dataset.

Replication Capabilities

AspectSyncoid (Sanoid)ZnapZend
Incremental sendsYesYes
Compressionlz4, gzip, zstdVia mbuffer
EncryptionVia SSHVia SSH
Multiple destinationsRun multiple syncoid commandsBuilt-in (dst_0, dst_1)
Bandwidth limitingVia mbufferVia mbuffer
Pre/post hooksNoLimited
Resume interrupted sendsYesYes

ZnapZend has a slight edge for multi-destination setups since it natively supports a primary and secondary target. With Syncoid, you need to run separate replication commands for each destination.

Monitoring and Health Checks

AspectSanoidZnapZend
Pool health checksYes — warns on degraded poolsNo
Snapshot monitoringYes — checks snapshot count vs expectedYes — tracks last successful send
Syslog integrationYesYes
Prometheus metricsThird-party exporters existccremer/znapzend-exporter
Email alertsVia cron outputVia syslog

Which Tool Should You Choose?

Choose Sanoid (+ Syncoid) if:

  • You want a centralized, auditable config file that is easy to version control
  • You need flexible, template-based retention policies with per-dataset overrides
  • You are running TrueNAS Core or Scale — Sanoid/Syncoid comes pre-installed
  • You want the most battle-tested tool with the largest user community (3,700+ stars)
  • Your primary concern is local snapshot management with occasional replication

Choose ZnapZend if:

  • You want an all-in-one daemon that handles both snapshots and replication
  • You prefer configuration stored as ZFS properties that travel with the dataset
  • You need built-in multi-destination replication (primary + offsite)
  • You want an official Docker image for containerized deployments
  • You like the compact retention plan syntax (1year=>1month,3month=>1week)

Choose Syncoid standalone if:

  • You only need fast, efficient remote replication without snapshot management
  • You already have a separate snapshot scheduler (e.g., a custom cron job)
  • You want the lightest possible tool — just send/receive over SSH
  • You need one-shot replication scripts for ad-hoc data migration

For most self-hosted setups, we recommend this architecture:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
┌─────────────────────────────────────────────────────┐
│  Primary Server (Sanoid + Syncoid)                  │
│  ┌─────────────┐    ┌─────────────┐                 │
│  │  Sanoid     │    │  Syncoid    │                 │
│  │  snapshots  │───>│  replicate  │                 │
│  └─────────────┘    └──────┬──────┘                 │
└────────────────────────────┼────────────────────────┘
                             │ SSH + ZFS send
┌─────────────────────────────────────────────────────┐
│  Backup Server (ZFS pool)                           │
│  Receives incremental snapshots, keeps retention    │
│  For multi-site: ZnapZend on backup pushes offsite  │
└─────────────────────────────────────────────────────┘

Run Sanoid on your primary server to manage local snapshots. Use Syncoid on a cron schedule (e.g., every 6 hours) to replicate to your backup server. If you need a tertiary offsite copy, consider adding ZnapZend on the backup server to push to a cloud or third location.

For readers interested in Kubernetes-native backup approaches, the Velero vs Stash vs Volsync guide covers container-level backup orchestration that complements ZFS-level protection.

FAQ

What is the difference between Sanoid and Syncoid?

Sanoid and Syncoid are separate tools that ship in the same repository. Sanoid manages the local snapshot lifecycle — it creates snapshots on a schedule and prunes them based on retention policies defined in a TOML config file. Syncoid handles replication — it sends ZFS snapshots from one system to another over SSH. They are designed to work together but can also be used independently. You can use Syncoid without Sanoid (if you manage snapshots manually), and you can use Sanoid without Syncoid (if you only need local snapshots).

Can I use ZnapZend and Sanoid on the same system?

Technically yes, but it is not recommended. Both tools create and manage snapshots, and running both against the same datasets will lead to conflicts — duplicate snapshots, unexpected pruning, and potential data loss. Pick one tool and stick with it across your infrastructure. If you have existing Sanoid configurations, migrating to ZnapZend (or vice versa) requires careful planning to avoid losing snapshot history during the transition.

Does ZFS snapshot replication encrypt data in transit?

Yes. Both Sanoid/Syncoid and ZnapZend use SSH to tunnel zfs send output to the remote host. This means all data is encrypted in transit using SSH’s built-in encryption. For added security, you can use SSH key-based authentication with restricted keys (using command="zfs receive ..." in authorized_keys) to limit what the backup server can do on the source system.

How much disk space do ZFS snapshots consume?

ZFS snapshots are space-efficient. When you create a snapshot, it initially consumes zero additional space — it simply marks the current state of all blocks as “referenced.” As data changes, only the modified blocks consume additional space (the old versions are retained for the snapshot). A typical server with moderate write activity might use 5-15% of pool capacity for a 30-day snapshot retention. Monitoring with zfs list -t snapshot shows the REFER and USED columns for each snapshot, helping you identify which datasets generate the most snapshot overhead.

Can I restore individual files from a ZFS snapshot?

Yes. ZFS snapshots are mounted read-only under .zfs/snapshot/<snapshot-name>/ within the dataset. You can browse this hidden directory and copy files out normally:

1
2
3
4
5
6
# List available snapshots
ls -la /pool/data/.zfs/snapshot/

# Copy a single file from a snapshot
cp /pool/data/.zfs/snapshot/zfs-auto-snap_daily-2026-04-20-00h00/documents/report.pdf \
   /pool/data/documents/

No zfs rollback is needed for individual file recovery — just browse and copy.

Is ZnapZend’s Docker image production-ready?

The official ZnapZend Docker image (oetiker/znapzend) works, but running ZFS tools in containers requires careful configuration. You need --privileged, host device mounts (/dev/zfs), and SSH keys mounted into the container. For production use, installing directly on the host OS is generally simpler and more reliable. Docker makes sense for testing or for environments where you must containerize everything, but the extra complexity rarely justifies it for a backup daemon that needs deep system access anyway.

Advertise here
Advertise here