Skip to content

Instantly share code, notes, and snippets.

@gjaekel
Created February 6, 2026 06:43
Show Gist options
  • Select an option

  • Save gjaekel/dee5fd7648854d4d9fac19143ece0275 to your computer and use it in GitHub Desktop.

Select an option

Save gjaekel/dee5fd7648854d4d9fac19143ece0275 to your computer and use it in GitHub Desktop.
Restic Wrapper
#!/bin/bash
#
# 20231229/gj
# 20240314/gj keep policy
# 20240315/gj backup ALL meta source
# 20240330/gj AUTO-DRY --yes
# 20241112/gj disable cache
# 20241110/gj mention about dry run
# 20241207/gj set TMPDIR to cache dir
# 20250221/gj ensure existence of TMPDIR
# 20260206/gj add filesystem layout example
#========================================
#
# filesystem layout example
#
# root@client:/import/storage/backup# tree -L 2 restic
# restic
# ├── bin
# │   ├── _restic
# │   ├── restic -> restic_0.17.3_linux_amd64
# │   ├── _restic-remote-backup
# │   └── URL
# ├── bar
# │   ├── config
# │   ├── data
# │   ├── index
# │   ├── keys
# │   ├── locks
# │   └── snapshots
# ├── foo
# │   ├── config
# │   ├── data
# │   ├── index
# │   ├── keys
# │   ├── locks
# │   └── snapshots
# ├── _restic.bar -> bin/_restic
# ├──
# ├── _restic.bar -> bin/_restic
# └── _restic.foo -> bin/_restic
#
#----------------------------------------
REPOSITORY="${0##*.}"; [ -z "$REPOSITORY" ] && REPOSITORY="restic"
P="$(realpath $0)"
RESTIC_BASE="${P%/bin/*}"; [ ! -d "$RESTIC_BASE" ] && echo "base dir not found!" >&2 && exit -1
RESTIC_BIN="$RESTIC_BASE/bin/restic"; [ ! -x "$RESTIC_BIN" ] && echo "restic binary not found!" >&2 && exit -1
ROOT_PARTITION="$(sed 's#^/dev/\([^ ]*\) / .*#\1#p' -n /proc/mounts)"
EXCLUDES=('/mnt/*' '.cache/')
MOUNTPOINT="/tmp/restic"
PRUNE_POLICY="--max-unused 1%"
KEEP_POLICY="--keep-within-daily 7d --keep-within-weekly 1m --keep-within-monthly 1y --keep-within-yearly 1000y --prune $PRUNE_POLICY"
KEEP_POLICY="--keep-within-daily 14d --keep-within-weekly 2m --keep-within-monthly 2y --keep-within-yearly 1000y --prune $PRUNE_POLICY"
KEEP_POLICY="--keep-tag keep --keep-daily 14 --keep-weekly 8 --keep-monthly 24 --keep-yearly 1000 --prune $PRUNE_POLICY"
RESTIC () {
export TMPDIR="$HOME/.cache/restic"
[ ! -d "$TMPDIR" ] && mkdir -p "$TMPDIR" && echo "TMPDIR \"$TMPDIR \" created."
[ ! -d "$TMPDIR" ] && echo "FATAL: can't create TMPDIR \"$TMPDIR\"!" >&2 && exit -1
echo "running \"restic $@\" on repository \"$REPOSITORY\" ..." >&2
RESTIC_REPOSITORY=$RESTIC_BASE/$REPOSITORY \
RESTIC_PASSWORD=$(rev <<< citser) \
RESTIC_COMPRESSION=max \
RESTIC_READ_CONCURRENCY=$(nproc) \
$RESTIC_BIN $@
}
PARTITION_OF() { # $1: file-or-path
local PARTITION="$(findmnt -n -o SOURCE -T $1)"
echo "${PARTITION#/dev/}"
}
CMD="$1"; shift
# # auto disable cache
# [ "$CMD" -a "$CMD" != "raw" ] && NOCACHE="--no-cache" && for ARG; do shift; [ "$ARG" == "--cache" ] && NOCACHE="" && continue; set -- "$@" "$ARG"; done && [ -z "$NOCACHE" ] && echo "caching enabled"
# auto dry run
AUTO_DRY='DRY="-n"; for ARG; do shift; [ "$ARG" == "-Y" -o "${ARG^^}" == "--YES" ] && DRY="" && continue; set -- "$@" "$ARG"; done; [ -z "$DRY" ] && echo -n "*NO* "; echo "DRY RUN!"' # cancel dry run by --yes or -Y
case "$CMD" in
'raw')
CMD="$1"; shift
;;
'backup')
SRC="$1"; shift; [ -z "$SRC" ] && echo "no source directory given!" >&2 && exit -1
if [ "$SRC" == "ALL" ]; then
case "$REPOSITORY" in
'esprimo') SRCS="/mnt/sda{4,7,8}";;
'ubuntu') SRCS='/';;
*) echo "unknow repository, ALL not definied!" >&2 && exit 1
esac
SRCS="$(eval echo $SRCS)"
echo "ALL is \"$SRCS\""
for SRC in $SRCS; do
$0 backup $SRC $@
done
exit
fi
[ ! -d "$SRC" ] && echo "\"$SRC\" don't exists!" >&2 && exit -1
PARTITION="$(PARTITION_OF $SRC)"
OPTS="-v -x --no-cache --exclude-caches ${EXCLUDES[@]/#/--exclude=}"
[[ "$SRC" =~ ^/mnt/ ]] && OPTS+=" --exclude=!$SRC"
OPTS+=" ${PARTITION:+--tag $PARTITION} $SRC"
CMD="backup"
;;
'mount')
[ ! -d "$MOUNTPOINT" ] && mkdir "$MOUNTPOINT" -p && trap "rmdir $MOUNTPOINT" EXIT
OPTS="--path-template %h:%t/%T $MOUNTPOINT"
;;
'forget')
eval $AUTO_DRY
OPTS="$KEEP_POLICY${DRY:+ $DRY}"
;;
'prune')
eval $AUTO_DRY
OPTS="$PRUNE_POLICY${DRY:+ $DRY}"
esac
RESTIC "$CMD""${NOCACHE+ $NOCACHE}""${OPTS+ $OPTS}" "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment