#!/usr/bin/env bash # # Guided setup for the MonitorSpider Linux backup (linux-files-mysql.sh). # # curl -fsSO https://monitorspider.com/backup-kits/setup.sh # sudo bash setup.sh # # Paste your monitor's ping URL when asked (shown on the monitor's page at # monitorspider.com) and answer a few questions. It will: # - fetch the monitor's settings and propose a matching cron schedule # - detect MySQL/PostgreSQL and ask what to back up and where to upload it # - install the backup script to /usr/local/sbin/monitorspider-backup.sh # - write the config to /etc/monitorspider-backup.conf (chmod 600) # - create the cron entry (/etc/cron.d/monitorspider-backup) # - offer to run the first backup right away # # Re-running is safe: existing config values are offered as defaults. # From https://monitorspider.com/backup-kits/ — MIT licensed, plain text: read it first. set -euo pipefail CONF="${MSPIDER_CONF:-/etc/monitorspider-backup.conf}" DEST="${MSPIDER_DEST:-/usr/local/sbin/monitorspider-backup.sh}" CRON_FILE="${MSPIDER_CRON:-/etc/cron.d/monitorspider-backup}" if [ "${MSPIDER_SETUP_TEST:-}" != "1" ] && [ "$(id -u)" -ne 0 ]; then echo "Please run as root: sudo bash setup.sh"; exit 1 fi ask() { # $1 prompt, $2 default local a read -rp "$1${2:+ [$2]}: " a echo "${a:-${2:-}}" } echo echo "=== MonitorSpider backup setup ===" echo # --- 1. monitor ------------------------------------------------------------- echo "Step 1 of 4 — your MonitorSpider monitor" echo "In the dashboard: Monitors -> your Backup (push) monitor -> copy the ping URL." PING_URL="${1:-}" MON_ID=""; MON_TOKEN="" while true; do [ -n "$PING_URL" ] || read -rp "Paste the ping URL: " PING_URL if [[ "$PING_URL" =~ id=([0-9]+).*token=([0-9a-fA-F]+) ]]; then MON_ID="${BASH_REMATCH[1]}"; MON_TOKEN="${BASH_REMATCH[2]}"; break fi echo "That does not look like a ping URL (expected ...backup-ping?id=&token=)." PING_URL="" done BASE="${PING_URL%%/srv/*}" MON_JSON="$(curl -fsS --max-time 20 "$BASE/srv/backup-config?id=$MON_ID&token=$MON_TOKEN")" || { echo "Could not fetch the monitor's settings — check the URL is complete and the monitor is enabled."; exit 1; } MON_NAME="$(sed -n 's/.*"name":"\([^"]*\)".*/\1/p' <<<"$MON_JSON")" MON_INTERVAL="$(sed -n 's/.*"expected_interval_hours":\([0-9.]*\).*/\1/p' <<<"$MON_JSON")" MON_GRACE="$(sed -n 's/.*"grace_hours":\([0-9.]*\).*/\1/p' <<<"$MON_JSON")" echo "Connected: monitor '$MON_NAME' expects a backup every ${MON_INTERVAL:-168}h (+${MON_GRACE:-6}h grace)." echo # --- 2. questions -> config -------------------------------------------------- echo "Step 2 of 4 — what to back up, where to send it" # shellcheck disable=SC1090 [ -f "$CONF" ] && { echo "Found existing $CONF — its values are offered as defaults."; . "$CONF"; } DIRS_DEFAULT="${BACKUP_DIRS[*]:-/etc /var/www}" DIRS_RAW="$(ask 'Folders to back up (space-separated)' "$DIRS_DEFAULT")" read -ra NEW_DIRS <<<"$DIRS_RAW" for d in "${NEW_DIRS[@]}"; do [ -e "$d" ] || echo " note: $d does not exist right now"; done MYSQL_DEFAULT="no"; command -v mysqldump >/dev/null && pgrep -x mysqld >/dev/null 2>&1 && MYSQL_DEFAULT="yes" NEW_MYSQL="$(ask 'Dump MySQL/MariaDB (all databases)? yes/no' "${MYSQL_DUMP:-$MYSQL_DEFAULT}")" PG_DEFAULT="no"; command -v pg_dumpall >/dev/null && pgrep -x postgres >/dev/null 2>&1 && PG_DEFAULT="yes" NEW_PG="$(ask 'Dump PostgreSQL (pg_dumpall)? yes/no' "${PGSQL_DUMP:-$PG_DEFAULT}")" echo echo "Where should the backups be uploaded? Two options:" echo " 1) rclone — any cloud/SFTP/FTP remote you have configured (rclone config)" echo " 2) curl — a plain FTP/SFTP URL like ftp://user:pass@host/folder/" NEW_RCLONE="${RCLONE_REMOTE:-}"; NEW_CURL="${CURL_UPLOAD_URL:-}" if command -v rclone >/dev/null && [ -n "$(rclone listremotes 2>/dev/null)" ]; then echo "rclone remotes found:"; rclone listremotes | sed 's/^/ /' NEW_RCLONE="$(ask 'rclone destination (remote:folder), or Enter to use a curl URL instead' "$NEW_RCLONE")" fi if [ -z "$NEW_RCLONE" ]; then while [ -z "$NEW_CURL" ]; do NEW_CURL="$(ask 'Upload URL (ftp://user:pass@host/folder/ — note the trailing slash)' "$NEW_CURL")"; done fi echo NEW_PASS="${ENCRYPT_PASSPHRASE:-}" if [ -n "$NEW_PASS" ]; then echo "Keeping the existing encryption passphrase from $CONF." else NEW_PASS="$(ask 'Encryption passphrase (GPG AES-256) — enter your own, or press Enter to generate one')" if [ -z "$NEW_PASS" ]; then NEW_PASS="$(tr -dc 'A-Za-z0-9' "$CONF" chmod 600 "$CONF" echo "Wrote $CONF (readable by root only — it contains credentials)" MISSING="" for c in tar gzip curl; do command -v "$c" >/dev/null || MISSING="$MISSING $c"; done [ -n "$NEW_PASS" ] && ! command -v gpg >/dev/null && MISSING="$MISSING gnupg" [ "$NEW_MYSQL" = "yes" ] && ! command -v mysqldump >/dev/null && MISSING="$MISSING mysql-client" [ -n "$MISSING" ] && { echo "MISSING tools:$MISSING — install them (apt/yum) and re-run setup."; exit 1; } echo "All required tools present." # --- 4. cron ------------------------------------------------------------------ echo echo "Step 4 of 4 — schedule it" RUN_TIME="$(ask 'Run at what time? (24h HH:MM)' '03:00')" HH="${RUN_TIME%%:*}"; MM="${RUN_TIME##*:}" if [ "${MON_INTERVAL%.*}" -le 24 ] 2>/dev/null; then echo "Your monitor expects a backup every ${MON_INTERVAL}h — scheduling DAILY at $RUN_TIME." CRON_SPEC="$MM $HH * * *" else DOW="$(ask 'Run on which day? (Sunday..Saturday)' 'Sunday')" CRON_SPEC="$MM $HH * * ${DOW:0:3}" echo "Scheduling WEEKLY on $DOW at $RUN_TIME (monitor window: ${MON_INTERVAL}h + ${MON_GRACE}h grace)." fi { echo "# MonitorSpider backup — written by setup.sh; monitor: $MON_NAME" echo "$CRON_SPEC root $DEST >/dev/null 2>&1" } > "$CRON_FILE" chmod 644 "$CRON_FILE" echo "Wrote $CRON_FILE" echo echo "Setup complete." echo " - Script: $DEST" echo " - Config: $CONF" echo " - Cron: $CRON_FILE ($CRON_SPEC)" echo " - Monitor: $MON_NAME — it will alert if a backup fails or stops arriving." echo RUN_NOW="$(ask 'Run the first backup now? It seeds the monitor and the size graph (y/N)' 'N')" if [[ "$RUN_NOW" =~ ^[yY] ]]; then bash "$DEST" && echo "First backup completed — the monitor page should be green with a size sample." \ || echo "First backup reported errors (see above) — the monitor received a FAIL ping, which is the system working." fi