hirak99 / yabsnap

Btrfs Scheduled Snapshot Manager for Arch
Apache License 2.0
53 stars 2 forks source link
arch-linux btrfs btrfs-snapshots

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 favorite AUR manager. E.g. -
yay -S yabsnap
# OR,
pamac install yabsnap

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.

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

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 subvol=@.snapshots

NOTE: The names can be different; you do not need to rename your existing subvolumes.

Tips -

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

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