From e77c8e8f43e90b618312f0c2a431edd6ba232ed0 Mon Sep 17 00:00:00 2001 From: Marc Michalsky Date: Sat, 18 Feb 2023 16:01:54 +0100 Subject: [PATCH] initial commit --- .borg-env.example | 15 ++++ .gitignore | 1 + LICENSE.md | 14 ++++ README.md | 194 ++++++++++++++++++++++++++++++++++++++++++++++ borgbackup.sh | 83 ++++++++++++++++++++ 5 files changed, 307 insertions(+) create mode 100644 .borg-env.example create mode 100644 .gitignore create mode 100644 LICENSE.md create mode 100644 README.md create mode 100755 borgbackup.sh diff --git a/.borg-env.example b/.borg-env.example new file mode 100644 index 0000000..044901e --- /dev/null +++ b/.borg-env.example @@ -0,0 +1,15 @@ +#! /bin/bash + +# Rename this file to .borg-env and place it in your home directory + +# Set ssh key +export BORG_RSH="ssh -i $HOME/.ssh/id_ed25519" + +# Setting this, so the repo does not need to be given on the commandline: +export BORG_REPO="ssh://borguser@borgserver.com:22/~/backups/$USER/$HOST" + +# See the section "Passphrase notes" for more infos. +export BORG_PASSPHRASE='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' + +# This array must containing everything you want to include in the backup +export BORG_TARGETS=("$HOME") diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4c49bd7 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.env diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..28378f9 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,14 @@ +Copyright 2023 Marc Michalsky + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the “Software”), to deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..51da2fb --- /dev/null +++ b/README.md @@ -0,0 +1,194 @@ +# Borgbackup Script + +Once set up, this script helps create backups with `borg` in a very convenient way. + +In fact, it's just a slightly more elaborated version of +the [example](https://borgbackup.readthedocs.io/en/stable/quickstart.html#automating-backups) in the official `borg` +documentation. It mainly focuses on the use of environment variables and also enables the distinction between manual and +automated backups. + +## Preparation + +### Install Borg + +The `borg` packages provided by package managers are usually not up to date. It is better to install borg via `pip` in a +virtual environment. + +Download dependencies. + +```bash +sudo apt-get install python3 python3-dev python3-pip python3-virtualenv \ +libacl1-dev libacl1 \ +libssl-dev \ +liblz4-dev libzstd-dev libxxhash-dev \ +build-essential \ +pkg-config python3-pkgconfig + +sudo apt-get install libfuse-dev fuse # needed for llfuse +# or +sudo apt-get install libfuse3-dev fuse3 # needed for pyfuse311 +``` + +Prepare virutal environment. + +```bash +sudo mkdir /opt/borg && cd /opt/borg +sudo pip3 -m venv borg-venv +``` + +Install `borg` via `pip`. + +```bash +source borg-venv/bin/activate +pip install -U pip setuptools wheel +pip install pkgconfig + +pip install borgbackup +# or +pip install borgbackup[llfuse] # to use llfuse +# or +pip install borgbackup[pyfuse3] # to use pyfuse3 + +``` + +Link `borg` binary to `$PATH`. + +```bash +cd /usr/local/bin +sudo ln -s /opt/borg/borg-venv/bin/borg borg +``` + +### [ If the `borg` repository should be located on a remote server ] + +**IMPORTANT:** `borg` must be installed also on the remote server! + +Generate a dedicated ssh key for every user which will create backups. + +```bash +ssh-keygen -t ed25519 # Don't set a password! +``` + +Print public key. + +```bash +cat $HOME/.ssh/id_ed25519.pub +# Example output: +# ssh-ed25519 AAAAxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx someuser@somehost +``` + +Add the public key to your `authorized_keys` file on the server. + +```bash +# ON REMOTE SERVER +echo 'command="borg serve --restrict-to-path ~/backups//",restrict ssh-ed25519 AAAAxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx someuser@somehost' >> $HOME/.ssh/authorized_keys +``` + +### Set up Borgbackup Script + +Download the repository. + +```bash +cd ~/Downloads +wget https://gitea.extrasolar.space/marc/borgbackup_script/archive/main.tar.gz +tar xzf main.tar.gz +mv borgbackup_script /opt/borgbackup +``` + +Copy the example environment file to the home directory(s) of the user(s) who will create backups. Then configure +the `.borg-env` file. + +```bash +cp /opt/borgbackup/.borg-env.example $HOME/.borg-env +sudo chown $USER. $HOME/.borg-env +sudo chmod 700 $HOME/.borg-env +nano $HOME/.borg-env +``` + +- [ If the borg repository is located on a remote server: set the right path to the dedicated ssh key ] +- Define the path to your borg repository +- Set a strong passphrase +- Define everything you want to include in your backup as an **absolute path** in the `BORG_TARGETS` array + +Make the script executable. + +```bash +sudo chmod +x /opt/borgbackup/borgbackup.sh +``` + +Link the script to the `$PATH`. + +```bash +cd /usr/local/bin +ln -s /opt/borgbackup/borgbackup.sh borgbackup +``` + +### Logs + +Create a logfile with read and write permissions for every user. + +```bash +sudo touch /var/log/backup.log +sudo chmod 666 /var/log/backup.log +``` + +Later, each backup procedure gets logged to that file. + +### Initialize `borg` repository + +```bash +source $HOME/.borg-env +borg init --encryption=repokey +``` + +Don't forget to export your repository key and store it in a *very* safe place. The key can be exported in three +different formats: + +```bash +borg key export /path/to/repo > encrypted-key-backup +borg key export --paper /path/to/repo > encrypted-key-backup.txt +borg key export --qr-html /path/to/repo > encrypted-key-backup.html +``` + +## Usage + +The backup script can be used to create backups either manually or scheduled. + +### Manual backup + +Manual backups will not be pruned automatically. They are prefixed with `man`. + +To create a manual backup just type: + +```bash +borgbackup +``` + +### Scheduled backups + +Scheduled backups will be pruned automatically. There will be kept: + +- 7 daily backups +- 4 weekly backups +- 6 monthly backups +- 2 yearly backups + +Scheduled backups are prefixed with `auto`. + +The scheduled backups can be automated by using `cron`. +To create scheduled backups, place this line in your `crontab` (edit with `crontab -e`): + +``` +0 3 * * * export BORG_RSH='ssh -oBatchMode=yes' && /usr/local/bin/borgbackup auto /dev/null 2>&1 +``` + +## Using `borg` + +Please refer to the [official documentation](https://borgbackup.readthedocs.io) to learn how to use `borg`. + +**Tip:** Before you use a borg command, `source` the `.borg-env` file. This way, you do not have to type the path to the +repository or the password. + +```bash +source $HOME/.borg-env +borg info +``` \ No newline at end of file diff --git a/borgbackup.sh b/borgbackup.sh new file mode 100755 index 0000000..abc74d1 --- /dev/null +++ b/borgbackup.sh @@ -0,0 +1,83 @@ +#!/bin/bash + +# Set mode +if [ "$1" = "auto" ]; then + mode="auto" +else + mode="man" +fi + +# Read environment variables +source "${HOME}/.borg-env" + +# some helpers and error handling: +info() { + printf "\n%s %s\n\n" ${DATE} "$*" >&2; + echo "$( date ) BORGBACKUP $* " >> /var/log/backup.log; +} + +trap 'echo $( date ) Backup interrupted >&2; exit 2' INT TERM + +info "Starting backup" + +# Backup the most important directories into an archive named after +# the machine this script is currently running on: + +/usr/local/bin/borg create \ + --verbose \ + --filter AME \ + --list \ + --stats \ + --show-rc \ + --compression lz4 \ + --exclude-caches \ + \ + ::"${mode}-{hostname}-{now}" \ + "${BORG_TARGETS[@]}" \ + +backup_exit=$? + +if [ $mode = "auto" ]; then + + info "Pruning repository" + + # Use the `prune` subcommand to maintain 7 daily, 4 weekly and 6 monthly + # archives of THIS machine. The '{hostname}-' prefix is very important to + # limit prune's operation to this machine's archives and not apply to + # other machines' archives also: + + /usr/local/bin/borg prune \ + --list \ + --glob-archives 'auto-*' \ + --show-rc \ + --keep-daily 7 \ + --keep-weekly 4 \ + --keep-monthly 6 \ + --keep-yearly 2 \ + + prune_exit=$? + + # actually free repo disk space by compacting segments + + info "Compacting repository" + + /usr/local/bin/borg compact + + compact_exit=$? + + # use highest exit code as global exit code + global_exit=$(( backup_exit > prune_exit ? backup_exit : prune_exit )) + global_exit=$(( compact_exit > global_exit ? compact_exit : global_exit )) + +else + global_exit=$(( compact_exit > global_exit ? compact_exit : global_exit )) +fi + +if [ ${global_exit} -eq 0 ]; then + info "Borg Backups finished successfully" +elif [ ${global_exit} -eq 1 ]; then + info "Borg Backups finished with warnings" +else + info "Borg Backups finished with errors" +fi +exit ${global_exit}