Sanoid on TrueNAS

syncoid to TrueNAS

In my homelab, I have 2 NAS systems:

  • Linux (Debian)
  • TrueNAS Core (based on FreeBSD)

On my Linux box, I use Jim Salter’s sanoid to periodically take snapshots of my ZFS pool. I also want to have a proper backup of the whole pool, so I use syncoid to transfer those snapshots to another machine. Sanoid itself is responsible only for taking new snapshots and pruning old ones you no longer care about. For example, you might set up a policy in sanoid to take a day’s worth of hourly snapshots and a year’s worth of monthly snapshots. That means, that sanoid will take a snapshot every hour, but – if executed with --prune-snapshots will delete all the hourlies (hourly snapshots in sanoid’s lingo) that are older than a day, monthlies that are older than a year and so on.

Now, if you want to use sanoid to ship your snapshots to another machine with its own ZFS pool, you’ll have to take care of pruning the old snapshot you don’t care about separately from your main machine. That means that you have to run sanoid --prune-snapshots not only on your main NAS, but also on the backup one. So, at the destination, you also run sanoid, but only to --prune-snapshots (unless you need to perform snapshots on that machine for some reason).

Both, sanoid and syncoid work on various operating systems, including GNU/Linux and FreeBSD. I’m running syncoid on my GNU/Linux box and use syncoid to transfer the snapshots to my TrueNAS Core box. Trunas Core is based on FreeBSD, but it’s an appliance. You’re not supposed to install sanoid/syncoid on it. If you try, it won’t work because TrueNAS Core doesn’t want users to muck the system with random packages. Maybe you could try wrestling it and force sanoid there, but if this breaks the system, well, it’s on you.

I recently discovered that you can pass the knowledge of ZFS pool(s) to a Jail in FreeBSD. And, since TrueNAS Core allows users to create Jails using built-in iocage, I decided to use that to create an unrestricted FreeBSD installation inside a jail, pass ZFS to it and run syncoid in there.

Creating a jail

It’s a little tricky to get this part right with TrueNAS Core, so let’s go over the details

In TrueNAS Core, you create jails using web GUI. Navigate to Jails section on the left-hand-side menu and click the ADD button.

Here you’ll have to click ADVANCED JAIL CREATION to show all the options we’ll need for forwarding ZFS to the new jail. Now:

  • Pick a name. E.g.: sanoid
  • For the Release I went with the currently newest one: 13.3-RELEASE
  • Checked auto-start
  • In Jail Properties I:
    • checked allow_mount and
    • chose allow_mount_zfs in the allow_mount_* drop-down

We’ll also have to set up mounting a ZFS dataset, but first we have to create the destination directory inside the jail. So at this point, you have to create the jail and start it. Later we’ll get back to these settings. In particular to the Custom Properties section.

Start the Jail using the GUI and go to shell. You can go to the jail’s shell directly from the browser, but I like to SSH to my TruNAS box and, as root, execute iocage console jail_name. E.g.,

root@truenas[~]# iocage console sanoid
Last login: Thu Mar 28 18:11:35 on pts/5
FreeBSD 13.1-RELEASE-p9 n245429-296d095698e TRUENAS

Welcome to FreeBSD!

Release Notes, Errata: https://www.FreeBSD.org/releases/
Security Advisories:   https://www.FreeBSD.org/security/
FreeBSD Handbook:      https://www.FreeBSD.org/handbook/
FreeBSD FAQ:           https://www.FreeBSD.org/faq/
Questions List:        https://www.FreeBSD.org/lists/questions/
FreeBSD Forums:        https://forums.FreeBSD.org/

Documents installed with the system are in the /usr/local/share/doc/freebsd/
directory, or can be installed later with:  pkg install en-freebsd-doc
For other languages, replace "en" with a language code like de or fr.

Show the version of FreeBSD installed:  freebsd-version ; uname -a
Please include that output and any error messages when posting questions.
Introduction to manual pages:  man man
FreeBSD directory layout:      man hier

To change this login announcement, see motd(5).
root@sanoid:~ #

And create the directory to which you’ll mount the dataset you’re receiving from the other box via syncoid. E.g. mkdir /mnt/my_datasets. Then, stop the jail using the GUI interface, click the EDIT button, scroll to the bottom and expand the Custom Properties. In there:

  • Check jail_zfs
  • Under jail_zfs_dataset choose the dataset you wish to prune (recursively). E.g., if your dataset is directly in your MainPool and is called my_dataset, you’d simply enter my_dataset here.
  • Under jail_zfs_mountpoint choose the directory you’ve just created (e.g., in our example it would be /mnt/my_datasets)

Save the changes, start the jail again and go to its shell.

Installing Sanoid

Now, you’re ready to install sanoid. It’s available in FreeBSD’s Port tree. So first run pkg update and then pkg install sanoid. When you run pkg for the first time ever, you’ll be prompted to install a package management system. Press y to acknowledge. And then run pkg install sanoid. Here’s what both the steps look like:

# pkg update
The package management tool is not yet installed on your system.
Do you want to fetch and install it now? [y/N]: y
Bootstrapping pkg from pkg+http://pkg.FreeBSD.org/FreeBSD:13:amd64/quarterly, please wait...
Verifying signature with trusted certificate pkg.freebsd.org.2013102301... done
[test-sync] Installing pkg-1.20.9...
[test-sync] Extracting pkg-1.20.9: 100%
Updating FreeBSD repository catalogue...
[test-sync] Fetching meta.conf: 100%    163 B   0.2kB/s    00:01    
[test-sync] Fetching packagesite.pkg: 100%    7 MiB   7.2MB/s    00:01    
Processing entries: 100%
FreeBSD repository update completed. 33638 packages processed.
All repositories are up to date.

# pkg install sanoid
Updating FreeBSD repository catalogue...
FreeBSD repository is up to date.
All repositories are up to date.
Updating database digests format: 100%
The following 10 package(s) will be affected (of 0 checked):

New packages to be INSTALLED:
        lzo2: 2.10_1
        lzop: 1.04
        mbuffer: 20230301_1
        mhash: 0.9.9.9_5
        p5-Capture-Tiny: 0.48
        p5-Config-IniFiles: 3.000003_1
        p5-IO-Stringy: 2.113
        perl5: 5.36.3_1
        pv: 1.7.0
        sanoid: 2.2.0

Number of packages to be installed: 10

The process will require 64 MiB more space.
15 MiB to be downloaded.

Proceed with this action? [y/N]: y
...

Ok, FreeBSD Ports packages install every package in /usr/local. So sanoid is in /usr/local/bin/sanoid:

# which sanoid
/usr/local/bin/sanoid

And its configuration is in /usr/local/etc/sanoid directory!! So edit /usr/local/etc/sanoid/sanoid.conf:

# vi /usr/local/etc/sanoid/sanoid.conf

Add the config for your dataset pruning. E.g., for my_dataset, it’d be:

[MainPool/my_dataset]
        use_template = backup
        recursive = zfs

Test it by running sanoid --prune-snapshots manually from the jail’s shell. If all looks good, schedule sanoid --prune-snapshots using cron. E.g., by adding:

0 * * * * /usr/local/bin/sanoid --prune-snapshots

to your crontab(5).