zfs-pacman-hook/README.md

3.7 KiB

zfs-pacman-hook

Arch Linux pacman hook for automatic ZFS snapshots

Setup

Get started like so:

  1. Install dependency jq
  2. Clone repo into arbitrary path <repo>
  3. Make pacman-zfs-snapshot.sh executable
    chmod +x <repo>/pacman-zfs-snapshot.sh
    
  4. Symlink to files, for example
    sudo ln -s <repo>/pacman-zfs-snapshot.sh /usr/local/bin/pacman-zfs-snapshot
    sudo ln -s <repo>/pacman-zfs-snapshot-install.hook /usr/share/libalpm/hooks/pacman-zfs-snapshot-install.hook
    sudo ln -s <repo>/pacman-zfs-snapshot-remove.hook /usr/share/libalpm/hooks/pacman-zfs-snapshot-remove.hook
    sudo ln -s <repo>/pacman-zfs-snapshot-upgrade.hook /usr/share/libalpm/hooks/pacman-zfs-snapshot-upgrade.hook
    sudo ln -s <repo>/pacman-zfs-snapshot.conf /etc/pacman-zfs-snapshot.conf
    
    Note that while you may choose arbitrary locations for symlinks the pacman-zfs-snapshot-*.hook files reference /usr/local/bin/pacman-zfs-snapshot. Change that accordingly if you need to.
  5. For datasets you want auto-snapshotted add property space.quico:auto-snapshot=true
    zfs set space.quico:auto-snapshot=true zpool/root/archlinux
    
    With any other property and any other value datasets will not be auto-snapshotted.
  6. Adjust pacman-zfs-snapshot.conf to your liking. You may want to set do_dry_run='true' for a start and just reinstall a benign package to get a feel for what this hook would do.

What's it do?

In pacman on every PreTransaction, meaning right before any actual operation on a package begins, we trigger a ZFS snapshot. By default we identify the active system dataset by doing findmnt / --noheadings --output source. If exactly one source returns that is the exact name of a ZFS dataset in an imported zpool we create a snapshot on it. If no source returns we silently exit. If more than one source returns we raise an error and halt the pacman transaction.

We retain two different snapshot chains, one for pacman transactions that only affect what we are calling trivial packages and a separate chain for important packages. By default only the exact regular expression package name match ^linux$ is considered important. Whenever an important package is affected by a transaction a snapshot goes into the corresponding chain. In all other cases - when an important package is not affected - snapshots go into the trivial chain.

The trivial snapshot chain by default keeps 15 snapshots, the important chain keeps 5. The thought process here is that you will likely not futz around with a kernel every day whereas you may very well install arbitrary packages multiple times a day. Snapshots should keep you safe for a couple of days hence the defaults of 5 and 15 snapshots, respectively.

You may optionally include more ZFS datasets in this snapshot mechanism. Have a look at pacman-zfs-snapshot.conf, its comments should be clear enough to get you going.

Development

Conventional commits

This project uses Conventional Commits for its commit messages.

Commit types

Commit types besides fix and feat are:

  • build: Project structure, directory layout, build instructions for roll-out
  • refactor: Keeping functionality while streamlining or otherwise improving function flow
  • test: Working on test coverage
  • docs: Documentation for project or components

Commit scopes

The following scopes are known for this project. A Conventional Commits commit message may optionally use one of the following scopes or none:

  • conf: How we deal with script config
  • script: Any other script work that doesn't specifically fall into the above scopes
  • hook: Configuring the hook(s)
  • meta: Affects the project's repo layout, readme content, file names etc.