feat(meta): Initial commit (#1)
This commit is contained in:
parent
7ea829aacf
commit
f7f6d71250
55
README.md
55
README.md
@ -1,3 +1,56 @@
|
|||||||
# zfs-pacman-hook
|
# zfs-pacman-hook
|
||||||
|
|
||||||
Arch Linux pacman hook for automatic snapshots
|
Arch Linux pacman hook for automatic ZFS snapshots
|
||||||
|
|
||||||
|
# Setup
|
||||||
|
|
||||||
|
Get started like so:
|
||||||
|
|
||||||
|
1. Install dependency `zfs-auto-snapshot`
|
||||||
|
1. Clone repo into arbitrary path `<repo>`
|
||||||
|
1. Make `pacman-zfs-snapshot.sh` executable
|
||||||
|
```
|
||||||
|
chmod +x <repo>/pacman-zfs-snapshot.sh
|
||||||
|
```
|
||||||
|
1. Symlink to files, for example
|
||||||
|
```
|
||||||
|
ln -s <repo>/pacman-zfs-snapshot.sh /usr/local/bin/pacman-zfs-snapshot
|
||||||
|
ln -s <repo>/pacman-zfs-snapshot.hook /usr/share/libalpm/hooks/pacman-zfs-snapshot.hook
|
||||||
|
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` file references `/usr/local/bin/pacman-zfs-snapshot`. Change that accordingly if you need to.
|
||||||
|
1. Adjust `pacman-zfs-snapshot.conf` to your liking
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
We use `zfs-auto-snapshot` both for snapshot creation and for destroying old snapshots. 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](https://www.conventionalcommits.org/) 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:
|
||||||
|
|
||||||
|
- `auto`: Change how `zfs-auto-snapshot` is run
|
||||||
|
- `conf`: How we deal with script config
|
||||||
|
- `script`: Any other script work that doesn't specifically fall into the above scopes
|
||||||
|
- `meta`: Affects the project's repo layout, readme content, file names etc.
|
||||||
|
12
pacman-zfs-snapshot.conf
Normal file
12
pacman-zfs-snapshot.conf
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# Pipe-separated list of kernel names. Will be matched against regular
|
||||||
|
# expression ^this_var_here$. Snapshots taken before a pacman transaction on
|
||||||
|
# an important package have a separate retention from snapshots for trivial
|
||||||
|
# packages. Lends itself to keeping kernel updates separate from everything
|
||||||
|
# else.
|
||||||
|
important_names='tmux'
|
||||||
|
|
||||||
|
snaps_trivial_keep='15'
|
||||||
|
snaps_important_keep='5'
|
||||||
|
|
||||||
|
snaps_trivial_suffix='trv'
|
||||||
|
snaps_important_suffix='imp'
|
14
pacman-zfs-snapshot.hook
Normal file
14
pacman-zfs-snapshot.hook
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
[Trigger]
|
||||||
|
Operation = Install
|
||||||
|
Operation = Upgrade
|
||||||
|
Operation = Remove
|
||||||
|
Type = Package
|
||||||
|
Target = *
|
||||||
|
|
||||||
|
[Action]
|
||||||
|
Description = Create ZFS snapshot on active system dataset
|
||||||
|
When = PreTransaction
|
||||||
|
Exec = /bin/sh -c 'while read -r f; do echo "$f"; done | /usr/local/bin/pacman-zfs-snapshot'
|
||||||
|
Depends = zfs-auto-snapshot
|
||||||
|
AbortOnFail
|
||||||
|
NeedsTargets
|
47
pacman-zfs-snapshot.sh
Executable file
47
pacman-zfs-snapshot.sh
Executable file
@ -0,0 +1,47 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
declare -a pkgs
|
||||||
|
while read pkg; do
|
||||||
|
pkgs+=("${pkg}")
|
||||||
|
done
|
||||||
|
|
||||||
|
declare conf_file
|
||||||
|
conf_file='/etc/pacman-zfs-snapshot.conf'
|
||||||
|
|
||||||
|
declare important_names snaps_trivial_keep snaps_important_keep snaps_trivial_suffix snaps_important_suffix
|
||||||
|
if [[ -r "${conf_file}" ]]; then
|
||||||
|
source "${conf_file}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! "${important_names}" ]]; then important_names='linux'; fi
|
||||||
|
if [[ ! "${snaps_trivial_keep}" ]]; then snaps_trivial_keep='5'; fi
|
||||||
|
if [[ ! "${snaps_important_keep}" ]]; then snaps_important_keep='5'; fi
|
||||||
|
if [[ ! "${snaps_trivial_suffix}" ]]; then snaps_trivial_suffix='trv'; fi
|
||||||
|
if [[ ! "${snaps_important_suffix}" ]]; then snaps_important_suffix='imp'; fi
|
||||||
|
|
||||||
|
function split_pkgs_by_importance () {
|
||||||
|
local pkgs_in_transaction
|
||||||
|
pkgs_in_transaction=("${@}")
|
||||||
|
for pkg in "${pkgs_in_transaction[@]}"; do
|
||||||
|
if grep -Piq -- '^'"${important_names}"'$' <<<"${pkg}"; then
|
||||||
|
important_pkgs_in_transaction+=("${pkg}")
|
||||||
|
else
|
||||||
|
unimportant_pkgs_in_transaction+=("${pkg}")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
function main () {
|
||||||
|
local pkgs_in_transaction
|
||||||
|
pkgs_in_transaction=("${@}")
|
||||||
|
|
||||||
|
declare -a important_pkgs_in_transaction unimportant_pkgs_in_transaction
|
||||||
|
split_pkgs_by_importance "${pkgs_in_transaction[@]}"
|
||||||
|
|
||||||
|
|
||||||
|
#for pkg in "${!important_pkgs_in_transaction[@]}"; do
|
||||||
|
# printf -- 'Array item '"'"'%s'"'"' equals '"'"'%s'"'"'\n' "${pkg}" "${important_pkgs_in_transaction[${pkg}]}"
|
||||||
|
#done
|
||||||
|
}
|
||||||
|
|
||||||
|
main "${pkgs[@]}"
|
Loading…
x
Reference in New Issue
Block a user