Skip to Content

Schedule ZFS Snapshots Using zfs-auto-snapshot

The ZFS Tools package offers an easy way to automatically create a rotating set of ZFS snapshots for backup purposes. Here’s how to set it up.

$ su
Password:

# pkg install zfstools
[...]

Message from zfstools-0.3.6_1:
--
To enable automatic snapshots, place lines such as these into /etc/crontab:

    PATH=/etc:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin
    15,30,45 * * * * root /usr/local/sbin/zfs-auto-snapshot frequent  4
    0        * * * * root /usr/local/sbin/zfs-auto-snapshot hourly   24
    7        0 * * * root /usr/local/sbin/zfs-auto-snapshot daily     7
    14       0 * * 7 root /usr/local/sbin/zfs-auto-snapshot weekly    4
    28       0 1 * * root /usr/local/sbin/zfs-auto-snapshot monthly  12

This will keep 4 15-minutely snapshots, 24 hourly snapshots, 7 daily snapshots,
4 weekly snapshots and 12 monthly snapshots. Any resulting zero-sized snapshots
will be automatically cleaned up.

Enable snapshotting on a dataset or top-level pool with:

    zfs set com.sun:auto-snapshot=true DATASET

Children datasets can be disabled for snapshot with:

    zfs set com.sun:auto-snapshot=false DATASET

Or for specific intervals:

    zfs set com.sun:auto-snapshot:frequent=false DATASET

See website and command usage output for further details.

During installation, the zfstools installer prints a set of cron commands to create a basic snapshot rotation. It says that the lines can be added to /etc/crontab, which is the system crontab, but the FreeBSD handbook warns that the system crontab should not be modified. Instead, the handbook recommends the creation of a separate user crontab to run cron jobs as root.

Note that the cron text given by the zfstools installer is formatted for the system crontab, in which the 6th column specifies the user who should run the cron job. To use those lines in a user crontab instead, delete the 6th column of text from each line, which is the column containing the word root.

To create a user crontab for the root user, run crontab -e -u root, then add the header lines specified in section 11.3.1 of the handbook, followed by the crontab lines (without the 6th column) copied from the zfstools installer output. After creating the root user crontab, double-check the schedule using crontab -l.

# crontab -e -u root
[...]

# crontab -l
SHELL=/bin/sh
PATH=/etc:/bin:/sbin:/usr/bin:/usr/sbin

# Order of crontab fields
# minute hour mday month wday command

# Periodic ZFS Snapshots
PATH=/etc:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin
15,30,45 *    *    *     *    /usr/local/sbin/zfs-auto-snapshot frequent  4
0        *    *    *     *    /usr/local/sbin/zfs-auto-snapshot hourly   24
7        0    *    *     *    /usr/local/sbin/zfs-auto-snapshot daily     7
14       0    *    *     7    /usr/local/sbin/zfs-auto-snapshot weekly    4
28       0    1    *     *    /usr/local/sbin/zfs-auto-snapshot monthly  12

The script will only create snapshots for datasets that have their com.sun:auto-snapshot property set to true, and the snapshot property will automatically be inherited by all descendants of that dataset unless disabled further down the tree.

It is not necessary to snapshot every dataset on the system; Michael W. Lucas recommends disabling snapshots for datasets that can be easily recreated if needed and for those for which old versions of the files are not generally useful:

  • /tmp
  • /usr/obj
  • /usr/ports
  • /usr/ports/distfiles
  • /usr/ports/packages
  • /usr/src
  • /var/crash
  • /var/empty
  • /var/run
  • /var/tmp

I also disable snapshots on /zroot/iocage/images and zroot/reserved.

After disabling snapshots for the non-essential datasets, some of which might not exist, enable them for zroot.

# zpool list
NAME    SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
zroot  3.62T  10.3G  3.61T        -         -     0%     0%  1.00x  ONLINE  -

# zfs list
NAME                                      USED  AVAIL  REFER  MOUNTPOINT
zroot                                    10.3G  3.50T    96K  /zroot
zroot/ROOT                               4.01G  3.50T    96K  none
zroot/ROOT/default                       4.01G  3.50T  4.01G  /
[...]

# zfs set com.sun:auto-snapshot=false zroot/tmp
# zfs set com.sun:auto-snapshot=false zroot/usr/obj
# zfs set com.sun:auto-snapshot=false zroot/usr/ports
# zfs set com.sun:auto-snapshot=false zroot/usr/ports/distfiles
# zfs set com.sun:auto-snapshot=false zroot/usr/ports/packages
# zfs set com.sun:auto-snapshot=false zroot/usr/src
# zfs set com.sun:auto-snapshot=false zroot/var/crash
# zfs set com.sun:auto-snapshot=false zroot/var/empty
# zfs set com.sun:auto-snapshot=false zroot/var/run
# zfs set com.sun:auto-snapshot=false zroot/var/tmp

# zfs set com.sun:auto-snapshot=false zroot/iocage/images
# zfs set com.sun:auto-snapshot=false zroot/reserved

# zfs set com.sun:auto-snapshot=true zroot

# zfs get com.sun:auto-snapshot
NAME                PROPERTY               VALUE    SOURCE
zroot               com.sun:auto-snapshot  true     local
zroot/ROOT          com.sun:auto-snapshot  true     inherited from zroot
zroot/ROOT/default  com.sun:auto-snapshot  true     inherited from zroot
zroot/iocage/images com.sun:auto-snapshot  false    local
zroot/reserved      com.sun:auto-snapshot  false    local
zroot/tmp           com.sun:auto-snapshot  false    local
zroot/usr           com.sun:auto-snapshot  true     inherited from zroot
zroot/usr/home      com.sun:auto-snapshot  true     inherited from zroot
zroot/usr/ports     com.sun:auto-snapshot  false    local
zroot/usr/src       com.sun:auto-snapshot  false    local
zroot/var           com.sun:auto-snapshot  true     inherited from zroot
zroot/var/audit     com.sun:auto-snapshot  true     inherited from zroot
zroot/var/crash     com.sun:auto-snapshot  false    local
zroot/var/log       com.sun:auto-snapshot  true     inherited from zroot
zroot/var/mail      com.sun:auto-snapshot  true     inherited from zroot
zroot/var/tmp       com.sun:auto-snapshot  false    local

That should be all it takes to get things running.

Within 15 minutes or so, the first set of snapshots should begin to appear in the system and can be viewed with zfs list -t snapshot. Old snapshots will be automatically deleted from the system when their replacements arrive.

# zfs list -t snapshot
NAME
 USED  AVAIL  REFER  MOUNTPOINT
zroot@zfs-auto-snap_frequent-2019-11-18-23h15
    0      -    96K  -
zroot/ROOT/default@zfs-auto-snap_frequent-2019-11-18-23h15
    0      -  4.01G  -
[...]