diff --git a/remote-backup/Dockerfile b/remote-backup/Dockerfile index 094f41c..61d1cc8 100644 --- a/remote-backup/Dockerfile +++ b/remote-backup/Dockerfile @@ -5,13 +5,13 @@ FROM $BUILD_FROM ENV LANG C.UTF-8 # Setup base -RUN apk add --no-cache jq openssh-client zip +RUN apk add --no-cache jq openssh-client zip sshpass rsync # Hass.io CLI ARG BUILD_ARCH ARG CLI_VERSION RUN apk add --no-cache curl \ - && curl -Lso /usr/bin/hassio https://github.com/home-assistant/hassio-cli/releases/download/1.2.1/hassio_${BUILD_ARCH} \ + && curl -Lso /usr/bin/hassio https://github.com/home-assistant/hassio-cli/releases/download/2.2.0/hassio_${BUILD_ARCH} \ && chmod a+x /usr/bin/hassio # Copy data diff --git a/remote-backup/config.json b/remote-backup/config.json index 858b38f..b11bff7 100644 --- a/remote-backup/config.json +++ b/remote-backup/config.json @@ -2,30 +2,42 @@ "name": "Remote Backup", "version": "dev", "slug": "remote_backup", - "description": "Exploit snapshots and SCP to create remote backups to specified server", + "description": "Exploit snapshots and SCP/rsync to create remote backups to specified server", "url": "https://github.com/overkill32/hassio-remote-backup", "startup": "once", "boot": "manual", "hassio_api": true, "hassio_role": "backup", - "map": ["backup:rw"], + "map": ["config", "addons", "share", "ssl", "backup:rw"], "arch": ["armhf", "armv7", "aarch64", "amd64", "i386"], "options": { + "ssh_enabled": true, "ssh_host": "", "ssh_port": 22, "ssh_user": "", "ssh_key": [], "remote_directory": "", "zip_password": "", - "keep_local_backup": "" + "keep_local_backup": "", + "rsync_enabled": false, + "rsync_host": "", + "rsync_rootfolder": "hassio-sync", + "rsync_user": "", + "rsync_password": "" }, "schema": { + "ssh_enabled": "bool", "ssh_host": "str", "ssh_port": "int", "ssh_user": "str", "ssh_key": ["str"], "remote_directory": "str", "zip_password": "str", - "keep_local_backup": "match(^(all|[+]?\\d*)$)" + "keep_local_backup": "match(^(all|[+]?\\d*)$)", + "rsync_enabled": "bool", + "rsync_host": "str", + "rsync_rootfolder": "str", + "rsync_user": "str", + "rsync_password": "str" } } diff --git a/remote-backup/run.sh b/remote-backup/run.sh index dbd25b4..462317a 100755 --- a/remote-backup/run.sh +++ b/remote-backup/run.sh @@ -4,6 +4,7 @@ set -e CONFIG_PATH=/data/options.json # parse inputs from options +SSH_ENABLED=$(jq --raw-output ".ssh_enabled" $CONFIG_PATH) SSH_HOST=$(jq --raw-output ".ssh_host" $CONFIG_PATH) SSH_PORT=$(jq --raw-output ".ssh_port" $CONFIG_PATH) SSH_USER=$(jq --raw-output ".ssh_user" $CONFIG_PATH) @@ -12,41 +13,51 @@ REMOTE_DIRECTORY=$(jq --raw-output ".remote_directory" $CONFIG_PATH) ZIP_PASSWORD=$(jq --raw-output '.zip_password' $CONFIG_PATH) KEEP_LOCAL_BACKUP=$(jq --raw-output '.keep_local_backup' $CONFIG_PATH) +RSYNC_ENABLED=$(jq --raw-output ".rsync_enabled" $CONFIG_PATH) +RSYNC_HOST=$(jq --raw-output ".rsync_host" $CONFIG_PATH) +RSYNC_ROOTFOLDER=$(jq --raw-output ".rsync_rootfolder" $CONFIG_PATH) +RSYNC_USER=$(jq --raw-output ".rsync_user" $CONFIG_PATH) +RSYNC_PASSWORD=$(jq --raw-output ".rsync_password" $CONFIG_PATH) + # create variables SSH_ID="${HOME}/.ssh/id" function add-ssh-key { - echo "Adding SSH key" - mkdir -p ~/.ssh - ( - echo "Host remote" - echo " IdentityFile ${HOME}/.ssh/id" - echo " HostName ${SSH_HOST}" - echo " User ${SSH_USER}" - echo " Port ${SSH_PORT}" - echo " StrictHostKeyChecking no" - ) > "${HOME}/.ssh/config" - - while read -r line; do - echo "$line" >> ${HOME}/.ssh/id - done <<< "$SSH_KEY" - - chmod 600 "${HOME}/.ssh/config" - chmod 600 "${HOME}/.ssh/id" + + if [ "$SSH_ENABLED" = true ] ; then + echo "Adding SSH key" + mkdir -p ~/.ssh + ( + echo "Host remote" + echo " IdentityFile ${HOME}/.ssh/id" + echo " HostName ${SSH_HOST}" + echo " User ${SSH_USER}" + echo " Port ${SSH_PORT}" + echo " StrictHostKeyChecking no" + ) > "${HOME}/.ssh/config" + + while read -r line; do + echo "$line" >> ${HOME}/.ssh/id + done <<< "$SSH_KEY" + + chmod 600 "${HOME}/.ssh/config" + chmod 600 "${HOME}/.ssh/id" + fi } function copy-backup-to-remote { - cd /backup/ - if [[ -z $ZIP_PASSWORD ]]; then - echo "Copying ${slug}.tar to ${REMOTE_DIRECTORY} on ${SSH_HOST} using SCP" - scp -F "${HOME}/.ssh/config" "${slug}.tar" remote:"${REMOTE_DIRECTORY}" - else - echo "Copying password-protected ${slug}.zip to ${REMOTE_DIRECTORY} on ${SSH_HOST} using SCP" - zip -P "$ZIP_PASSWORD" "${slug}.zip" "${slug}".tar - scp -F "${HOME}/.ssh/config" "${slug}.zip" remote:"${REMOTE_DIRECTORY}" && rm "${slug}.zip" + if [ "$SSH_ENABLED" = true ] ; then + cd /backup/ + if [[ -z $ZIP_PASSWORD ]]; then + echo "Copying ${slug}.tar to ${REMOTE_DIRECTORY} on ${SSH_HOST} using SCP" + scp -F "${HOME}/.ssh/config" "${slug}.tar" remote:"${REMOTE_DIRECTORY}" + else + echo "Copying password-protected ${slug}.zip to ${REMOTE_DIRECTORY} on ${SSH_HOST} using SCP" + zip -P "$ZIP_PASSWORD" "${slug}.zip" "${slug}".tar + scp -F "${HOME}/.ssh/config" "${slug}.zip" remote:"${REMOTE_DIRECTORY}" && rm "${slug}.zip" + fi fi - } function delete-local-backup { @@ -57,16 +68,16 @@ function delete-local-backup { : elif [[ -z ${KEEP_LOCAL_BACKUP} ]]; then echo "Deleting local backup: ${slug}" - hassio snapshots remove -name "${slug}" + hassio snapshots remove "${slug}" else - last_date_to_keep=$(hassio snapshots list | jq .data.snapshots[].date | sort -r | \ + last_date_to_keep=$(hassio snapshots list --raw-json | jq .data.snapshots[].date | sort -r | \ head -n "${KEEP_LOCAL_BACKUP}" | tail -n 1 | xargs date -D "%Y-%m-%dT%T" +%s --date ) - hassio snapshots list | jq -c .data.snapshots[] | while read backup; do + hassio snapshots list --raw-json | jq -c .data.snapshots[] | while read backup; do if [[ $(echo ${backup} | jq .date | xargs date -D "%Y-%m-%dT%T" +%s --date ) -lt ${last_date_to_keep} ]]; then echo "Deleting local backup: $(echo ${backup} | jq -r .slug)" - hassio snapshots remove -name "$(echo ${backup} | jq -r .slug)" + hassio snapshots remove "$(echo ${backup} | jq -r .slug)" fi done @@ -76,14 +87,39 @@ function delete-local-backup { function create-local-backup { name="Automated backup $(date +'%Y-%m-%d %H:%M')" echo "Creating local backup: \"${name}\"" - slug=$(hassio snapshots new --options name="${name}" | jq --raw-output '.data.slug') + slug=$(hassio snapshots new --raw-json --name="${name}" | jq --raw-output '.data.slug') echo "Backup created: ${slug}" } +function rsync_folders { + + if [ "$RSYNC_ENABLED" = true ] ; then + rsyncurl="$RSYNC_USER@$RSYNC_HOST::$RSYNC_ROOTFOLDER" + echo "[Info] trying to rsync hassio folders to $rsyncurl" + echo "" + echo "[Info] /config" + sshpass -p $RSYNC_PASSWORD rsync -av --exclude '*.db-shm' --exclude '*.db-wal' /config/ $rsyncurl/config/ --delete + echo "" + echo "[Info] /addons" + sshpass -p $RSYNC_PASSWORD rsync -av /addons/ $rsyncurl/addons/ --delete + echo "" + echo "[Info] /backup" + sshpass -p $RSYNC_PASSWORD rsync -av /backup/ $rsyncurl/backup/ --delete + echo "" + echo "[Info] /share" + sshpass -p $RSYNC_PASSWORD rsync -av /share/ $rsyncurl/share/ --delete + echo "" + echo "[Info] /ssl" + sshpass -p $RSYNC_PASSWORD rsync -av /ssl/ $rsyncurl/ssl/ --delete + echo "[Info] Finished rsync" + fi +} + add-ssh-key create-local-backup copy-backup-to-remote +rsync_folders delete-local-backup echo "Backup process done!"