From c5be15b7bf01365ab5dfd0de6caadbc6183f1fb3 Mon Sep 17 00:00:00 2001 From: "Casper V. Kristensen" Date: Tue, 10 May 2022 01:25:47 +0200 Subject: [PATCH] Add borg --- borg/backup.sh | 94 +++++++++++++++++++++++++++++++++++++++++ borg/borg-daily.service | 8 ++++ borg/borg-daily.timer | 10 +++++ install/borg.sh | 48 +++++++++++++++++++++ 4 files changed, 160 insertions(+) create mode 100644 borg/backup.sh create mode 100644 borg/borg-daily.service create mode 100644 borg/borg-daily.timer create mode 100755 install/borg.sh diff --git a/borg/backup.sh b/borg/backup.sh new file mode 100644 index 0000000..6654bef --- /dev/null +++ b/borg/backup.sh @@ -0,0 +1,94 @@ +#!/bin/bash + + +# Desktop notification + function notify() { + if [ -x "$(command -v notify-send)" ]; then + # https://stackoverflow.com/questions/28195805/running-notify-send-as-root/49533938#49533938 + local display=":$(ls /tmp/.X11-unix/* | sed 's#/tmp/.X11-unix/X##' | head -n 1)" + local uid=$(id -u caspervk) + sudo -u caspervk DISPLAY=$display DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$uid/bus notify-send --expire-time=0 --icon=backup "$@" + fi + } + +notify "Borgbackup: Started" + +# Avoid UnicodeError +export LANG=en_US.UTF-8 + +# Ask an external program to supply the repository passphrase: +export BORG_PASSCOMMAND='cat /usr/local/etc/borg/passphrase.key' + +# When running Borg using an automated script, ssh might still ask for a password, even if there is an SSH key for +# the target server. Use this to make scripts more robust: +export BORG_RSH='ssh -oBatchMode=yes' + +# Set repository location +# Note: because of the way the server is set up, the repo resides in `/home/borg/repos//` on the server. +export BORG_REPO=ssh://borg@sigma.caspervk.net:222/./auto-full + +# Initialize remote repository (doesn't matter if it already is). +borg init --encryption=repokey-blake2 + +# Backup directories into an archive named after the machine and current utc time. +# Patterns: +# A backup root (starting point) path starts with the prefix R, followed by a path. +# An include rule starts with the prefix +. +# An exclude rule starts with the prefix -. +# An exclude-norecurse rule starts with !. +borg create \ + --filter AME \ + --show-rc \ + --stats \ + --compression zstd \ + --remote-ratelimit 0 \ + --exclude-caches \ + \ + --pattern '! /dev' \ + --pattern '! /proc' \ + --pattern '! /sys' \ + --pattern '! /var/run' \ + --pattern '! /var/tmp' \ + --pattern '! /run' \ + --pattern '! /tmp' \ + --pattern '! /lost+found' \ + --pattern '! /var/cache' \ + --pattern '! /**/found.000/*' \ + --pattern '! /mnt' \ + \ + --pattern '! /home/*/.steam' \ + --pattern '! /home/*/GOG Games' \ + --pattern '! /home/*/.cache' \ + --pattern '! /home/*/Downloads' \ + --pattern '! /home/*/.local/share/Trash' \ + \ + --pattern '+ /media/caspervk/C/Users/Casper/Desktop' \ + --pattern '+ /media/caspervk/C/Program Files (x86)/World of Warcraft/_classic_' \ + --pattern '- /media' \ + \ + --pattern '- /media/caspervk/Backup/Downloads' \ + --pattern '- /media/caspervk/Backup/monero' \ + --pattern '- /media/caspervk/Backup/Programmer/VirtualBox' \ + --pattern '+ /media/caspervk/Backup' \ + ::'{hostname}-{utcnow}' \ + / +backup_exit=$? + +# Use the `prune` subcommand to maintain 7 daily, 4 weekly and 6 monthly archives: +# Note that as the repo is append-only, prune won’t free disk space, but merely tag data as deleted in a new +# transaction. As soon as we write to the repo in non-append-only mode (e.g. prune, delete or create archives from an +# admin machine), it will remove the deleted objects permanently (including the ones that were already marked as +# deleted, but not removed, in append-only mode). +borg prune \ + --list \ + --show-rc \ + --keep-daily 7 \ + --keep-weekly 4 \ + --keep-monthly 6 +prune_exit=$? + +notify "Borgbackup: Finished" + +# use highest exit code as global exit code +global_exit=$(( backup_exit > prune_exit ? backup_exit : prune_exit )) +exit ${global_exit} diff --git a/borg/borg-daily.service b/borg/borg-daily.service new file mode 100644 index 0000000..67b1b94 --- /dev/null +++ b/borg/borg-daily.service @@ -0,0 +1,8 @@ +[Unit] +Description=Daily full system borg backup +After=network.target network-online.target + +[Service] +Type=oneshot +ExecStartPre=/bin/sh -c 'until host sigma.caspervk.net; do sleep 10; done' +ExecStart=/usr/local/sbin/backup.sh diff --git a/borg/borg-daily.timer b/borg/borg-daily.timer new file mode 100644 index 0000000..afc1b73 --- /dev/null +++ b/borg/borg-daily.timer @@ -0,0 +1,10 @@ +[Unit] +Description=Daily full system borg backup + +[Timer] +OnCalendar=*-*-* 00:00:00 +RandomizedDelaySec=6h +Persistent=true + +[Install] +WantedBy=timers.target diff --git a/install/borg.sh b/install/borg.sh new file mode 100755 index 0000000..abd8460 --- /dev/null +++ b/install/borg.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +set -e + +# Packages +sudo apt update +sudo apt upgrade +sudo apt install -y borgbackup + +# Backup script - not symlinked to avoid potential privilege escalation +sudo cp borg/backup.sh /usr/local/sbin/backup.sh +sudo chown root:root /usr/local/sbin/backup.sh +sudo chmod 744 /usr/local/sbin/backup.sh + +# Passphrase +if [ ! -f /usr/local/etc/borg/passphrase.key ]; then + echo '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@' + echo '@@ PLEASE BACKUP BORG PASSPHRASE: @@' + pwgen 32 1 | sudo tee /usr/local/etc/borg/passphrase.key + echo '@@ (/usr/local/etc/borg/passphrase.key) @@' + echo '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@' + read -p 'Press any key to continue..' + sudo chmod 600 /usr/local/etc/borg/passphrase.key +fi + + +# Systemd service and timer - not symlinked to avoid potential privilege escalation +sudo cp borg/borg-daily.service /etc/systemd/system/ +sudo cp borg/borg-daily.timer /etc/systemd/system/ +sudo chown root:root /etc/systemd/system/borg-daily.service /etc/systemd/system/borg-daily.timer +sudo systemctl enable borg-daily.timer + + +# SSH +ssh-keyscan -t ed25519 -p 222 sigma.caspervk.net | sudo tee /root/.ssh/known_hosts # add backup server to known_hosts +sudo ssh-keygen -t ed25519 # generate key for the root user +echo "Please add the following to ~borg/.ssh/authorized_keys:" +echo "command=\"mkdir -p ~/repos/$(hostname); cd ~/repos/$(hostname); borg serve --append-only --restrict-to-path ~/repos/$(hostname)\",restrict $(sudo cat /root/.ssh/id_ed25519.pub)" +ssh sigma.caspervk.net -p 222 + + +# To setup the server: +# sudo apt install borgbackup +# sudo adduser --disabled-password borg +# sudo su borg +# cd ~ +# mkdir repos/ +# chmod 700 repos/