diff --git a/auto-snapshot/Dockerfile b/auto-snapshot/Dockerfile new file mode 100644 index 0000000..b13a620 --- /dev/null +++ b/auto-snapshot/Dockerfile @@ -0,0 +1,14 @@ +ARG BUILD_FROM +FROM $BUILD_FROM + +ENV LANG C.UTF-8 + +# Copy scripts for add-on +COPY run.sh / +COPY snapshot.sh / + +RUN apk add -U jq bc curl && \ + chmod a+x /run.sh && \ + chmod a+x /snapshot.sh + +CMD [ "/run.sh" ] diff --git a/auto-snapshot/README.md b/auto-snapshot/README.md new file mode 100644 index 0000000..b0eadf8 --- /dev/null +++ b/auto-snapshot/README.md @@ -0,0 +1,4 @@ +## Auto Snapshot + +This plugins takes a snapshot of your hassio instance based on the timing you specify in config. Just use standard cron format (min hour day month weekday). +You can specify how many snapshots you want to mantain (should be >= 1). Note that snapshots are deleted after a new one is taken, so if something goes wrong, you end up with no recent snapshots and the oldest valid ones. diff --git a/auto-snapshot/config.json b/auto-snapshot/config.json new file mode 100644 index 0000000..bc47ddc --- /dev/null +++ b/auto-snapshot/config.json @@ -0,0 +1,25 @@ +{ + "name": "Auto Snapshot", + "url": "https://git.asperti.com/paspo/hassio-addons", + "version": "0.1.3", + "slug": "auto-snapshot", + "description": "Take hassio snapshots with fixed timings and manage retention. Since Homeassistant 2021.9 SNAPSHOT is renamed to BACKUP, so please use the new addon AUTO-BACKUP. This addon will not be supported anymore.", + "startup": "before", + "boot": "auto", + "arch": [ + "aarch64", + "amd64", + "armhf", + "i386" + ], + "hassio_api": true, + "hassio_role": "backup", + "options": { + "cron": "15 3 * * *", + "num_snapshots": 10 + }, + "schema": { + "cron": "str", + "num_snapshots": "int" + } +} diff --git a/auto-snapshot/icon.png b/auto-snapshot/icon.png new file mode 100644 index 0000000..6f87fa2 Binary files /dev/null and b/auto-snapshot/icon.png differ diff --git a/auto-snapshot/logo.png b/auto-snapshot/logo.png new file mode 100644 index 0000000..6f87fa2 Binary files /dev/null and b/auto-snapshot/logo.png differ diff --git a/auto-snapshot/run.sh b/auto-snapshot/run.sh new file mode 100644 index 0000000..a8c470d --- /dev/null +++ b/auto-snapshot/run.sh @@ -0,0 +1,16 @@ +#!/bin/bash +set -e + +CONFIG_PATH=/data/options.json + +CRON=$(jq --raw-output ".cron" $CONFIG_PATH) + +echo "$CRON /snapshot.sh >> /var/log/cron.log" > /var/spool/cron/crontabs/root + +# change perms +chmod 600 /var/spool/cron/crontabs/root + +echo "Auto Snapshot ready." +crond +touch /var/log/cron.log +tail -f /var/log/cron.log \ No newline at end of file diff --git a/auto-snapshot/snapshot.sh b/auto-snapshot/snapshot.sh new file mode 100644 index 0000000..19afb65 --- /dev/null +++ b/auto-snapshot/snapshot.sh @@ -0,0 +1,47 @@ +#!/bin/sh + +echo +echo "Taking a new snapshot" + +CONFIG_PATH=/data/options.json +NUM_SNAPSHOTS=$(jq --raw-output ".num_snapshots" $CONFIG_PATH) +if [ $NUM_SNAPSHOTS -lt 1 ] ; then + NUM_SNAPSHOTS=1 +fi + +# retrieve current snapshot list +CURRENT_SNAPSHOTS=$( curl -s -H "X-HASSIO-KEY: $HASSIO_TOKEN" http://hassio/snapshots ) +STATUS=$(echo "$CURRENT_SNAPSHOTS" | jq --raw-output '.result') +if [ ! "$STATUS" = "ok" ] ; then + echo "ERROR: Can't retrieve current snapshot list." + exit 1 +fi + + +# take snapshot (this can take a long time) +START_TIMESTAMP=$(date "+%s") +RESULT=$( curl -s -H "X-HASSIO-KEY: $HASSIO_TOKEN" --data '{"name":"Automatic Snapshot"}' -X POST http://hassio/snapshots/new/full ) +SNAPSHOT_TIMESTAMP=$(date "+%s") +SNAPSHOT_TIME=$(echo "$SNAPSHOT_TIMESTAMP - $START_TIMESTAMP" | bc) + +# check if snapshot is ok +STATUS=$(echo "$RESULT" | jq --raw-output '.result') +if [ ! "$STATUS" = "ok" ] ; then + echo "Snapshot FAILED after $SNAPSHOT_TIME seconds." + exit 1 +fi + +SLUG=$(echo "$RESULT" | jq --raw-output '.data.slug') +echo "Snapshot $SLUG taken SUCCESSFULLY in $SNAPSHOT_TIME seconds." + +# housekeeping: +# we take the list of snapshots (which was taken before this snapshot) +# we sort by date (reversed), remove the protected snapshots and take +# only a list of slugs +# then we skip the first NUM_SNAPSHOTS slugs and delete all the rest +FIRST_SLUG_TO_DELETE=$(echo "1 + $NUM_SNAPSHOTS" | bc) +echo $CURRENT_SNAPSHOTS | jq --raw-output ".data.snapshots | sort_by(.date) | reverse[] | select(.slug != \"$SLUG\") | select (.protected==false) | .slug " | tail -n +$FIRST_SLUG_TO_DELETE | while read SLUG_TO_DELETE + do + echo "Removing snapshot $SLUG_TO_DELETE" + curl -s -H "X-HASSIO-KEY: $HASSIO_TOKEN" -X POST http://hassio/snapshots/$SLUG_TO_DELETE/remove + done