Skip to main content
The CM5 image uses a multi-subvolume Btrfs layout with Snapper for automated timeline snapshots. This gives you rollback capability and efficient snapshot replication to SATA or NVMe storage.

Subvolume layout

SubvolumeMount pointMount optionsPurpose
@/compress=zstd,space_cache=v2,noatimeRoot filesystem
@boot/bootcompress=zstd,space_cache=v2,noatimeKernel and initramfs
@swap/swapcompress=zstd,space_cache=v2,noatime,nodatacowswap.img file
@snapshots/.snapshotscompress=zstd,space_cache=v2,noatimeSnapper snapshot storage
@var_log/var/logcompress=zstd,space_cache=v2,noatimeLog files (isolated from root)
@home/homecompress=zstd,space_cache=v2,noatimeUser home directories
@frigate/media/frigatenodatacowFrigate NVR recordings and snapshots
@docker/var/lib/dockernodatacowDocker layer storage
The @swap and @docker subvolumes use nodatacow because Btrfs Copy-on-Write is counterproductive for large sequential writes and swap files.

Snapper configuration

The root subvolume is configured in /etc/snapper/configs/root:
/etc/snapper/configs/root
SUBVOLUME="/"
FSTYPE="btrfs"
TIMELINE_CREATE="yes"
TIMELINE_CLEANUP="yes"
TIMELINE_LIMIT_HOURLY="6"
TIMELINE_LIMIT_DAILY="7"
TIMELINE_LIMIT_WEEKLY="4"
TIMELINE_LIMIT_MONTHLY="6"
TIMELINE_LIMIT_YEARLY="2"
SPACE_LIMIT="0.5"
FREE_LIMIT="0.2"
SettingValueMeaning
TIMELINE_LIMIT_HOURLY6Keep last 6 hourly snapshots
TIMELINE_LIMIT_DAILY7Keep last 7 daily snapshots
TIMELINE_LIMIT_WEEKLY4Keep last 4 weekly snapshots
TIMELINE_LIMIT_MONTHLY6Keep last 6 monthly snapshots
TIMELINE_LIMIT_YEARLY2Keep last 2 yearly snapshots
SPACE_LIMIT0.5Stop creating snapshots if less than 50% free
FREE_LIMIT0.2Stop creating snapshots if less than 20% free
Snapper timers are enabled by default:
systemctl enable --now snapper-timeline.timer snapper-cleanup.timer

Managing snapshots

List snapshots

snapper -c root list

Create a manual snapshot

# Before a system update — good practice
snapper -c root create --description "before-pacman-update"

View differences between snapshots

snapper -c root diff 3..5

Rollback with Snapper

# Roll back to snapshot 4 (undoes all changes from 4 to current)
snapper -c root undochange 4..0
Snapper undochange operates on files, not the subvolume itself. For a full subvolume rollback, use btrfs subvolume snapshot manually.

Replicating snapshots to SATA backup

Once a SATA disk is connected (enumerates as /dev/sdX), you can replicate snapshots for off-device backup:
# Create a read-only snapshot
btrfs subvolume snapshot -r / /.snapshots/initial

# Send to SATA backup (first time — full send)
btrfs send /.snapshots/initial | btrfs receive /mnt/sata-backup/

# Incremental send (subsequent runs — much faster)
btrfs subvolume snapshot -r / /.snapshots/current
btrfs send -p /.snapshots/initial /.snapshots/current | btrfs receive /mnt/sata-backup/
Mount the SATA backup disk as a Btrfs volume and keep the parent snapshot for incremental sends. Incremental replication transfers only changed blocks — essential for eMMC longevity.

Expanding the Btrfs pool with NVMe

After enabling NVMe in config.txt (dtparam=nvme=on), you can add it to the Btrfs pool and mirror the eMMC:
# Add NVMe to the btrfs pool
btrfs device add /dev/nvme0n1 /

# Convert to RAID1 (mirrors data and metadata across eMMC + NVMe)
btrfs balance start -dconvert=raid1 -mconvert=raid1 /
This gives you fault tolerance: if the eMMC fails, the NVMe retains a complete copy of all data.

Periodic TRIM

fstrim.timer is enabled by default to run weekly TRIM on eMMC and NVMe:
# Check timer status
systemctl status fstrim.timer

# Run TRIM manually
sudo fstrim -v /
TRIM is important for eMMC wear leveling and NVMe performance on long-running systems.

Build docs developers (and LLMs) love