Improve new restic scripts and remove resticwrapper, borgwrapper; provide a PKGBUILD for ArchLinux
This commit is contained in:
parent
da266c680b
commit
287fa053f5
18 changed files with 58 additions and 564 deletions
19
README.md
19
README.md
|
@ -1,22 +1,31 @@
|
|||
# README
|
||||
|
||||
A collection of scripts and systemd services which might be useful for servers.
|
||||
A collection of scripts and systemd services which might be useful.
|
||||
|
||||
After you pulled, use `./sync` and pick an action which should be self-explaining.
|
||||
Use at your own risk.
|
||||
|
||||
## Installation
|
||||
|
||||
1. After you pulled, use `./sync` and pick an action which should be self-explaining.
|
||||
2. Alternatively, build a `pacman` package for ArchLinux via `makepkg -csi` inside the `dist/` folder.
|
||||
|
||||
## Usage
|
||||
|
||||
Services and scripts don't depend on each other but have hints that they can be
|
||||
combined (out-commented line in service files for `systemd_failure_notify@.service`
|
||||
for example).
|
||||
|
||||
Use at your own risk.
|
||||
Examples are given inside `usr/share/doc/`.
|
||||
|
||||
## User network-online.target
|
||||
## FAQ
|
||||
|
||||
### User cannot use network-online.target
|
||||
|
||||
By default, no user unit can depend on system events like `network-online.target`.
|
||||
To enable this, you need to link the proper `.target` which you like to use inside
|
||||
the user service before.
|
||||
|
||||
```
|
||||
```shell
|
||||
systemctl --user link /usr/lib/systemd/system/network-online.target
|
||||
```
|
||||
|
||||
|
|
2
dist/.gitignore
vendored
Normal file
2
dist/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
dotfiles-system-git
|
||||
*.zst
|
22
dist/PKGBUILD
vendored
Normal file
22
dist/PKGBUILD
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
pkgname=dotfiles-system-git
|
||||
_pkgname="dotfiles-system"
|
||||
pkgver=r81.da266c6
|
||||
pkgrel=1
|
||||
pkgdesc="Common system helper scripts"
|
||||
arch=('any')
|
||||
url="https://git.myservermanager.com/alexander.schaeferdiek/dotfiles-system"
|
||||
makedepends=('git')
|
||||
license=('GPL')
|
||||
source=("${pkgname}::git+https://git.myservermanager.com/alexander.schaeferdiek/dotfiles-system.git")
|
||||
sha256sums=('SKIP')
|
||||
|
||||
pkgver() {
|
||||
cd ${pkgname}
|
||||
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "${srcdir}/${pkgname}"
|
||||
cp -r etc/ "${pkgdir}/etc"
|
||||
cp -r usr/ "${pkgdir}/usr"
|
||||
}
|
|
@ -10,6 +10,8 @@ Type=oneshot
|
|||
ExecStart=sh %h/.config/restic/%I-create.sh
|
||||
Environment="PATH=/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:%h/.bin"
|
||||
Environment="SSH_AUTH_SOCK=/run/user/%u/keyring/ssh"
|
||||
Environment="RESTIC_FILE_INCLUDE=%h/.config/restic/%I.include"
|
||||
Environment="RESTIC_FILE_EXCLUDE=%h/.config/restic/%I.exclude"
|
||||
EnvironmentFile=%h/.config/restic/%I.env
|
||||
|
||||
[Install]
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
[Unit]
|
||||
Description=Run borgwrapper
|
||||
#OnFailure=systemd_failure_notify@%n.service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=borgwrapper
|
||||
#ExecStart=borgwrapper /home/myUser/borgwrapper-custom.conf
|
||||
#Environment="PATH=/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/home/myUser/.customBinaryPathWithBorgSymlinkForVirtualenv"
|
||||
#Environment="SSH_AUTH_SOCK=/run/user/myUserId/keyring/ssh"
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
|
@ -1,9 +0,0 @@
|
|||
[Unit]
|
||||
Description=Run borgwrapper
|
||||
|
||||
[Timer]
|
||||
OnCalendar=20:00
|
||||
Persistent=false
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
|
@ -10,6 +10,8 @@ Type=oneshot
|
|||
ExecStart=sh %h/.config/restic/%I-create.sh
|
||||
Environment="PATH=/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:%h/.bin"
|
||||
Environment="SSH_AUTH_SOCK=/run/user/%u/keyring/ssh"
|
||||
Environment="RESTIC_FILE_INCLUDE=%h/.config/restic/%I.include"
|
||||
Environment="RESTIC_FILE_EXCLUDE=%h/.config/restic/%I.exclude"
|
||||
EnvironmentFile=%h/.config/restic/%I.env
|
||||
|
||||
[Install]
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
[Unit]
|
||||
Description=Run resticwrapper
|
||||
OnFailure=systemd_failure_notify@%n.service
|
||||
Wants=network-online.target
|
||||
After=network-online.target
|
||||
Requires=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=resticwrapper
|
||||
Environment="PATH=/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:%h/.bin"
|
||||
Environment="SSH_AUTH_SOCK=/run/user/%u/keyring/ssh"
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
|
@ -1,9 +0,0 @@
|
|||
[Unit]
|
||||
Description=Run resticwrapper
|
||||
|
||||
[Timer]
|
||||
OnCalendar=23:00
|
||||
Persistent=false
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
|
@ -1,221 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# called before backup
|
||||
borgwrapper_pre_backup() {
|
||||
return;
|
||||
}
|
||||
|
||||
# called after backup
|
||||
borgwrapper_post_backup() {
|
||||
return;
|
||||
}
|
||||
|
||||
# usage
|
||||
usage() {
|
||||
USAGE=$(cat <<EOF
|
||||
Usage: borgwrapper [CONFIG_FILE (absolute path)]
|
||||
|
||||
A script which wraps the most common use case for borg: creating a backup and sending a notification.
|
||||
|
||||
If no CONFIG_FILE is given, \$HOME/.borgwrapper.conf is used. This fallback option
|
||||
has to exist if no other CONFIG_FILE exists. Otherwise the script exits.
|
||||
|
||||
Configuration can be done in any file and any pre-defined variable can be overwritten.
|
||||
|
||||
The following are at least required for the script to work:
|
||||
- BORGWRAPPER_BACKUP_NAME // [a-z09], should be unique for multiple backups (with the same remote user)
|
||||
- BORGWRAPPER_BACKUP_FILES // an array of files and directories to backup, e.g. =('/home', '/root')
|
||||
- BORGWRAPPER_BACKUP_REPOSITORY // trailing slash, add "user@host:/dir/" if remote
|
||||
|
||||
The following are optional or have reasonable defaults:
|
||||
- BORGWRAPPER_BACKUP_PASSWORD='' // the password if needed
|
||||
- BORGWRAPPER_BACKUP_TIMESTAMP_FORMAT=$(date "+%s")
|
||||
- BORGWRAPPER_BACKUP_PRUNE=true // prune the repository (cleans old backups; uses \$BORGWRAPPER_BACKUP_KEEP_IN_DAYS)? false|true
|
||||
- BORGWRAPPER_BACKUP_KEEP_IN_DAYS=60 // in days, integer only (used for prune)
|
||||
- BORGWRAPPER_BACKUP_CHECK=true // checks entire repository, this is slow! false|true
|
||||
- BORGWRAPPER_BACKUP_CHECK_MAX_AGE_IN_SECONDS=604800 // determine when "borg check" has to run by comparing current time with latest run check (determined by last mod time of \$BORGWRAPPER_BACKUP_CHECK_FILE). default is 7 days, 0 will always run the check
|
||||
- BORGWRAPPER_BACKUP_CHECK_FILE="~/.borgwrapper-\$BORGWRAPPER_BACKUP_NAME.check" // used for time comparison
|
||||
- BORGWRAPPER_BACKUP_LOG=true // log? false|true
|
||||
- BORGWRAPPER_BACKUP_LOG_PRUNE=true // overwrite old log for each execution? false|true
|
||||
- BORGWRAPPER_BACKUP_LOG_FILE="~/.borgwrapper-\$BORGWRAPPER_BACKUP_NAME.log" // log file to save output to to
|
||||
- BORGWRAPPER_BACKUP_NOTIFY_VIA_MAIL=false // send email (\$BORGWRAPPER_BACKUP_LOG has to be set to true)? false|true
|
||||
- BORGWRAPPER_BACKUP_NOTIFY_MAIL_ADDRESS="" // mail.rc has to be configured
|
||||
- BORGWRAPPER_BACKUP_NOTIFY_UI=false // use notify-send for UI notification? false|true
|
||||
- BORGWRAPPER_BACKUP_COMPRESSION="lz4" // compress repository
|
||||
- BORGWRAPPER_BACKUP_ENCRYPTION="none" // encrypt repository
|
||||
|
||||
Borg specific values can also be overwritten and have reasonable defaults:
|
||||
- BORG_BINARY=borg; // defaults to /usr/bin/borg (determined by 'which borg'), adjust to a virtualenv if needed
|
||||
- BORGWRAPPER_BORG_INIT_PARAMS="init --encryption=\$BORGWRAPPER_BACKUP_ENCRYPTION"; // encryption=none|repokey-blake2|...
|
||||
- BORGWRAPPER_BORG_CREATE_PARAMS="create -v -s -p -C \$BORGWRAPPER_BACKUP_COMPRESSION";
|
||||
- BORGWRAPPER_BORG_CHECK_PARAMS="check -v";
|
||||
- BORGWRAPPER_BORG_PRUNE_PARAMS="prune -v -s -d \$BORGWRAPPER_BACKUP_KEEP_IN_DAYS";
|
||||
- BORGWRAPPER_BORG_LIST_PARAMS="list -v";
|
||||
- BORGWRAPPER_BORG_INFO_PARAMS="info";
|
||||
|
||||
More information can be found in the docs: https://borgbackup.readthedocs.io
|
||||
|
||||
The following functions are executed before and after the backup and can also be overwritten in the config file by redefining them:
|
||||
- borgwrapper_pre_backup
|
||||
- borgwrapper_post_backup
|
||||
|
||||
You can copy this script to '/usr/local/bin' and use create a custom CONFIG_FILE as user. Examples can be found in '/usr/share/doc/<scriptname>'.
|
||||
EOF
|
||||
)
|
||||
echo "$USAGE";
|
||||
}
|
||||
|
||||
set -e;
|
||||
|
||||
# helper functions
|
||||
source_config() {
|
||||
local config=$1;
|
||||
local configFallback=$2;
|
||||
|
||||
if [[ ! -f "$config" ]]; then
|
||||
if [[ ! -f "$configFallback" ]]; then
|
||||
echo "No config file specified and could not find default in '${configFallback}'!";
|
||||
echo "";
|
||||
usage;
|
||||
exit 1;
|
||||
else
|
||||
config=${configFallback};
|
||||
fi
|
||||
fi
|
||||
|
||||
set -a;
|
||||
source "${config}";
|
||||
set +a;
|
||||
}
|
||||
apply_defaults() {
|
||||
[[ -z ${BORGWRAPPER_BACKUP_PASSWORD} ]] && BORGWRAPPER_BACKUP_PASSWORD='';
|
||||
[[ -z ${BORGWRAPPER_BACKUP_TIMESTAMP_FORMAT} ]] && BORGWRAPPER_BACKUP_TIMESTAMP_FORMAT=$(date "+%s");
|
||||
[[ -z ${BORGWRAPPER_BACKUP_PRUNE} ]] && BORGWRAPPER_BACKUP_PRUNE=true;
|
||||
[[ -z ${BORGWRAPPER_BACKUP_KEEP_IN_DAYS} ]] && BORGWRAPPER_BACKUP_KEEP_IN_DAYS=60;
|
||||
[[ -z ${BORGWRAPPER_BACKUP_CHECK} ]] && BORGWRAPPER_BACKUP_CHECK=true;
|
||||
[[ -z ${BORGWRAPPER_BACKUP_CHECK_MAX_AGE_IN_SECONDS} ]] && BORGWRAPPER_BACKUP_CHECK_MAX_AGE_IN_SECONDS=604800;
|
||||
[[ -z ${BORGWRAPPER_BACKUP_CHECK_FILE} ]] && BORGWRAPPER_BACKUP_CHECK_FILE="$HOME/.borgwrapper-${BORGWRAPPER_BACKUP_NAME}.check";
|
||||
[[ -z ${BORGWRAPPER_BACKUP_LOG} ]] && BORGWRAPPER_BACKUP_LOG=true;
|
||||
[[ -z ${BORGWRAPPER_BACKUP_LOG_PRUNE} ]] && BORGWRAPPER_BACKUP_LOG_PRUNE=true;
|
||||
[[ -z ${BORGWRAPPER_BACKUP_LOG_FILE} ]] && BORGWRAPPER_BACKUP_LOG_FILE="$HOME/.borgwrapper-${BORGWRAPPER_BACKUP_NAME}.log";
|
||||
[[ -z ${BORGWRAPPER_BACKUP_NOTIFY_VIA_MAIL} ]] && BORGWRAPPER_BACKUP_NOTIFY_VIA_MAIL=false;
|
||||
[[ -z ${BORGWRAPPER_BACKUP_NOTIFY_MAIL_ADDRESS} ]] && BORGWRAPPER_BACKUP_NOTIFY_MAIL_ADDRESS="";
|
||||
[[ -z ${BORGWRAPPER_BACKUP_NOTIFY_UI} ]] && BORGWRAPPER_BACKUP_NOTIFY_UI=false;
|
||||
[[ -z ${BORGWRAPPER_BACKUP_COMPRESSION} ]] && BORGWRAPPER_BACKUP_COMPRESSION=none;
|
||||
[[ -z ${BORGWRAPPER_BACKUP_ENCRYPTION} ]] && BORGWRAPPER_BACKUP_ENCRYPTION=none;
|
||||
[[ -z ${BORG_BINARY} ]] && BORG_BINARY=$(which borg);
|
||||
[[ -z ${BORGWRAPPER_BORG_INIT_PARAMS} ]] && BORGWRAPPER_BORG_INIT_PARAMS="init --encryption=${BORGWRAPPER_BACKUP_ENCRYPTION}";
|
||||
[[ -z ${BORGWRAPPER_BORG_CREATE_PARAMS} ]] && BORGWRAPPER_BORG_CREATE_PARAMS="create -v -s -p -C ${BORGWRAPPER_BACKUP_COMPRESSION}";
|
||||
[[ -z ${BORGWRAPPER_BORG_CHECK_PARAMS} ]] && BORGWRAPPER_BORG_CHECK_PARAMS="check -v";
|
||||
[[ -z ${BORGWRAPPER_BORG_PRUNE_PARAMS} ]] && BORGWRAPPER_BORG_PRUNE_PARAMS="prune -v -s -d ${BORGWRAPPER_BACKUP_KEEP_IN_DAYS}";
|
||||
[[ -z ${BORGWRAPPER_BORG_LIST_PARAMS} ]] && BORGWRAPPER_BORG_LIST_PARAMS="list -v";
|
||||
[[ -z ${BORGWRAPPER_BORG_INFO_PARAMS} ]] && BORGWRAPPER_BORG_INFO_PARAMS="info";
|
||||
}
|
||||
check_required() {
|
||||
if [[ -z ${BORGWRAPPER_BACKUP_REPOSITORY} ]]; then
|
||||
echo "BORGWRAPPER_BACKUP_REPOSITORY is required"
|
||||
exit 1;
|
||||
fi
|
||||
if [[ -z ${BORGWRAPPER_BACKUP_NAME} ]]; then
|
||||
echo "BORGWRAPPER_BACKUP_NAME is required"
|
||||
exit 1;
|
||||
fi
|
||||
type ${BORG_BINARY} >/dev/null 2>&1 || { echo >&2 "Require '${BORG_BINARY}' (binary) but it's not installed. Aborting."; exit 1; }
|
||||
}
|
||||
|
||||
# define wrapper functions
|
||||
backup() {
|
||||
echo "Using ${BORG_BINARY} as binary";
|
||||
borgwrapper_pre_backup;
|
||||
|
||||
if [ ! -z "${BORGWRAPPER_BACKUP_PASSWORD}" ]; then
|
||||
export BORG_PASSPHRASE=${BORGWRAPPER_BACKUP_PASSWORD};
|
||||
fi
|
||||
|
||||
# init hint
|
||||
echo "Hint: If you haven't, you need to create the borg repository manually before first run if it doesn't exist:";
|
||||
echo "${BORG_BINARY} ${BORGWRAPPER_BORG_INIT_PARAMS} ${BORGWRAPPER_BACKUP_REPOSITORY}${BORGWRAPPER_BACKUP_NAME}";
|
||||
|
||||
# create
|
||||
${BORG_BINARY} ${BORGWRAPPER_BORG_CREATE_PARAMS} ${BORGWRAPPER_BACKUP_REPOSITORY}${BORGWRAPPER_BACKUP_NAME}::${BORGWRAPPER_BACKUP_TIMESTAMP_FORMAT} "${BORGWRAPPER_BACKUP_FILES[@]}";
|
||||
|
||||
# notify UI
|
||||
if [ "${BORGWRAPPER_BACKUP_NOTIFY_UI}" = true ]; then
|
||||
notify-send "Started backup" ${BORGWRAPPER_BACKUP_REPOSITORY}${BORGWRAPPER_BACKUP_NAME}::${BORGWRAPPER_BACKUP_TIMESTAMP_FORMAT};
|
||||
fi
|
||||
|
||||
# check
|
||||
if [ "${BORGWRAPPER_BACKUP_CHECK}" = true ]; then
|
||||
|
||||
# use for first time creation
|
||||
doCheck=false
|
||||
|
||||
if [ ! -f "${BORGWRAPPER_BACKUP_CHECK_FILE}" ]; then
|
||||
touch ${BORGWRAPPER_BACKUP_CHECK_FILE}
|
||||
doCheck=true
|
||||
fi
|
||||
|
||||
# compare date
|
||||
lastMod=$(date -r ${BORGWRAPPER_BACKUP_CHECK_FILE} +%s)
|
||||
age=$((${BORGWRAPPER_BACKUP_TIMESTAMP_FORMAT} - ${lastMod}))
|
||||
|
||||
if [ "$age" -gt "${BORGWRAPPER_BACKUP_CHECK_MAX_AGE_IN_SECONDS}" ]; then
|
||||
doCheck=true
|
||||
fi
|
||||
|
||||
|
||||
if [ "$doCheck" = true ]; then
|
||||
${BORG_BINARY} ${BORGWRAPPER_BORG_CHECK_PARAMS} ${BORGWRAPPER_BACKUP_REPOSITORY}${BORGWRAPPER_BACKUP_NAME};
|
||||
touch ${BORGWRAPPER_BACKUP_CHECK_FILE}
|
||||
fi
|
||||
fi
|
||||
|
||||
# prune
|
||||
if [ "${BORGWRAPPER_BACKUP_PRUNE}" = true ]; then
|
||||
${BORG_BINARY} ${BORGWRAPPER_BORG_PRUNE_PARAMS} ${BORGWRAPPER_BACKUP_REPOSITORY}${BORGWRAPPER_BACKUP_NAME};
|
||||
fi
|
||||
|
||||
# log
|
||||
if [ "${BORGWRAPPER_BACKUP_LOG}" = true ]; then
|
||||
|
||||
if [ "${BORGWRAPPER_BACKUP_LOG_PRUNE}" = true ] && [ -f "${BORGWRAPPER_BACKUP_LOG_FILE}" ]; then
|
||||
rm ${BORGWRAPPER_BACKUP_LOG_FILE};
|
||||
fi
|
||||
|
||||
touch ${BORGWRAPPER_BACKUP_LOG_FILE};
|
||||
${BORG_BINARY} ${BORGWRAPPER_BORG_LIST_PARAMS} ${BORGWRAPPER_BACKUP_REPOSITORY}${BORGWRAPPER_BACKUP_NAME} >> ${BORGWRAPPER_BACKUP_LOG_FILE};
|
||||
echo "---" >> ${BORGWRAPPER_BACKUP_LOG_FILE};
|
||||
${BORG_BINARY} ${BORGWRAPPER_BORG_INFO_PARAMS} ${BORGWRAPPER_BACKUP_REPOSITORY}${BORGWRAPPER_BACKUP_NAME}::${BORGWRAPPER_BACKUP_TIMESTAMP_FORMAT} >> ${BORGWRAPPER_BACKUP_LOG_FILE};
|
||||
|
||||
if [ "${BORGWRAPPER_BACKUP_NOTIFY_VIA_MAIL}" = true ]; then
|
||||
local hostname=$(hostname)
|
||||
cat ${BORGWRAPPER_BACKUP_LOG_FILE}|mailx -Ssendwait -s "[borgwrapper on ${hostname}] ${BORGWRAPPER_BACKUP_REPOSITORY}${BORGWRAPPER_BACKUP_NAME}::${BORGWRAPPER_BACKUP_TIMESTAMP_FORMAT} finished" ${BORGWRAPPER_BACKUP_NOTIFY_MAIL_ADDRESS};
|
||||
fi
|
||||
fi
|
||||
|
||||
# notify UI
|
||||
if [ "${BORGWRAPPER_BACKUP_NOTIFY_UI}" = true ]; then
|
||||
notify-send "Finished backup" ${BORGWRAPPER_BACKUP_REPOSITORY}${BORGWRAPPER_BACKUP_NAME}::${BORGWRAPPER_BACKUP_TIMESTAMP_FORMAT};
|
||||
fi
|
||||
|
||||
borgwrapper_post_backup;
|
||||
}
|
||||
|
||||
# check requirements
|
||||
CONFIG_FILE="$1";
|
||||
FALLBACK_CONFIG_FILE="${HOME}/.borgwrapper.conf";
|
||||
source_config "${CONFIG_FILE}" "${FALLBACK_CONFIG_FILE}";
|
||||
apply_defaults;
|
||||
check_required;
|
||||
|
||||
COMMAND="backup"
|
||||
case "$COMMAND" in
|
||||
backup)
|
||||
backup;
|
||||
;;
|
||||
*)
|
||||
echo "Unsupported command or no command given" >&2
|
||||
usage;
|
||||
exit 1
|
||||
;;
|
||||
esac
|
|
@ -1,225 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# called before backup
|
||||
resticwrapper_pre_backup() {
|
||||
return;
|
||||
}
|
||||
|
||||
# called after backup
|
||||
resticwrapper_post_backup() {
|
||||
return;
|
||||
}
|
||||
|
||||
# usage
|
||||
usage() {
|
||||
USAGE=$(cat <<EOF
|
||||
Usage: resticwrapper [CONFIG_FILE (absolute path)]
|
||||
|
||||
A script which wraps the most common use case for restic: creating a backup and sending a notification.
|
||||
|
||||
If no CONFIG_FILE is given, \$HOME/.resticwrapper.conf is used. This fallback option
|
||||
has to exist if no other CONFIG_FILE exists. Otherwise the script exits.
|
||||
|
||||
Configuration can be done in any file and any pre-defined variable can be overwritten.
|
||||
|
||||
The following are at least required for the script to work:
|
||||
- RESTICWRAPPER_BACKUP_NAME // [a-z09], should be unique for multiple backups (with the same remote user)
|
||||
- RESTICWRAPPER_BACKUP_FILES // an array of files and directories to backup, e.g. =('/home', '/root')
|
||||
- RESTICWRAPPER_BACKUP_REPOSITORY // trailing slash, add "user@host:/dir/" if remote
|
||||
|
||||
The following are optional or have reasonable defaults:
|
||||
- RESTICWRAPPER_BACKUP_PASSWORD='' // the password if needed
|
||||
- RESTICWRAPPER_BACKUP_PASSWORD_FILE='' // a password file if needed
|
||||
- RESTICWRAPPER_BACKUP_PRUNE=true // prune the repository (cleans old backups; uses \$RESTICWRAPPER_BACKUP_KEEP_IN_DAYS)? false|true
|
||||
- RESTICWRAPPER_BACKUP_KEEP_IN_DAYS=60 // in days, integer only (used for prune)
|
||||
- RESTICWRAPPER_BACKUP_CHECK=true // checks entire repository, this is slow! false|true
|
||||
- RESTICWRAPPER_BACKUP_CHECK_MAX_AGE_IN_SECONDS=604800 // determine when "restic check" has to run by comparing current time with latest run check (determined by last mod time of \$RESTICWRAPPER_BACKUP_CHECK_FILE). default is 7 days, 0 will always run the check
|
||||
- RESTICWRAPPER_BACKUP_CHECK_FILE="~/.resticwrapper-\$RESTICWRAPPER_BACKUP_NAME.check" // used for time comparison
|
||||
- RESTICWRAPPER_BACKUP_LOG=true // log? false|true
|
||||
- RESTICWRAPPER_BACKUP_LOG_PRUNE=true // overwrite old log for each execution? false|true
|
||||
- RESTICWRAPPER_BACKUP_LOG_FILE="~/.resticwrapper-\$RESTICWRAPPER_BACKUP_NAME.log" // log file to save output to to
|
||||
- RESTICWRAPPER_BACKUP_NOTIFY_VIA_MAIL=false // send email (\$RESTICWRAPPER_BACKUP_LOG has to be set to true)? false|true
|
||||
- RESTICWRAPPER_BACKUP_NOTIFY_MAIL_ADDRESS="" // mail.rc has to be configured
|
||||
- RESTICWRAPPER_BACKUP_NOTIFY_UI=false // use notify-send for UI notification? false|true
|
||||
|
||||
Borg specific values can also be overwritten and have reasonable defaults:
|
||||
- RESTIC_BINARY=restic; // defaults to /usr/bin/restic (determined by 'which restic'), adjust to a virtualenv if needed
|
||||
- RESTICWRAPPER_RESTIC_INIT_PARAMS="init -r=\${RESTICWRAPPER_BACKUP_REPOSITORY}\${RESTICWRAPPER_BACKUP_NAME}";
|
||||
- RESTICWRAPPER_RESTIC_CREATE_PARAMS="backup --verbose";
|
||||
- RESTICWRAPPER_RESTIC_CHECK_PARAMS="check";
|
||||
- RESTICWRAPPER_RESTIC_PRUNE_PARAMS="forget --prune --keep-within 0y0m\${RESTICWRAPPER_BACKUP_KEEP_IN_DAYS}d0h";
|
||||
- RESTICWRAPPER_RESTIC_LIST_PARAMS="snapshots";
|
||||
- RESTICWRAPPER_RESTIC_INFO_PARAMS="stats";
|
||||
|
||||
More information can be found in the docs: https://restic.readthedocs.io
|
||||
|
||||
The following functions are executed before and after the backup and can also be overwritten in the config file by redefining them:
|
||||
- resticwrapper_pre_backup
|
||||
- resticwrapper_post_backup
|
||||
|
||||
You can copy this script to '/usr/local/bin' and use create a custom CONFIG_FILE as user. Examples can be found in '/usr/share/doc/<scriptname>'.
|
||||
EOF
|
||||
)
|
||||
echo "$USAGE";
|
||||
}
|
||||
|
||||
set -e;
|
||||
|
||||
# helper functions
|
||||
source_config() {
|
||||
local config=$1;
|
||||
local configFallback=$2;
|
||||
|
||||
if [[ ! -f "$config" ]]; then
|
||||
if [[ ! -f "$configFallback" ]]; then
|
||||
echo "No config file specified and could not find default in '${configFallback}'!";
|
||||
echo "";
|
||||
usage;
|
||||
exit 1;
|
||||
else
|
||||
config=${configFallback};
|
||||
fi
|
||||
fi
|
||||
|
||||
set -a;
|
||||
source "${config}";
|
||||
set +a;
|
||||
}
|
||||
apply_defaults() {
|
||||
[[ -z ${RESTICWRAPPER_BACKUP_PASSWORD} ]] && RESTICWRAPPER_BACKUP_PASSWORD='';
|
||||
[[ -z ${RESTICWRAPPER_BACKUP_PASSWORD_FILE} ]] && RESTICWRAPPER_BACKUP_PASSWORD_FILE='';
|
||||
[[ -z ${RESTICWRAPPER_BACKUP_PRUNE} ]] && RESTICWRAPPER_BACKUP_PRUNE=true;
|
||||
[[ -z ${RESTICWRAPPER_BACKUP_KEEP_IN_DAYS} ]] && RESTICWRAPPER_BACKUP_KEEP_IN_DAYS=60;
|
||||
[[ -z ${RESTICWRAPPER_BACKUP_CHECK} ]] && RESTICWRAPPER_BACKUP_CHECK=true;
|
||||
[[ -z ${RESTICWRAPPER_BACKUP_CHECK_MAX_AGE_IN_SECONDS} ]] && RESTICWRAPPER_BACKUP_CHECK_MAX_AGE_IN_SECONDS=604800;
|
||||
[[ -z ${RESTICWRAPPER_BACKUP_CHECK_FILE} ]] && RESTICWRAPPER_BACKUP_CHECK_FILE="$HOME/.resticwrapper-${RESTICWRAPPER_BACKUP_NAME}.check";
|
||||
[[ -z ${RESTICWRAPPER_BACKUP_LOG} ]] && RESTICWRAPPER_BACKUP_LOG=true;
|
||||
[[ -z ${RESTICWRAPPER_BACKUP_LOG_PRUNE} ]] && RESTICWRAPPER_BACKUP_LOG_PRUNE=true;
|
||||
[[ -z ${RESTICWRAPPER_BACKUP_LOG_FILE} ]] && RESTICWRAPPER_BACKUP_LOG_FILE="$HOME/.resticwrapper-${RESTICWRAPPER_BACKUP_NAME}.log";
|
||||
[[ -z ${RESTICWRAPPER_BACKUP_NOTIFY_VIA_MAIL} ]] && RESTICWRAPPER_BACKUP_NOTIFY_VIA_MAIL=false;
|
||||
[[ -z ${RESTICWRAPPER_BACKUP_NOTIFY_MAIL_ADDRESS} ]] && RESTICWRAPPER_BACKUP_NOTIFY_MAIL_ADDRESS="";
|
||||
[[ -z ${RESTICWRAPPER_BACKUP_NOTIFY_UI} ]] && RESTICWRAPPER_BACKUP_NOTIFY_UI=false;
|
||||
[[ -z ${RESTIC_BINARY} ]] && RESTIC_BINARY=$(which restic);
|
||||
[[ -z ${RESTICWRAPPER_RESTIC_INIT_PARAMS} ]] && RESTICWRAPPER_RESTIC_INIT_PARAMS="init -r ${RESTIC_REPOSITORY}";
|
||||
[[ -z ${RESTICWRAPPER_RESTIC_CREATE_PARAMS} ]] && RESTICWRAPPER_RESTIC_CREATE_PARAMS="backup --verbose";
|
||||
[[ -z ${RESTICWRAPPER_RESTIC_CHECK_PARAMS} ]] && RESTICWRAPPER_RESTIC_CHECK_PARAMS="check";
|
||||
[[ -z ${RESTICWRAPPER_RESTIC_PRUNE_PARAMS} ]] && RESTICWRAPPER_RESTIC_PRUNE_PARAMS="forget --prune --keep-within 0y0m${RESTICWRAPPER_BACKUP_KEEP_IN_DAYS}d0h";
|
||||
[[ -z ${RESTICWRAPPER_RESTIC_LIST_PARAMS} ]] && RESTICWRAPPER_RESTIC_LIST_PARAMS="snapshots";
|
||||
[[ -z ${RESTICWRAPPER_RESTIC_INFO_PARAMS} ]] && RESTICWRAPPER_RESTIC_INFO_PARAMS="stats";
|
||||
}
|
||||
check_required() {
|
||||
if [[ -z ${RESTICWRAPPER_BACKUP_REPOSITORY} ]]; then
|
||||
echo "RESTICWRAPPER_BACKUP_REPOSITORY is required"
|
||||
exit 1;
|
||||
fi
|
||||
if [[ -z ${RESTICWRAPPER_BACKUP_NAME} ]]; then
|
||||
echo "RESTICWRAPPER_BACKUP_NAME is required"
|
||||
exit 1;
|
||||
fi
|
||||
type ${RESTIC_BINARY} >/dev/null 2>&1 || { echo >&2 "Require '${RESTIC_BINARY}' (binary) but it's not installed. Aborting."; exit 1; }
|
||||
}
|
||||
|
||||
# define wrapper functions
|
||||
backup() {
|
||||
echo "Using ${RESTIC_BINARY} as binary";
|
||||
resticwrapper_pre_backup;
|
||||
|
||||
set -a;
|
||||
RESTIC_REPOSITORY="${RESTICWRAPPER_BACKUP_REPOSITORY}${RESTICWRAPPER_BACKUP_NAME}";
|
||||
set +a;
|
||||
|
||||
if [ ! -z "${RESTICWRAPPER_BACKUP_PASSWORD}" ]; then
|
||||
export RESTIC_PASSWORD=${RESTICWRAPPER_BACKUP_PASSWORD};
|
||||
fi
|
||||
|
||||
if [ ! -z "${RESTICWRAPPER_BACKUP_PASSWORD_FILE}" ]; then
|
||||
export RESTIC_PASSWORD_FILE=${RESTICWRAPPER_BACKUP_PASSWORD};
|
||||
fi
|
||||
|
||||
# init hint
|
||||
echo "Hint: If you haven't, you need to create the restic repository manually before first run if it doesn't exist:";
|
||||
echo "${RESTIC_BINARY} ${RESTICWRAPPER_RESTIC_INIT_PARAMS} ${RESTICWRAPPER_BACKUP_REPOSITORY}${RESTICWRAPPER_BACKUP_NAME}";
|
||||
|
||||
# create
|
||||
${RESTIC_BINARY} ${RESTICWRAPPER_RESTIC_CREATE_PARAMS} "${RESTICWRAPPER_BACKUP_FILES[@]}"
|
||||
|
||||
# notify UI
|
||||
if [ "${RESTICWRAPPER_BACKUP_NOTIFY_UI}" = true ]; then
|
||||
notify-send "Started backup" ${RESTIC_REPOSITORY};
|
||||
fi
|
||||
|
||||
# check
|
||||
if [ "${RESTICWRAPPER_BACKUP_CHECK}" = true ]; then
|
||||
|
||||
# use for first time creation
|
||||
doCheck=false
|
||||
|
||||
if [ ! -f "${RESTICWRAPPER_BACKUP_CHECK_FILE}" ]; then
|
||||
touch ${RESTICWRAPPER_BACKUP_CHECK_FILE}
|
||||
doCheck=true
|
||||
fi
|
||||
|
||||
# compare date
|
||||
lastMod=$(date -r ${RESTICWRAPPER_BACKUP_CHECK_FILE} +%s)
|
||||
age=$(($(date "+%s") - ${lastMod}))
|
||||
|
||||
if [ "$age" -gt "${RESTICWRAPPER_BACKUP_CHECK_MAX_AGE_IN_SECONDS}" ]; then
|
||||
doCheck=true
|
||||
fi
|
||||
|
||||
|
||||
if [ "$doCheck" = true ]; then
|
||||
${RESTIC_BINARY} ${RESTICWRAPPER_RESTIC_CHECK_PARAMS};
|
||||
touch ${RESTICWRAPPER_BACKUP_CHECK_FILE}
|
||||
fi
|
||||
fi
|
||||
|
||||
# prune
|
||||
if [ "${RESTICWRAPPER_BACKUP_PRUNE}" = true ]; then
|
||||
${RESTIC_BINARY} ${RESTICWRAPPER_RESTIC_PRUNE_PARAMS};
|
||||
fi
|
||||
|
||||
# log
|
||||
if [ "${RESTICWRAPPER_BACKUP_LOG}" = true ]; then
|
||||
|
||||
if [ "${RESTICWRAPPER_BACKUP_LOG_PRUNE}" = true ] && [ -f "${RESTICWRAPPER_BACKUP_LOG_FILE}" ]; then
|
||||
rm ${RESTICWRAPPER_BACKUP_LOG_FILE};
|
||||
fi
|
||||
|
||||
touch ${RESTICWRAPPER_BACKUP_LOG_FILE};
|
||||
${RESTIC_BINARY} ${RESTICWRAPPER_RESTIC_LIST_PARAMS} >> ${RESTICWRAPPER_BACKUP_LOG_FILE};
|
||||
echo "---" >> ${RESTICWRAPPER_BACKUP_LOG_FILE};
|
||||
${RESTIC_BINARY} ${RESTICWRAPPER_RESTIC_INFO_PARAMS} >> ${RESTICWRAPPER_BACKUP_LOG_FILE};
|
||||
|
||||
if [ "${RESTICWRAPPER_BACKUP_NOTIFY_VIA_MAIL}" = true ]; then
|
||||
local hostname=$(hostname)
|
||||
cat ${RESTICWRAPPER_BACKUP_LOG_FILE}|mailx -Ssendwait -s "[resticwrapper on ${hostname} for ${RESTICWRAPPER_BACKUP_NAME}]" ${RESTICWRAPPER_BACKUP_NOTIFY_MAIL_ADDRESS};
|
||||
fi
|
||||
fi
|
||||
|
||||
# notify UI
|
||||
if [ "${RESTICWRAPPER_BACKUP_NOTIFY_UI}" = true ]; then
|
||||
notify-send "Finished backup" ${RESTIC_REPOSITORY};
|
||||
fi
|
||||
|
||||
resticwrapper_post_backup;
|
||||
}
|
||||
|
||||
# check requirements
|
||||
CONFIG_FILE="$1";
|
||||
FALLBACK_CONFIG_FILE="${HOME}/.resticwrapper.conf";
|
||||
source_config "${CONFIG_FILE}" "${FALLBACK_CONFIG_FILE}";
|
||||
apply_defaults;
|
||||
check_required;
|
||||
|
||||
COMMAND="backup"
|
||||
case "$COMMAND" in
|
||||
backup)
|
||||
backup;
|
||||
;;
|
||||
*)
|
||||
echo "Unsupported command or no command given" >&2
|
||||
usage;
|
||||
exit 1
|
||||
;;
|
||||
esac
|
|
@ -1,15 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
BORGWRAPPER_BACKUP_NAME="backup-name"
|
||||
BORGWRAPPER_BACKUP_REPOSITORY="/mnt/myBackups/"
|
||||
BORGWRAPPER_BACKUP_FILES=(\
|
||||
'/etc/' \
|
||||
'$HOME/' \
|
||||
)
|
||||
|
||||
borgwrapper_pre_backup() {
|
||||
return;
|
||||
}
|
||||
|
||||
borgwrapper_post_backup() {
|
||||
return;
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
#BORG_RSH="ssh -i /path/to/another/rsa_key/.ssh/backup-key"
|
||||
BORGWRAPPER_BACKUP_NAME="backup-name"
|
||||
BORGWRAPPER_BACKUP_REPOSITORY="ssh://user@remoteHost:Port/./"
|
||||
BORGWRAPPER_BACKUP_FILES=(\
|
||||
'/etc/' \
|
||||
'$HOME/' \
|
||||
)
|
||||
BORGWRAPPER_BACKUP_ENCRYPTION="repokey-blake2"
|
||||
BORGWRAPPER_BACKUP_PASSWORD="secretPassword"
|
||||
BORGWRAPPER_BORG_CREATE_PARAMS="create -v -s -p --exclude-from /path/to/.borgwrapper.exclude"
|
||||
BORGWRAPPER_BACKUP_LOG=true
|
||||
BORGWRAPPER_BACKUP_NOTIFY_VIA_MAIL=true
|
||||
BORGWRAPPER_BACKUP_NOTIFY_MAIL_ADDRESS="alias@domain.tld"
|
||||
|
||||
borgwrapper_pre_backup() {
|
||||
return;
|
||||
}
|
||||
|
||||
borgwrapper_post_backup() {
|
||||
return;
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
/proc/**
|
||||
/var/log/**
|
||||
*/build/**
|
||||
*/node_modules/**
|
|
@ -1,11 +1,12 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
/usr/bin/restic backup \
|
||||
--one-file-system \
|
||||
--exclude-file /home/myuser/.config/restic/mybackup.exclude \
|
||||
--files-from /home/myuser/.config/restic/mybackup.include
|
||||
# pre action or use ExecStartPre
|
||||
|
||||
/usr/bin/restic forget \
|
||||
--keep-daily 7 \
|
||||
--keep-weekly 4 \
|
||||
--keep-monthly 3
|
||||
/usr/bin/restic backup \
|
||||
"${RESTIC_ADDITIONAL_CREATE_PARAMS}" \
|
||||
--exclude-file "${RESTIC_FILE_EXCLUDE}" \
|
||||
--files-from "${RESTIC_FILE_INCLUDE}"
|
||||
|
||||
/usr/bin/restic forget "${RESTIC_KEEP}"
|
||||
|
||||
# post action or adapt ExecStartPost
|
|
@ -12,3 +12,7 @@ RESTIC_CACHE_DIR="..."
|
|||
RESTIC_PASSWORD="..."
|
||||
#RESTIC_REPOSITORY="sftp://restic-mybackup//my/remote/path"
|
||||
RESTIC_REPOSITORY="..."
|
||||
RESTIC_KEEP="--keep-daily 7 --keep-weekly 4 --keep-monthly 3"
|
||||
|
||||
# advanced parameters
|
||||
RESTIC_ADDITIONAL_CREATE_PARAMS="--one-file-system"
|
|
@ -1,3 +1,4 @@
|
|||
/home/lost+found
|
||||
/home/**/.cache
|
||||
*.bak/**
|
||||
*/.cache/**
|
|
@ -1,16 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
RESTICWRAPPER_BACKUP_NAME="backup-name"
|
||||
RESTICWRAPPER_BACKUP_REPOSITORY="/mnt/myBackups/"
|
||||
RESTICWRAPPER_BACKUP_FILES=(\
|
||||
'/etc/' \
|
||||
'$HOME/' \
|
||||
)
|
||||
RESTICWRAPPER_BACKUP_PASSWORD="myPassword"
|
||||
|
||||
resticwrapper_pre_backup() {
|
||||
return;
|
||||
}
|
||||
|
||||
resticwrapper_post_backup() {
|
||||
return;
|
||||
}
|
Loading…
Reference in a new issue