An open API service indexing awesome lists of open source software.

https://github.com/phdenzel/btrsnap

A lightweight btrfs snapshot script as an alternative to timeshift or snapper
https://github.com/phdenzel/btrsnap

btrfs btrfs-snapshots systemd-service systemd-timer

Last synced: about 1 month ago
JSON representation

A lightweight btrfs snapshot script as an alternative to timeshift or snapper

Awesome Lists containing this project

README

          

#+AUTHOR: phdenzel
#+TITLE: btrsnap
#+DATE: 2022-04-12 Tue
#+OPTIONS: author:nil title:t date:nil timestamp:nil toc:nil num:nil \n:nil

This is yet another btrfs snapshotting program. Ever since I've been
using btrfs as the filesystem of my daily driver, I took advantage of
the main feature of btrfs: (almost) instantaneous snapshots. I created
them through [[https://github.com/teejee2008/timeshift][timeshift]], then I eventually switched to [[https://github.com/openSUSE/snapper][snapper]], never
realizing that btrfs-progs already ships with a pretty usable
snapshotting utility itself. The advantage of btrfs-progs over
timeshift or snapper, is that it leaves decisions to the user and
doesn't impose specific filesystem configurations or naming
conventions. Over the time, I accumulated several bash scripts
wrapping these utility functions, most of which I used to run as cron
jobs.

This is a unified re-write of these separate functions into a proper
framework unimaginatively called ~btrsnap~. It imposes my
configuration as defaults, but integrates environment variables and a
configuration file, giving the user the option to fully customize to
any setup. Moreover, it provides systemd service and timer templates
which can be used to run timed and automated snapshots.

* Install

Install ~btrsnap~ using
#+begin_src shell
sudo make install
#+end_src
This will install the script to ~/usr/local/bin/~ which should already
be in your PATH.

Alternatively you can run
#+begin_src shell
PREFIX=/path/of/your/choice make install
#+end_src
which might need sudo priviliges depending on your choice.
Don't forget to add the chosen prefix to your PATH.

In case you're running on ~systemd~ (I have no opinions on the matter,
and I'm not interested in discussions about it) and you want to
automate btrsnap, use
#+begin_src shell
sudo btrsnap gentemp / root --delay 0
#+end_src
or for snapshotting your home directories
#+begin_src shell
sudo btrsnap gentemp /home home --delay 10
#+end_src
These commands create a directory ~services~ and
~btrsnap-root@.service~ and ~btrsnap-home@.service~ with corresponding
~btrsnap-*@.timer~ templates within.

They can be installed with
#+begin_src shell
sudo make install-services
#+end_src
which copies the service files and their corresponding timers to
~/etc/systemd/system/~.

Services can then be timed with e.g.
#+begin_src shell
sudo systemctl enable --now btrsnap-root@weekly.timer
#+end_src
which will run weekly snapshots of your root subvolume.
You can also enable the following timers:
- ~btrsnap-root@hourly.timer~
- ~btrsnap-root@daily.timer~
- ~btrsnap-root@monthly.timer~
- ~btrsnap-root@yearly.timer~
- analogously for other service templates

These service templates enable you to periodically snapshot your root
subvolume mounted at ~/~ (or in case of ~btrsnap-home@.service~ to
snapshot ~/home~). If you have a different setup simply add analogous
files with your specifications using ~btrsnap-gentemp~.
Note that to avoid any issues with deadlocks due to simultaneously
writing to the log files, it is advisable to choose different delays
for different btrsnap tasks using the ~--delay~ flag.

To uninstall ~btrsnap~ (from any location) and installed btrsnap
services and timers, simply run
#+begin_src shell
sudo make uninstall
#+end_src

* Usage

~btrsnap~ has several subcommands which can be inspected using

#+begin_src shell
sudo btrsnap help
#+end_src

#+begin_src shell
Usage: sudo btrsnap [options]

Subcommands:
e(nv)
- Print all environment variables

l(i)[s](t) [options] [source]
- List all snapshots (and updates logs)

i(nfo) [options] [snapshot]
- Print info about a specific snapshot (wrapper for btrfs subvol show)

c(reate) [options] [source] [target]
- Create a snapshot in the target directory

r(e)m(ove) [options] [snapshot]
- Delete specific snapshots

d(iff) [options] [snapshot-a] [snapshot-b]
- Show diffs between two snapshots

u(ndo) [snapshot]
- Undo changes to a specific file from a snapshot

r(estore) [options] [snapshot] [subvolume]
- Restore the filesystem to a former snapshot

s(crub) [options] [source]
- Scrub the oldest snapshots above the limits

g(en)t(emp) [options] [source] [target]
- Generate systemd service and timer templates

For help with each subcommand run:
btrsnap -h|--help

The current basedir for btrsnap is BTRSNAP_BASEDIR=/snapshots
If arguments are given as relative paths, the BTRSNAP_BASEDIR variable
is used as base path, otherwise it is ignored.

btrsnap configuration and logs are in
- .btrsnap/btrsnap.conf
- .btrsnap/btrsnap.log
#+end_src

*** btrsnap-create

The most frequently used command would probably be
#+begin_src
sudo btrsnap create / /snapshots/root
#+end_src
which saves a snapshot of the root subvolume mounted at ~/~ to
~/snapshots/root/%y%m%dT%H:%M:%S.%2N~ (this happens to be the default
which is why ~sudo btrsnap c~ yields the same result).

You can also add a different name format and some description to the
snapshot with
#+begin_src shell
sudo btrsnap c -f special / /mydata/special_dir -m "A really special snapshot"
#+end_src
This saves the snapshot of ~/~ to ~/mydata/special_dir/special~.

*** btrsnap-list

All snapshots, their most important attributes, and their description
can be inspected using
#+begin_src shell
sudo btrsnap ls
#+end_src

#+begin_src shell
# Snapshot Source Time Flags Mode Description
1 /snapshots/root/220418T22:31:23.37 / 22-04-18 22:31:23.37 +0200 r manual
2 /mydata/special_dir/special / 22-04-19 22:32:01.68 +0200 r manual A really special snapshot
#+end_src

*** btrsnap-remove

If at any point you decide to delete a snapshot, use
#+begin_src shell
sudo btrsnap rm /mydata/special_dir/special
#+end_src

You can also select snapshots by index
#+begin_src shell
sudo btrsnap rm 2
#+end_src
or since in this case it is the latest snapshot
#+begin_src shell
sudo btrsnap rm -1
#+end_src

*** btrsnap-scrub

~btrsnap~ works with modes and limit parameters (which of course can
be reconfigured). Each mode has different limit defaults:

- manual: 12
- hourly: 4
- daily: 3
- weekly: 6
- monthly: 4
- yearly: 1

The ~scrub~ subcommand enforces these limits and deletes the oldest
snapshots when the number of snapshots with that mode is exceeded.

For instance,
#+begin_src shell
sudo btrsnap scrub /
#+end_src
clears all snapshots of root with all modes.

#+begin_src shell
sudo btrsnap scrub --mode hourly
#+end_src
clears all snapshots taken in 'hourly' mode regardless of its source.

** Configuration file

~btrsnap~ integrates with environment variables and configuration
files. In case you don't want to change the program's source code
itself, add
#+begin_src shell
export BTRSNAP_CONF=/snapshots/.btrsnap/btrsnap.conf~
#+end_src
to your ~.bashrc~ or ~.zshrc~. In the configuration file you can
define your own default values for
#+begin_src conf
BTRSNAP_BASEDIR="/snapshots"
BTRSNAP_LOG=".$PROGNAME/$PROGNAME.log"
BTRSNAP_SRC='/'
BTRSNAP_TARGET="root"
BTRSNAP_MODE="manual"
BTRSNAP_WRITABLE=0
BTRSNAP_TIMEFORMAT="+%y%m%dT%H:%M:%S.%2N"
BTRSNAP_WARNINGS=1

BTRSNAP_MANUAL_LIMIT=12
BTRSNAP_MONTHLY_LIMIT=4
BTRSNAP_WEEKLY_LIMIT=3
BTRSNAP_DAILY_LIMIT=6
BTRSNAP_HOURLY_LIMIT=4
BTRSNAP_YEARLY_LIMIT=1

DRY_RUN=0
VERBOSE=0
#+end_src

**** TODO

Note, for now, snapshots have to reside on the same btrfs device.

- [ ] btrsnap-remove: * w/ mode selection
- [ ] compatibility with external devices/drives
(for external devices you need to manually use btrfs send/receive
and `btrfs property set` ro to false)
- [ ] pacman hooks to automatically run btrsnap on installs or upgrades