Managing and Pruning ZFS Snapshots with Native Properties and Sanoid

2 min read

Automated snapshotting protects datasets against accidental file deletion and ransomware. However, unmonitored snapshots on high-churn datasets (like temporary downloads, virtual machine disks, or scratch volumes) quickly consume available pool capacity.

Here is how to manage, exclude, and prune ZFS snapshots cleanly on modern Linux and TrueNAS.

⚡ Quick Runbook: 60-Second Implementation

TL;DR: Copy and deploy the baseline production definition directly onto your host:

# Disable automated snapshots on a specific dataset
sudo zfs set com.sun:auto-snapshot=false tank/downloads
sudo zfs set com.sun:auto-snapshot=false tank/temp

1. Excluding Datasets from Snapshot Automation

If you use snapshot automation tools (like zfs-auto-snapshot), you do not need complex exclusion scripts. Simply set the dataset’s user property:

# Disable automated snapshots on a specific dataset
sudo zfs set com.sun:auto-snapshot=false tank/downloads
sudo zfs set com.sun:auto-snapshot=false tank/temp

To re-enable at any time:

sudo zfs inherit com.sun:auto-snapshot tank/downloads

2. Mass Deleting Stale Snapshots Safely

When an automated script creates thousands of snapshots that must be cleared, avoid slow iterative loops. Use ZFS snapshot range syntax:

# List all snapshots for a dataset
zfs list -t snapshot -r tank/scratch

# Batch destroy a range of sequential snapshots
# Syntax: zfs destroy dataset@earliest_snap%latest_snap
sudo zfs destroy tank/scratch@auto-snap_hourly-2024-01-01%auto-snap_hourly-2024-06-01

# Filter and delete all snapshots matching a specific pattern
zfs list -H -t snapshot -o name -r tank/scratch | grep 'auto-snap' | xargs -n 1 sudo zfs destroy

3. Recommended Modern Tooling: Sanoid / Syncoid

In modern production deployments, Sanoid provides granular, declarative policy management over legacy cron scripts:

# /etc/sanoid/sanoid.conf
[tank/media]
    use_template = production
    frequently = 0
    hourly = 24
    daily = 30
    monthly = 3
    yearly = 0
    autosnap = yes
    autoprune = yes

[tank/temp]
    autosnap = no
    autoprune = no

Related Runbooks in This Series

Tags:

← Previous:
Next: →