Migrating a Proxmox server from zfs-auto-snapshot to sanoid for ZFS snapshot management. The server has been running zfs-auto-snapshot with systemd timers for over a decade, but the AUR package description notes that as of 2021, sanoid and zrepl are better maintained alternatives. Since I’m setting up a new backup pipeline anyway, seemed like a good time to make the switch.

The main difference between the two is configuration model. Where zfs-auto-snapshot uses ZFS properties (com.sun:auto-snapshot=true) on individual datasets, sanoid uses a centralized /etc/sanoid/sanoid.conf file with template-based policies. Sanoid also ships with syncoid, which will be useful for the replication part of the backup strategy.

Current Configuration

The server is running five systemd timers for zfs-auto-snapshot:

$ systemctl list-timers | grep zfs-auto-snapshot
Wed 2025-11-05 13:45:00 EST 3min 36s left   Wed 2025-11-05 13:30:34 EST 10min ago    zfs-auto-snapshot-frequent.timer zfs-auto-snapshot-frequent.service
Wed 2025-11-05 14:00:00 EST 18min left      Wed 2025-11-05 13:00:29 EST 40min ago    zfs-auto-snapshot-hourly.timer   zfs-auto-snapshot-hourly.service
Thu 2025-11-06 00:00:00 EST 10h left        Wed 2025-11-05 00:00:44 EST 13h ago      zfs-auto-snapshot-daily.timer    zfs-auto-snapshot-daily.service
Mon 2025-11-10 00:00:00 EST 4 days left     Mon 2025-11-03 00:00:44 EST 2 days ago   zfs-auto-snapshot-weekly.timer   zfs-auto-snapshot-weekly.service
Mon 2025-12-01 00:00:00 EST 3 weeks 4 days  Sat 2025-11-01 00:00:33 EDT 4 days ago   zfs-auto-snapshot-monthly.timer  zfs-auto-snapshot-monthly.service

Datasets with auto-snapshot enabled:

$ zfs get -t filesystem,volume com.sun:auto-snapshot -s local,received
NAME        PROPERTY               VALUE  SOURCE
pond        com.sun:auto-snapshot  false  local
pond/data   com.sun:auto-snapshot  true   local
pond/srv    com.sun:auto-snapshot  true   received
rpool       com.sun:auto-snapshot  false  local
rpool/ROOT  com.sun:auto-snapshot  true   local
rpool/data  com.sun:auto-snapshot  true   local

This has accumulated thousands of snapshots over the years. At the time of migration there were 145 frequent, 866 hourly, 1,129 daily, 292 weekly, and 394 monthly snapshots.

Installing sanoid

Sanoid is available in Debian repositories, so installation on Proxmox is straightforward:

apt update
apt install sanoid

The package doesn’t create /etc/sanoid automatically. Create it and copy the defaults file:

mkdir -p /etc/sanoid
cp /usr/share/sanoid/sanoid.defaults.conf /etc/sanoid/

Configuration

Create /etc/sanoid/sanoid.conf to match the existing retention policies. The zfs-auto-snapshot defaults are 4 frequent (every 15 minutes, keep last hour), 24 hourly, 31 daily, 8 weekly, and 12 monthly.

######################################
# Sanoid Configuration File          #
# Migrated from zfs-auto-snapshot    #
######################################

#############################
# Dataset Configurations    #
#############################

[rpool/data]
    use_template = production
    recursive = yes

[rpool/ROOT]
    use_template = production
    recursive = yes

[pond/data]
    use_template = production
    recursive = yes

[pond/srv]
    use_template = production
    recursive = yes

#############################
# Specific Overrides        #
#############################

[pond/data/subvol-101-disk-0]
    use_template = ignore

[pond/data/subvol-111-disk-1-frigate/storage]
    use_template = ignore

[pond/data/subvol-114-disk-1]
    use_template = ignore

[pond/data/subvol-114-disk-3]
    use_template = ignore

#############################
# Templates                 #
#############################

[template_production]
    frequently = 4
    hourly = 24
    daily = 31
    weekly = 8
    monthly = 12
    yearly = 0
    autosnap = yes
    autoprune = yes

[template_ignore]
    autoprune = no
    autosnap = no
    monitor = no

The specific overrides are for datasets that had com.sun:auto-snapshot=false set. The template system is cleaner than managing individual ZFS properties.

One gotcha: don’t put comments on the same line as values. Initially tried frequently = 4 # every 15min, keep 4 but sanoid’s parser treats the entire string as the value, causing numeric comparison errors. Comments need to be on separate lines.

Testing

Test the configuration without making changes:

sanoid --configdir=/etc/sanoid --verbose --readonly

This outputs debug information about which datasets will be snapshotted. If the configuration is valid, manually trigger the first batch of snapshots:

sanoid --configdir=/etc/sanoid --verbose --take-snapshots

Output shows snapshot creation:

INFO: taking snapshots...
taking snapshot rpool/data/subvol-100-disk-0@autosnap_2025-11-05_13:54:45_monthly
taking snapshot rpool/data/subvol-100-disk-0@autosnap_2025-11-05_13:54:45_weekly
taking snapshot rpool/data/subvol-100-disk-0@autosnap_2025-11-05_13:54:45_daily
taking snapshot rpool/data/subvol-100-disk-0@autosnap_2025-11-05_13:54:45_hourly
taking snapshot rpool/data/subvol-100-disk-0@autosnap_2025-11-05_13:54:45_frequently

Verify they were created:

$ zfs list -t snapshot -o name | grep autosnap | head -5
pond/data@autosnap_2025-11-05_13:54:46_monthly
pond/data@autosnap_2025-11-05_13:54:46_weekly
pond/data@autosnap_2025-11-05_13:54:46_daily
pond/data@autosnap_2025-11-05_13:54:46_hourly
pond/data@autosnap_2025-11-05_13:54:46_frequently

The sanoid systemd timer was automatically enabled during package installation:

$ systemctl status sanoid.timer
● sanoid.timer - Run Sanoid Every 15 Minutes
     Loaded: loaded (/lib/systemd/system/sanoid.timer; enabled; preset: enabled)
     Active: active (waiting) since Wed 2025-11-05 13:45:18 EST; 8min ago
    Trigger: Wed 2025-11-05 14:00:00 EST; 6min left
   Triggers: ● sanoid.service

Coexistence and Cutover

Both systems can run simultaneously. Sanoid creates autosnap_* snapshots while zfs-auto-snapshot creates zfs-auto-snap_* snapshots. They don’t interfere with each other. After confirming sanoid was working correctly, disable the old timers:

systemctl stop zfs-auto-snapshot-frequent.timer \
               zfs-auto-snapshot-hourly.timer \
               zfs-auto-snapshot-daily.timer \
               zfs-auto-snapshot-weekly.timer \
               zfs-auto-snapshot-monthly.timer

systemctl disable zfs-auto-snapshot-frequent.timer \
                  zfs-auto-snapshot-hourly.timer \
                  zfs-auto-snapshot-daily.timer \
                  zfs-auto-snapshot-weekly.timer \
                  zfs-auto-snapshot-monthly.timer

Verify they’re disabled:

$ systemctl list-timers | grep zfs-auto-snapshot
# (no output)

At this point there are 2,826 old zfs-auto-snap_* snapshots and 49 new autosnap_* snapshots. The old snapshots will age out naturally as they exceed their retention periods. Sanoid only manages snapshots it created, so it won’t touch the old ones.

Result

The migration preserves the same retention policies with a more maintainable configuration model. The centralized config file is easier to modify than hunting down ZFS properties, and the template system makes it simple to apply consistent policies across datasets. Syncoid shipping with sanoid will be useful for the next part of the backup setup, which is replicating datasets from the workstation to this server.

Backup