Skip to content
daniel@cosenza:~/blog
FreeBSDHow-To October 14, 2025 3 min read

How to Automate ZFS Snapshots with periodic

Set up hourly, daily, and weekly ZFS snapshots on a schedule, with automatic pruning, using FreeBSD's built-in periodic framework — no third-party tools required.

This sets up a complete, automated snapshot schedule for a ZFS dataset — hourly, daily, and weekly snapshots, each retained for an appropriate window and pruned automatically, using tools already present in the FreeBSD base system.

Step 1: confirm periodic is already scheduled

FreeBSD’s cron runs /etc/periodic scripts automatically via default crontab entries that ship with the base system — you generally don’t need to add these yourself, only enable the ZFS snapshot module specifically.

crontab -l -u root

You should see entries invoking periodic daily, periodic weekly, and (if configured) periodic hourly already.

Step 2: enable hourly periodic, if not already active

Hourly periodic isn’t enabled by default on a stock install — add it explicitly:

# /etc/crontab (or a root crontab entry)
0  *  *  *  *  root  periodic hourly

Step 3: configure the ZFS snapshot periodic settings

FreeBSD’s periodic framework includes a built-in ZFS snapshot module, controlled entirely through /etc/periodic.conf:

# /etc/periodic.conf
daily_scrub_zfs_enable="YES"

daily_snapshot_zfs_enable="YES"
daily_snapshot_zfs_keep="7"

weekly_snapshot_zfs_enable="YES"
weekly_snapshot_zfs_keep="4"

hourly_snapshot_zfs_enable="YES"
hourly_snapshot_zfs_keep="24"

This configuration keeps the last 24 hourly snapshots, 7 daily snapshots, and 4 weekly snapshots — a reasonable general-purpose retention window, automatically pruning older snapshots as new ones are created.

Step 4: choose which datasets get snapshotted

By default, the periodic ZFS snapshot scripts operate on datasets with the com.sun:auto-snapshot property set to true:

zfs set com.sun:auto-snapshot=true zroot/home
zfs set com.sun:auto-snapshot=false zroot/tmp

Explicitly disabling it on datasets like a scratch/tmp dataset avoids wasting snapshot space on data that’s deliberately transient and never needs a rollback point.

Step 5: test it manually before waiting for the schedule

periodic hourly
zfs list -t snapshot

Running it manually once confirms the configuration works correctly before relying on the scheduled cron invocation, and immediately shows you the snapshot naming convention it uses (typically dataset@zfs-auto-snap_hourly-YYYY-MM-DD-HHMM).

Step 6: verify pruning actually works over time

zfs list -t snapshot -o name,creation -s creation | grep hourly

After the configured retention count is exceeded, confirm older snapshots are actually being removed automatically rather than accumulating indefinitely — a misconfigured _keep value or a typo in a periodic.conf variable name can silently disable pruning while snapshot creation continues, slowly consuming space.

Step 7: check space consumption periodically

zfs list -o space zroot/home

Recall that snapshots aren’t free once the live dataset diverges from them — USEDSNAP in this output shows exactly how much space your retained snapshots are consuming, which is worth checking occasionally to confirm your retention windows are appropriately sized for your actual rate of change.

Why the built-in periodic framework, not a third-party tool

FreeBSD’s periodic-based ZFS snapshot automation ships in the base system, requires no additional package installation, and integrates directly with the same cron/periodic framework already handling every other scheduled maintenance task on the system — for straightforward hourly/daily/weekly retention needs, it’s a more maintainable choice than adding a separate third-party snapshot management tool with its own configuration format and dependencies.