This is how I set up automatic snapshots (like Time Machine on Mac) on my backup server (an old Raspberry Pi 1B running Raspberry Pi OS – a.k.a. Raspbian, with an old 1TB USB2 HD attached), using Snapper. Supposedly Snapper can work with modified ext4, but it seems far more tested with Btrfs, so I’m using that. This is more or less for my own reference in case I need to do it again, but should work well enough elsewhere.
You need the btrfs-progs and snapper packages:
sudo apt install btrfs-progs snapper
First, the filesystem needs to be btrfs – either from the start or the tool btrfs-convert can do this in place from ext3/4. Note on the current version of Raspbian btrfs-convert is missing and the version from buster-backports segfaults – I used the Pi version of Ubuntu 20.04 to do that.
I’m mounting my hard drive at /ext, so get the UUID with blkid then add to fstab and mount (done this way rather than /dev/sdX etc as it gets the right partition even when USB devices plugged/unplugged/similar). Note if you’re using subvolumes in btrfs you’ll have to adjust the fstab entry:
blkid # Copy the relevant UUID sudo nano /etc/fstab # And add the line, adjusted as required: UUID=copied-from-blkid /ext btrfs defaults 0 0 sudo mount /ext
Note if you want multiple configurations for multiple partitions, you can use the “-c myconfigname” option on all the following snapper commands, but I’m not bothering here as I’m only interested in versioning /ext. Note apt will automatically create snapshots on the root config before & after making changes – so if you’re using this solely on a data partition you might want to use a different config for it anyway. To do the initial snapper setup:
sudo snapper create-config /ext
This creates the /ext/.snapshots directory. If you just want to accept the defaults, you’re done – hourly snapshots will be taken, and it’ll automatically delete after 10 hourly, 10 daily, 0 weekly, 10 monthly and 10 yearly snapshots
To view all snapshots:
sudo snapper list
To manually create a snapshot:
sudo snapper create --description "My First Snapshot"
To look at a file in a snapshot, get the ID with list and just look in the .snapshots dir, e.g.:
sudo ls /ext/.snapshots/VERSION_ID/snapshot
To restore a single file from a snapshot, either just copy or with the IDs from list (the -v is verbose – lists the changed files):
snapper -v undochange PREID..POSTID /path/to/file
To completely revert to a snapshot, just omit the path. Note do NOT do this on the root filesystem, as it can cause really odd things to happen – this isn’t a perfect revert. If you want to do that, change fstab to mount the relevant snapshot directly or take a snapshot of the snapshot. I haven’t done that, and there seems to be differing opinions on the best way to do it, so look at the various links. For small things though, as I said, just omit the path:
snapper -v undochange PREID..POSTID
To adjust how often snapshots are automatically created, and how many are retained (If using multiple configs, replace root with config name):
sudo nano /etc/snapper/configs/root
See here for a good reference on how things in the config file work – this also includes instructions on how to make it so non-root users can use snapper.
If you want to look at the underlying Btrfs snapshots:
sudo btrfs subvolume list /ext
The automatic snapshots and cleanup are triggered via systemd (joy.). To see them, and how long’s left on each:
systemctl list-timers | grep snapper