Skip to content

Latest commit

 

History

History
301 lines (228 loc) · 10.2 KB

README.md

File metadata and controls

301 lines (228 loc) · 10.2 KB

Yet Another Btrfs Snapshotter

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.

Installing

Arch Linux: Install from AUR

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

Other Distributions: Install from git

git clone https://github.com/hirak99/yabsnap
cd yabsnap

# To install -
sudo scripts/install.sh

# To uninstall -
sudo scripts/uninstall.sh

What does it do?

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.

Alternatives

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.

Usage

Quick Start

  • Create a config: yabsnap create-config CONFIGNAME
    • This will create a file /etc/yabsnap/configs/CONFIGNAME.conf
  • Edit the config to change the source field, to point to a btrfs mounted directory. E.g. source = /, or source = /home.

Also, ensure that the service is enabled,

sudo systemctl enable --now yabsnap.timer

You should now have automated backups running.

Recommended Subvolume Layout

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 of subvolid=NUMERIC_ID. This is necessary to allow rollbacks without touching the fstab.
  • Create a top level subvolume for all snapshots.

Example Shell commands to set up

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

fstab

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.

Config File

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"

Command Line Interface

Global flags

  • --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.

Commands

yabsnap create-config NAME

Creates a new config by NAME.
Immediately after that, the source and dest_prefix fields must be filled out.

yabsnap list

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.

yabsnap list-json

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'

yabsnap create

Creates an user snapshot.

Optionally add comment with --comment "COMMENT".

yabsnap delete PATH|TIMESTAMP

Deletes a snapshot.

E.g. yabsnap delete /.snapshots/@home-20221006143047
Or, yabsnap delete 20221006143047 # Deletes all snapshots with this timestamp.

yabsnap rollback-gen PATH|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.

FAQ

  • 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.
  • 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 used yabsnap delete PATH_TO_SNAPSHOT, it would take care of that for you.
  • 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.
  • 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.