Skip to content

Instantly share code, notes, and snippets.

@morten-olsen
Last active May 9, 2020 10:03
Show Gist options
  • Save morten-olsen/729008a69ed1f0f796d215ba8af7dc5a to your computer and use it in GitHub Desktop.
Save morten-olsen/729008a69ed1f0f796d215ba8af7dc5a to your computer and use it in GitHub Desktop.
Simple backup

Simple backup

A simple backup solution using docker and duplicati to perform remote encrypted incremental backups of a folder

Requirements

  • curl
  • docker

Installing

Run curl https://gist.githubusercontent.com/morten-olsen/729008a69ed1f0f796d215ba8af7dc5a/raw/install.sh | bash in the directory where you want to setup backup

This will install ./backup.sh which is the file to start backups and restores on the specific folder, as well as /usr/bin/dbackups.sh if not already installed, which is the man backup runner

To perform a backup run ./backup.sh backup which if first run will ask you for the target. See https://duplicati.readthedocs.io/en/latest/05-storage-providers/ for compatible targets. Currently file:// targets are not supported, due to sandboxing.

To restore the latest backup run ./backup.sh restore

It creates a .backupdb folder inside the backup location which stores backup state to facilitate managing state, and perform incremental backups.

Each run will ask for an encryption password if no "BACKUP_PASS" environmnent variable is set.

Automatic backup

The easiest way to run periodic backups is to set the script up to run in cron. Remeber that you will need the BACKUP_PASS variable set, to run it non-interactive

#!/bin/bash
SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
SOURCE="$(readlink "$SOURCE")"
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
done
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
CMD_LOCATION="/usr/bin/dbackup.sh"
GIST_ID="morten-olsen/729008a69ed1f0f796d215ba8af7dc5a"
GIST_LOCATION="https://gist.githubusercontent.com/$GIST_ID/raw/dbackup.sh"
COMMAND="$1"
shift
if [ ! -f "$CMD_LOCATION" ]; then
sudo curl "$GIST_LOCATION" -o "$CMD_LOCATION"
sudo chmod +x "$CMD_LOCATION"
fi
"$CMD_LOCATION" "$COMMAND" "$DIR"
#!/bin/bash
COMMAND="$1"
[ -f "$HOME/.secrets" ] && source "$HOME/.secrets"
shift
SOURCE="$1"
shift
DATA_LOCATION="$SOURCE/.backupdb"
CONFIG_LOCATION="$DATA_LOCATION/config"
DB_LOCATION="$DATA_LOCATION/db"
mkdir -p "$CONFIG_LOCATION"
mkdir -p "$DB_LOCATION"
TARGET="dropbox://backups/$1?authid=$DROPBOX_AUTH_TOKEN"
shift
case "$COMMAND" in
"backup")
docker run -it --rm \
-v """$SOURCE:/source""" \
-v """$CONFIG_LOCATION:/config""" \
-v """$DB_LOCATION:/app/db""" \
linuxserver/duplicati \
mono /app/duplicati/Duplicati.CommandLine.exe \
backup \
$TARGET /source \
--dbpath="/app/db/db.sqlite" \
--exclude="/source/.backupdb/*" \
--encryption-module="aes" \
--compression-module="zip" \
--dblock-size="50mb" \
--keep-time="3M" \
--passphrase="$BACKUP_PASS"
;;
"restore")
docker run -it --rm \
-v """$SOURCE:/source""" \
linuxserver/duplicati \
mono /app/duplicati/Duplicati.CommandLine.exe \
restore $TARGET \
--restore-permissions=true \
--passphrase="$BACKUP_PASS"
;;
*)
echo "Command not found";;
esac
#!/bin/bash
CMD_LOCATION="$PWD/backup.sh"
GIST_ID="morten-olsen/729008a69ed1f0f796d215ba8af7dc5a"
GIST_LOCATION="https://gist.githubusercontent.com/$GIST_ID/raw/backup.sh"
curl -o "$CMD_LOCATION" "$GIST_LOCATION"
chmod +x "$CMD_LOCATION"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment