Migrate from zfs-auto-snapshot to sanoid on Proxmox
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.