├── etc └── backup │ ├── local.post │ ├── local.pre │ ├── example.repo │ ├── local.config │ └── local.exclude ├── README.md ├── LICENSE └── bin └── backup /etc/backup/local.post: -------------------------------------------------------------------------------- 1 | # run commands after the backup (script must be executable) 2 | -------------------------------------------------------------------------------- /etc/backup/local.pre: -------------------------------------------------------------------------------- 1 | # run commands before the backup (script must be executable) 2 | -------------------------------------------------------------------------------- /etc/backup/example.repo: -------------------------------------------------------------------------------- 1 | RESTIC_REPOSITORY=s3:http://example.org:9000/restic 2 | RESTIC_PASSWORD=REPO_PASSWORD 3 | AWS_SECRET_ACCESS_KEY=ACCESS_KEY 4 | AWS_ACCESS_KEY_ID=ACCESS_KEY_ID 5 | -------------------------------------------------------------------------------- /etc/backup/local.config: -------------------------------------------------------------------------------- 1 | BACKUP_HOSTNAME=$(hostname -f) 2 | BACKUP_DIR="/" 3 | BACKUP_ARGS="--tag filesystem" 4 | # HEALTHCHECK_URL="" 5 | # RESTIC_ARGS="" 6 | -------------------------------------------------------------------------------- /etc/backup/local.exclude: -------------------------------------------------------------------------------- 1 | /dev 2 | /lost+found 3 | /media 4 | /mnt 5 | /proc 6 | /run 7 | /sys 8 | /tmp 9 | /var/spool 10 | /var/run 11 | /var/tmp 12 | /var/log 13 | *.swp 14 | /boot 15 | /lib 16 | /lib64 17 | /bin/ 18 | /sbin/ 19 | /usr/sbin 20 | .cache 21 | cache 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # restic-tools 2 | Wrapper around restic backup to simplify certain tasks. 3 | Repositories can be configured in `/etc/backup/$REPO.repo`. 4 | Local includes and excludes in `/etc/backup/local.config` or `/etc/backup/local.exclude` 5 | 6 | * `backup $REPO local` for local backup to repo configured by 7 | * `backup $REPO monitor $HOST $WARN_HOURS $CRIT_HOURS` for Nagios/Icinga checks of backups 8 | * `backup $REPO $ARGUMENTS` for invoking restic with $ARGUMENTS for the repository 9 | 10 | In `local.config`: 11 | * `BACKUP_HOSTNAME` is the name your host will show up as in restic 12 | * `BACKUP_DIR` is the root of the directory you want to back up 13 | * `HEALTHCHECK_URL` is an optional URL to [healthchecks.io](https://healthchecks.io/checks/) (comment out if you don't need it) 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Alexander Rust 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /bin/backup: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | set -uo pipefail 3 | 4 | display_usage() { 5 | echo "Usage: $0 (local|monitor |restic arguments)" >&2 6 | } 7 | 8 | if [ "$#" -lt 2 ]; then 9 | display_usage 10 | exit 1 11 | fi 12 | 13 | TARGET=$1 14 | ACTION=$2 15 | RESTIC=$(which restic) 16 | CURL=$(which curl) 17 | 18 | check_config() { 19 | CONFIG=/etc/backup/$1.repo 20 | if [ ! -f $CONFIG ]; then 21 | echo "Repo config file $CONFIG not found!" 22 | exit 1 23 | else 24 | set -a 25 | source $CONFIG 26 | set +a 27 | fi 28 | 29 | 30 | if [[ ! -x $RESTIC ]]; then 31 | echo "Restic binary not found" 32 | exit 1 33 | fi 34 | } 35 | 36 | handle_params () { 37 | 38 | . /etc/backup/local.config 39 | if [ $2 == "local" ]; then 40 | do_local_backup 41 | elif [ $2 == "monitor" ]; then 42 | do_monitor $@ 43 | else 44 | shift 1 45 | # define an empty default if RESTIC_ARGS is not set 46 | RESTIC_ARGS=${RESTIC_ARGS:-""} 47 | $RESTIC $RESTIC_ARGS $@ 48 | fi 49 | } 50 | 51 | 52 | do_local_backup () { 53 | if [ ! -f /etc/backup/local.config ]; then 54 | echo "local backup config file $/etc/backup/local.config not found!" 55 | exit 1 56 | fi 57 | 58 | . /etc/backup/local.config 59 | 60 | # define an empty default if BACKUP_ARGS is not set 61 | BACKUP_ARGS=${BACKUP_ARGS:-""} 62 | 63 | if [[ -x /etc/backup/local.pre ]]; then 64 | /etc/backup/local.pre $TARGET 65 | fi 66 | 67 | $RESTIC --exclude-file /etc/backup/local.exclude backup --host $BACKUP_HOSTNAME $BACKUP_ARGS $BACKUP_DIR 68 | 69 | if [[ -x /etc/backup/local.post ]]; then 70 | /etc/backup/local.post $TARGET 71 | fi 72 | 73 | if [[ -n "${HEALTHCHECK_URL:-}" ]]; then 74 | if [[ -x $CURL ]]; then 75 | $CURL -fsS --retry 4 "$HEALTHCHECK_URL" > /dev/null 76 | fi 77 | fi 78 | } 79 | 80 | do_monitor () { 81 | if [ $# -lt 5 ]; then 82 | display_usage 83 | exit 1; 84 | fi 85 | WARN=$4 86 | CRIT=$5 87 | 88 | # define an empty default if RESTIC_ARGS is not set 89 | RESTIC_ARGS=${RESTIC_ARGS:-""} 90 | SNAPS=`$RESTIC $RESTIC_ARGS snapshots --compact --no-lock -H $3` 91 | # Get last line and parse into variables. Removes header and is empty when no snapshot exists for host 92 | LAST=`sed 1,2d <<< $SNAPS | head -n -2 | tail -n 1` 93 | COUNT=`tail -n 1 <<< $SNAPS | cut -d " " -f 1` 94 | if [ ! $? -eq 0 ]; then 95 | echo "WARNING - restic command returned an error" 96 | exit 1; 97 | fi 98 | 99 | IFS=' ' read HASH DATE TIME HOST DIR <<< "$LAST" 100 | 101 | if [ -z "$HASH" ]; then 102 | echo "UNKNOWN - No snapshot found for $3" 103 | exit 4; 104 | fi 105 | 106 | 107 | # Compute time difference since last snapshot 108 | case $(uname -s) in 109 | Darwin) 110 | BACKUP_TST=$(date -j -f "%Y-%m-%d %H:%M:%S" "$DATE $TIME" "+%s") 111 | ;; 112 | *) 113 | BACKUP_TST=$(date -d "$DATE $TIME" +"%s" ) 114 | ;; 115 | esac 116 | 117 | NOW_TST=$(date +%s) 118 | DIFF_S=`expr $NOW_TST - $BACKUP_TST` 119 | 120 | DIFF_H=`expr $DIFF_S / 3600` 121 | 122 | MESSAGE="Last snapshot #$HASH ${DIFF_H}h ago|snapshots=$COUNT; age=$DIFF_H" 123 | RET=0 124 | RET_H="OK" 125 | 126 | if [ $DIFF_H -lt $WARN ]; then 127 | RET=0 128 | RET_H="OK" 129 | elif [ $DIFF_H -lt $CRIT ]; then 130 | RET=1 131 | RET_H="WARNING" 132 | else 133 | RET=2 134 | RET_H="CRITICAL" 135 | 136 | fi 137 | echo "$RET_H - $MESSAGE" 138 | return $RET 139 | } 140 | 141 | check_config $@ 142 | handle_params $@ 143 | --------------------------------------------------------------------------------