Skip to content

Repository files, collaboration, releases and project activity.

archforge-external-status / scripts/restore.shmain
▤ scripts/restore.sh1702 bytes
25 lines · Select a line number for a permalink
1#!/usr/bin/env bash
2set -Eeuo pipefail
3umask 077
4[[ $EUID -eq 0 ]] || { echo 'Run with sudo.' >&2; exit 1; }
5[[ $# -eq 1 && -f "$1" ]] || { echo "Usage: sudo $0 /var/backups/archforge-status/backup-....tar.gz"; exit 1; }
6FILE=$(realpath -- "$1")
7[[ "$FILE" == /var/backups/archforge-status/backup-*.tar.gz ]] || { echo 'Backups must be from the managed backup directory' >&2; exit 1; }
8TMP=$(mktemp -d)
9trap 'rm -rf "$TMP"' EXIT
10# Reject unexpected entries, symlinks and paths before extracting as root.
11while IFS= read -r item; do case "$item" in ./|./status.db|./status.env|./msmtprc) ;; *) echo "Unsafe archive path: $item" >&2; exit 1;; esac; done < <(tar -tzf "$FILE")
12while IFS= read -r type; do [[ "$type" == '-' || "$type" == 'd' ]] || { echo 'Unsupported archive file type' >&2;exit 1;}; done < <(tar -tvzf "$FILE" | cut -c1)
13tar -xzf "$FILE" -C "$TMP" --no-same-owner --no-same-permissions
14[[ -s "$TMP/status.env" ]] || { echo 'Backup does not contain status.env'; exit 1; }
15echo 'This will replace the live database and configuration.'
16read -rp "Type RESTORE to continue: " OK
17[[ "$OK" == RESTORE ]] || exit 1
18systemctl stop archforge-status
19rm -f /var/lib/archforge-status/status.db-wal /var/lib/archforge-status/status.db-shm
20if [[ -f "$TMP/status.db" ]]; then install -o archforge-status -g archforge-status -m 600 "$TMP/status.db" /var/lib/archforge-status/status.db; fi
21install -o root -g archforge-status -m 640 "$TMP/status.env" /etc/archforge-status/status.env
22if [[ -f "$TMP/msmtprc" ]]; then install -o archforge-status -g archforge-status -m 600 "$TMP/msmtprc" /etc/archforge-status/msmtprc; fi
23systemctl start archforge-status
24systemctl --no-pager --full status archforge-status