Currently this is tested on Arch and Fedora, and should work in most other distributions.
Note: Preliminary work has began to support non-btrfs (e.g. rsync, BCacheFS) based snapshots. If you are a developer, this comment explains the abstraction for implementing a new backend.
Use your preferred AUR handler -
yay -S yabsnap
# OR
paru -S yabsnap
Or install manually from AUR -
mkdir yabsnap_tmp && cd yabsnap_tmp
curl 'https://aur.archlinux.org/cgit/aur.git/plain/PKGBUILD?h=yabsnap' -o PKGBUILD
mkpkg -si
git clone https://github.com/hirak99/yabsnap
cd yabsnap
# To install -
sudo scripts/install.sh
# To uninstall -
sudo scripts/uninstall.sh
Allows managing scheduled btrfs snapshots.
- Supports multiple sources, and customizing destination directory. Use
yabsnap create-config
to configure what gets snapped, and when. - Supports pre-installation snaps with auto-generated comments.
- Supports rollback - by generating a short shell script.
Some good alternatives are timeshift, snapper; both very good in what they do.
However, neither supports customized of snapshot location, (e.g. Arch recommended
layout).
Adhering to such layouts, and rolling back using them, sometime involve
non-obvious
workarounds.
The motivation for yabsnap
was to create a simpler, hackable and customizable
snapshot system.
yabsnap | timeshift | snapper | |
---|---|---|---|
Custom sources | ✓ | Only root and home (1) | ✓ |
Custom destinations | ✓ | ||
Pacman hook | ✓ | Via timeshift-autosnap (2) | Via snap-pac |
File system | btrfs | btrfs, ext4 | btrfs |
GUI | ✓ | With snapper-gui | |
Rollback | ✓ | ✓ | Only default subvolume |
(1) timeshift does not allow separate schedules or triggers for root and home.
(2) At the time of writing, timeshift-autosnap
does not tag the snapshot with
pacman command used.
- Create a config:
yabsnap create-config CONFIGNAME
- This will create a file
/etc/yabsnap/configs/CONFIGNAME.conf
- This will create a file
- Edit the config to change the
source
field, to point to a btrfs mounted directory. E.g.source = /
, orsource = /home
.
Also, ensure that the service is enabled,
sudo systemctl enable --now yabsnap.timer
You should now have automated backups running.
Below is an example layout.
Subvolumes | Mount Point | Mount Options |
---|---|---|
@ | / |
subvol=@ |
@home (optional) | /home |
subvol=@home |
@.snapshots | /.snapshots |
[email protected] |
NOTE: The names can be different; you do not need to rename your existing subvolumes.
Tips -
- Mount by
subvol=NAME
, instead ofsubvolid=NUMERIC_ID
. This is necessary to allow rollbacks without touching the fstab. - Create a top level subvolume for all snapshots.
To set this up in shell, mount the top volume and create a @.snapshots subvolume -
# Mount the top level subvolume (id 5) into a temporary mount dir.
TOP=/run/mount/btrfs_top # Temporary path to mount subvol.
mkdir $TOP
mount /dev/sdX $TOP -t btrfs -o subvolid=5
# Assuming @ (or root) and optionally @home already exists,
# all you need is a new subvolume for snapshots.
btrfs subvolume create $TOP/@.snapshots
# Also need directory to mount @.snapshots into -
mkdir $TOP/.snapshots
And then add a line to your fstab
to mount the @.snapshots subvolume on every boot.
Example lines for fstab -
# fstab: Example for root. Notably, use subvol=/@, do not use subvolid.
UUID=BTRFS_VOL_UUID / btrfs rw,noatime,ssd,space_cache=v2,subvol=/@,compress=zstd 0 1
# fstab: Example for /.snapshots.
UUID=BTRFS_VOL_UUID /.snapshots btrfs rw,noatime,ssd,space_cache=v2,subvolid=260,subvol=/@.snapshots 0 2
Replace BTRFS_VOL_UUID
with the uuid from lsblk -f
, for the partition where the subvolumes reside.
Once you create a config, automated snapshots should start running.
You can further configure the behavior of snapshots by editing the config. Below is how a config file looks like.
# All configurations must be under the [DEFAULT] section.
[DEFAULT]
# Source, must be a btrfs mount.
# For example, `source = /` or `source = /home`.
source =
# Destination including directory and prefix where the snapshots will be stored.
# For example, `dest_prefix = /.snapshots/@root-` will result in snapshots like
# "/.snapshots/@root-20230315120000".
# Time in the format YYYYMMDDhhmmss will be added to the prefix while creating snaps.
dest_prefix =
# Only one snap can be made within this interval.
# The intervals are counted from 1970 Jan 1, 12:00 AM UTC.
trigger_interval = 1 hour
# How much minimum time must pass before a snap can be cleaned up.
min_keep_secs = 1800
# How many user-created snaps to keep.
# User created snaps can are made with 'create' command.
keep_user = 1
# How many pre-installation snaps to keep.
# Any value more than 0 will enable pacman hook, and store snap on before pacman operation.
# Will also work for AUR managers such as yay, since AUR managers also use pacman.
keep_preinstall = 1
# How much time must have passed from last installation to trigger a snap.
# This prevents snaps multiple installations from a script to each trigger snap in short succession.
preinstall_interval = 5 minutes
# How many scheduled snaps to keep.
# If all are 0, scheduled snap will be disabled.
keep_hourly = 0
keep_daily = 5
keep_weekly = 0
keep_monthly = 0
keep_yearly = 0
# Snapshot mechanism. Only BTRFS is supported as of now.
snap_type = BTRFS
# Uncomment example to specify scripts to run after yabsnap creates or deletes any snap.
# Use space as delimiter to specify multiple scripts if desired.
# If any creation / deletion operation occurs, each script will be called once.
# Example -
# post_transaction_scripts = "/home/me/script1.sh" "/home/me/script2.sh"
--dry-run
Disables all snapshot changes. Shows what it would do instead.--config-file CONFIG-FILE
Specify which config file to operate on.--source SOURCE
Restricts to the config which has the specified source, for example--source /home
. The source must be specified in one of the config files. Alternatively, a config-file directly may also be specified with--config-file CONFIG-FILE
.
Creates a new config by NAME
.
Immediately after that, the source
and dest_prefix
fields must be filled
out.
Lists existing snaps. Example -
Config: /etc/yabsnap/configs/home.conf (source=/home)
Snaps at: /.snapshots/@home-...
20221006143047 S 2022-10-06 14:30:47
20221006153007 S 2022-10-06 15:30:07
20221006163019 S 2022-10-06 16:30:19
20221006164659 I 2022-10-06 16:46:59 pacman -S perl-rename
Config: /etc/yabsnap/configs/root.conf (source=/)
Snaps at: /.snapshots/@root-...
20221006122312 U 2022-10-06 12:23:12 test_comment
20221006164659 I 2022-10-06 16:46:59 pacman -S perl-rename
The indicators S
, I
, U
respectively indicate scheduled, installation, user snapshots.
Similar to list, but as a machine readable json.
This can be useful to build commands. For instance, with bash you could use jq
to filter -
# Filter all snaps created during installation.
yabsnap list-json | jq -c 'select(.trigger=="I")'
# Filter all snaps created during installation, and using home.conf.
yabsnap list-json | jq -c 'select(.trigger=="I" and (.config_file | endswith("/home.conf")))'
Or restructure -
# Show only the timestamps.
yabsnap list-json | jq '.file.timestamp'
Creates an user snapshot.
Optionally add comment with --comment "COMMENT"
.
Deletes a snapshot.
E.g.
yabsnap delete /.snapshots/@home-20221006143047
Or,
yabsnap delete 20221006143047 # Deletes all snapshots with this timestamp.
Generates a script for rolling back.
E.g.
yabsnap rollback-gen /.snapshots/@home-20221006143047
Or,
yabsnap rollback-gen 20221006143047
Just running it will not carry out any changes, it will only display a script on
the console.
The script must be stored and executed to perform the rollback operation.
-
Does it work on other distros than Arch?
- It should work if installed with
sudo scripts/install.sh
, although- Installation hook will not work.
- And rest of the features should be tested.
- If you'd want full support on a distro, I'm happy to know so that I can evaluate and find a way to prioritize it. Please open an issue.
- It should work if installed with
-
I deleted a snapshot manually. Will it confuse yabsnap?
- No. You should also delete the corresponding metadata
-meta.json
manually (it's in the same directory). If you usedyabsnap delete PATH_TO_SNAPSHOT
, it would take care of that for you.
- No. You should also delete the corresponding metadata
-
How do I delete multiple snaps?
- The quickest way is to delete them manually. Remove the snaps with
btrfs subvolume snapshot del YOUR_SNAP
, and corresponding-meta.json
files.
- The quickest way is to delete them manually. Remove the snaps with
-
Why Python?
- Python, when written with high code quality, serves as an excellent orchestrator. This is precisely what we needed for Yabsnap, with a focus on (1) expressiveness, (2) ease of maintenance, and (3) accessibility for contributors. While low-level speed or efficiency is not a primary concern for us, modern Python supports static type checking, making it a robust choice for our needs. To ensure code health and maintainability, we emphasize strict adherence to code style and readability standards.