--- /dev/null
+#!/bin/bash
+
+set -eu
+
+if pgrep borg > /dev/null; then
+ echo "Borg is still running!"
+ exit 1
+fi
+
+source "$1"
+
+set -x
+
+ionice -c 3 -p $$
+renice -n 19 -p $$ > /dev/null
+
+[ "$BACKUP_SNAP" -eq 1 ] && bsnap on
+
+borg create \
+ $([ -t 0 ] && echo --progress) \
+ --info --stats \
+ --compression lz4 \
+ --exclude-from "$BACKUP_EXCLUDE_FILE" \
+ "${BACKUP_REPO}::{hostname}-{now}" "$BACKUP_PATH"
+
+borg prune \
+ --info --stats \
+ --keep-daily=7 \
+ --keep-weekly=4 \
+ --keep-monthly=12 \
+ "$BACKUP_REPO"
+
+[ "$BACKUP_SNAP" -eq 1 ] && bsnap off
--- /dev/null
+#!/bin/bash
+
+set -eu
+
+function snap {
+ unsnap
+
+ cat /etc/fstab | awk '{print $5 " " $1 " " $2;}' | while read -r dump dev mnt; do
+ if [ "$dump" = 1 ]; then
+ echo "bind mount $mnt"
+ mount --bind "${mnt}" "/a${mnt}"
+ elif [ "$dump" = 2 ]; then
+ read -r lvname vgname _ < <(lvdisplay --noheadings -C "$dev")
+ echo "snapshot ${vgname}/${lvname}"
+ lvcreate -L1G --snapshot --name "${lvname}snap" "${vgname}/${lvname}"
+ mount -o ro "${dev}snap" "/a${mnt}"
+ fi
+ done
+}
+
+function unsnap {
+ tac /etc/fstab | awk '{print $5 " " $1 " " $2;}' | while read -r dump dev mnt; do
+ snapmnt="/a${mnt}"
+ snapdev="${dev}snap"
+ if [ "$dump" = 1 ]; then
+ echo "umount $snapmnt"
+ mountpoint -q "$snapmnt" && umount "$snapmnt"
+ elif [ "$dump" = 2 ]; then
+ echo "umount $snapmnt"
+ mountpoint -q "$snapmnt" && umount "$snapmnt"
+
+ echo "unsnapshot $snapdev"
+ [ -b "$(readlink -f "$snapdev")" ] && echo y | lvremove "${dev}snap"
+ fi
+ done
+}
+
+if [ "$(id -u)" -ne 0 ]; then
+ echo "Must be root"
+ exit 1
+fi
+
+mkdir -p /a
+
+if [ "${1:-}" = "off" ]; then
+ unsnap
+elif [ "${1:-}" = "on" ]; then
+ snap
+else
+ echo "Usage: $0 on|off"
+ exit 1
+fi
--- /dev/null
+#!/bin/bash
+
+set -eux
+
+cd "$(dirname "$0")"
+
+BORG_PASSPHRASE="$(dd if=/dev/urandom of=/dev/stdout bs=1 count=15 2>/dev/null | base64)"
+
+install -m 0755 bsnap backup /usr/local/bin/
+install -m 0644 -T etc-borg-exclude /etc/borg-exclude
+install -m 0600 -T etc-borg-env /etc/borg-env
+sed -i "s|SECRET|$BORG_PASSPHRASE|" /etc/borg-env
+
+install -m 0644 -T etc-cron.d-backup /etc/cron.d/backup
+H=$((16#$(hostname|md5sum|head -c 1) % 7 + 14))
+M=$((16#$(hostname|md5sum|head -c 2) % 60))
+sed -i -e "s|\$H|$H|" -e "s|\$M|$M|" /etc/cron.d/backup
+
+[ -f /root/.ssh/id_rsa.pub ] || ssh-keygen
+cat /root/.ssh/id_rsa.pub
+install -m 0600 -T root-ssh-config /root/.ssh/config
--- /dev/null
+#!/bin/bash
+
+set -eux
+
+cd "$(dirname "$0")"
+
+git pull --ff-only
+install -m 0755 bsnap backup /usr/local/bin/
--- /dev/null
+BACKUP_SNAP=1
+BACKUP_EXCLUDE_FILE="/etc/borg-exclude"
+BACKUP_PATH="/a"
+BACKUP_REPO="backuphost:root"
+export BORG_PASSPHRASE="SECRET"
--- /dev/null
+/a/home/*/.cache
+/a/home/*/.thumbnails
+/a/home/*/tmp
+/a/tmp
+/a/var/cache
+/a/var/tmp
--- /dev/null
+SHELL=/bin/bash
+PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
+MAILTO=root
+
+# m h dom mon dow user command
+ $M $H * * * root chronic backup
--- /dev/null
+Host *
+ HashKnownHosts no
+
+Host backuphost
+ User borg
+ Hostname backup.example.com