diff --git a/.env.sample b/.env.sample index fc4f2db..3db56ad 100644 --- a/.env.sample +++ b/.env.sample @@ -8,6 +8,11 @@ RESTIC_REPOSITORY=/backups/restic CRON_SCHEDULE='30 3 * * *' +# Push Notifiactions +#PUSH_URL_START=https://status.example.com/api/push/xxxxxxxxxx?status=up&msg=start +#PUSH_URL_SUCCESS=https://status.example.com/api/push/xxxxxxxxxx?status=up&msg=OK +#PUSH_URL_FAIL=https://status.example.com/api/push/xxxxxxxxxx?status=down&msg=fail + # swarm-cronjob, instead of built-in cron #COMPOSE_FILE="$COMPOSE_FILE:compose.swarm-cronjob.yml" diff --git a/README.md b/README.md index bf09e96..69e4232 100644 --- a/README.md +++ b/README.md @@ -38,12 +38,12 @@ Backupbot II tries to help, by * `abra app new backup-bot-two` * `abra app config ` - set storage options. Either configure `CRON_SCHEDULE`, or set up `swarm-cronjob` -* `abra app secret generate -a ` +* `abra app secret generate -a ` * `abra app deploy ` ## Configuration -Per default Backupbot stores the backups locally in the repository `/backups/restic`, which is accessible as volume at `/var/lib/docker/volumes/_backups/_data/restic/` +Per default Backupbot stores the backups locally in the repository `/backups/restic`, which is accessible as volume at `/var/lib/docker/volumes/_backups/_data/restic/` The backup location can be changed using the `RESTIC_REPOSITORY` env variable. @@ -57,7 +57,7 @@ AWS_ACCESS_KEY_ID= COMPOSE_FILE="$COMPOSE_FILE:compose.s3.yml" ``` and add your `` as docker secret: -`abra app secret insert aws_secret_access_key v1 ` +`abra app secret insert aws_secret_access_key v1 ` See [restic s3 docs](https://restic.readthedocs.io/en/latest/030_preparing_a_new_repo.html#amazon-s3) for more information. @@ -79,7 +79,7 @@ Add the key to your `authorized_keys`: `ssh-copy-id -i backupkey @` Add your `SSH_KEY` as docker secret: ``` -abra app secret insert ssh_key v1 """$(cat backupkey) +abra app secret insert ssh_key v1 """$(cat backupkey) """ ``` > Attention: This command needs to be executed exactly as stated above, because it places a trailing newline at the end, if this is missing you will get the following error: `Load key "/run/secrets/ssh_key": error in libcrypto` @@ -95,67 +95,81 @@ COMPOSE_FILE="$COMPOSE_FILE:compose.secret.yml" ``` Add your REST server url as secret: ``` -`abra app secret insert restic_repo v1 "rest:https://user:pass@host:8000/"` +`abra app secret insert restic_repo v1 "rest:https://user:pass@host:8000/"` ``` The secret will overwrite the `RESTIC_REPOSITORY` variable. See [restic REST docs](https://restic.readthedocs.io/en/latest/030_preparing_a_new_repo.html#rest-server) for more information. +## Push notifications + +The following env variables can be used to setup push notifications for backups. `PUSH_URL_START` is requested just before the backups starts, `PUSH_URL_SUCCESS` is only requested if the backup was successful and if the backup fails `PUSH_URL_FAIL` will be requested. +Each variable is optional and independent of the other. +``` + +PUSH_URL_START=https://status.example.com/api/push/xxxxxxxxxx?status=up&msg=start +PUSH_URL_SUCCESS=https://status.example.com/api/push/xxxxxxxxxx?status=up&msg=OK +PUSH_URL_FAIL=https://status.example.com/api/push/xxxxxxxxxx?status=down&msg=fail +``` + + ## Usage +Run the cronjob that creates a backup, including the push notifications and docker logging: +`abra app run app run_cron` Create a backup of all apps: -`abra app run app -- backup create` +`abra app run app -- backup create` > The apps to backup up need to be deployed Create an individual backup: -`abra app run app -- backup --host create` +`abra app run app -- backup --host create` Create a backup to a local repository: -`abra app run app -- backup create -r /backups/restic` +`abra app run app -- backup create -r /backups/restic` > It is recommended to shutdown/undeploy an app before restoring the data Restore the latest snapshot of all including apps: -`abra app run app -- backup restore` +`abra app run app -- backup restore` Restore a specific snapshot of an individual app: -`abra app run app -- backup --host restore --snapshot ` +`abra app run app -- backup --host restore --snapshot ` Show all snapshots: -`abra app run app -- backup snapshots` +`abra app run app -- backup snapshots` Show all snapshots containing a specific app: -`abra app run app -- backup --host snapshots` +`abra app run app -- backup --host snapshots` Show all files inside the latest snapshot (can be very verbose): -`abra app run app -- backup ls` +`abra app run app -- backup ls` Show specific files inside a selected snapshot: -`abra app run app -- backup ls --snapshot --path /var/lib/docker/volumes/` +`abra app run app -- backup ls --snapshot --path /var/lib/docker/volumes/` Download files from a snapshot: ``` -filename=$(abra app run app -- backup download --snapshot --path ) -abra app cp app:$filename . +filename=$(abra app run app -- backup download --snapshot --path ) +abra app cp app:$filename . ``` ## Run restic ``` -abra app run app bash +abra app run app bash export AWS_SECRET_ACCESS_KEY=$(cat $AWS_SECRET_ACCESS_KEY_FILE) export RESTIC_PASSWORD=$(cat $RESTIC_PASSWORD_FILE) restic snapshots diff --git a/abra.sh b/abra.sh index d806fdb..29c8f69 100644 --- a/abra.sh +++ b/abra.sh @@ -1,3 +1,11 @@ export ENTRYPOINT_VERSION=v1 export BACKUPBOT_VERSION=v1 export SSH_CONFIG_VERSION=v1 + +run_cron () { + schedule="$(crontab -l | tr -s " " | cut -d ' ' -f-5)" + rm -f /tmp/backup.log + echo "* * * * * $(crontab -l | tr -s " " | cut -d ' ' -f6-)" | crontab - + while [ ! -f /tmp/backup.log ]; do sleep 1; done + echo "$schedule $(crontab -l | tr -s " " | cut -d ' ' -f6-)" | crontab - +} diff --git a/entrypoint.sh b/entrypoint.sh index 2f9c708..30bbf73 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -2,7 +2,7 @@ set -e -o pipefail -apk add --upgrade --no-cache restic bash python3 py3-pip py3-click py3-docker-py py3-json-logger +apk add --upgrade --no-cache restic bash python3 py3-pip py3-click py3-docker-py py3-json-logger curl # Todo use requirements file with specific versions pip install --break-system-packages resticpy==1.0.2 @@ -14,7 +14,23 @@ fi cron_schedule="${CRON_SCHEDULE:?CRON_SCHEDULE not set}" -echo "$cron_schedule backup --machine-logs create" | crontab - +if [ -n "$PUSH_URL_START" ] +then + push_start_notification="curl -s '$PUSH_URL_START' &&" +fi + + +if [ -n "$PUSH_URL_SUCCESS" ] +then + push_success_notification=" 2>&1 | tee /tmp/backup.log && grep -q 'backup finished' /tmp/backup.log && curl -s '$PUSH_URL_SUCCESS'" +fi + +if [ -n "$PUSH_URL_FAIL" ] +then + push_fail_notification="|| curl -s '$PUSH_URL_FAIL'" +fi + +echo "$cron_schedule $push_start_notification backup --machine-logs create $push_success_notification $push_fail_notification" | crontab - crontab -l crond -f -d8 -L /dev/stdout