#!/bin/bash # services/gaming-backup.sh — Frequent gaming-saves backup (no service downtime). # Part of the modular post-install system (sourced by setup.sh). # # Can also be run standalone on any machine: # sudo bash gaming-backup.sh # (Docker must already be installed when run standalone) # # Backs up the things you can't re-download — progress, saved games, user data: # • Minecraft worlds / player data (every /data instance under $DOCKER_DIR) # • Emulator saves & save states ($GAME_STORAGE_DIR/saves) [gaming box] # • Emulator BIOS / firmware ($GAME_STORAGE_DIR/bios) [gaming box] # • RetroArch shaders & overlays ($GAME_STORAGE_DIR/retroarch) [gaming box] # • ES-DE scraped artwork ($GAME_STORAGE_DIR/media) [gaming box] # • Steam user data & game saves ($GAME_STORAGE_DIR/steam) [gaming box] # • Wolf state (/etc/wolf — config + profile_data) [gaming box] # # Unlike the 'backup' service, nothing is stopped — Minecraft worlds are flushed # to disk (save-all) and snapshotted live. Run this hourly or every few hours for # frequent save protection; use 'backup' nightly for full service recovery. # # It does NOT back up ROMs or Steam game installs — those are re-downloadable. # # Safe to re-run: it reconnects to an existing repository and refreshes the # config, policies, worker script and timer. # ── Standalone bootstrap ────────────────────────────────────────────────────── # Detected when the script is executed directly rather than sourced by setup.sh. # Sets up helpers and globals, then defers execution until after the function # definition at the bottom of this file. if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then [[ "$(id -u)" == "0" ]] || { echo "Run with sudo: sudo bash $0"; exit 1; } _SELF_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" _COMMON="$_SELF_DIR/../lib/common.sh" if [[ -f "$_COMMON" ]]; then # Full repo present — use the real helpers (picks up ~/docker/.config too) # shellcheck source=../lib/common.sh source "$_COMMON" else # One-off copy — inline minimal stubs so the script works without the repo log_info() { echo -e "\033[0;34m[INFO]\033[0m $*"; } log_success() { echo -e "\033[0;32m[OK]\033[0m $*"; } log_warning() { echo -e "\033[1;33m[WARN]\033[0m $*"; } log_error() { echo -e "\033[0;31m[ERROR]\033[0m $*" >&2; } ensure_docker_dir_ownership() { chown -R "$ACTUAL_USER:$ACTUAL_USER" "$@" 2>/dev/null || true } # Match common.sh's eval-based pattern so local vars in install_* are set correctly prompt_text() { local _q="$1" _def="$2" _var="$3" _r [[ "${UNATTENDED:-false}" == "true" ]] && { eval "$_var='$_def'"; return; } read -r -p " $_q " _r eval "$_var='${_r:-$_def}'" } prompt_yn() { local _q="$1" _def="$2" _var="$3" _r [[ "${UNATTENDED:-false}" == "true" ]] && { eval "$_var='$_def'"; return; } read -r -p " $_q " _r eval "$_var='${_r:-$_def}'" } generate_password() { local _len="${1:-32}" tr -dc 'A-Za-z0-9' < /dev/urandom | head -c "$_len" } fi # Globals — ACTUAL_USER/ACTUAL_HOME must come before DOCKER_DIR # ($HOME under sudo is /root, not the real user's home) ACTUAL_USER="${ACTUAL_USER:-${SUDO_USER:-$USER}}" ACTUAL_HOME="$(getent passwd "$ACTUAL_USER" 2>/dev/null | cut -d: -f6 || echo "${HOME:-/root}")" DOCKER_DIR="${DOCKER_DIR:-$ACTUAL_HOME/docker}" DRY_RUN="${DRY_RUN:-false}" UNATTENDED="${UNATTENDED:-false}" SITE_TZ="${SITE_TZ:-$(cat /etc/timezone 2>/dev/null || echo UTC)}" SITE_DOMAIN="${SITE_DOMAIN:-example.com}" SITE_CADDY_NET="${SITE_CADDY_NET:-caddy_net}" CADDY_REMOTE_HOST="${CADDY_REMOTE_HOST:-}" register_service() { :; } # no-op — no wizard to register into _RUN_STANDALONE=1 fi # ───────────────────────────────────────────────────────────────────────────── register_service gaming-backup backup "Gaming saves backup (Minecraft worlds, emulator saves, Steam)" install_gaming-backup() { log_info "Setting up gaming saves backup (Kopia)..." # ── Repo-conventional paths ────────────────────────────────────────────── local BACKUP_DIR="$DOCKER_DIR/gaming-backup" local CONF_FILE="$BACKUP_DIR/backup.conf" # editable settings local WORKER="$BACKUP_DIR/backup_gaming.sh" # worker script local KOPIA_CONFIG="/etc/gaming-backup/repository.config" local CACHE_DIR="/var/cache/gaming-backup" local SVC_NAME="post-install-gaming-backup" local DEFAULT_REPO="$ACTUAL_HOME/backups/gaming-kopia" echo "" echo "╔═══════════════════════════════════════════════════════╗" echo "║ Gaming Backup Setup · Kopia ║" echo "║ Minecraft worlds · game saves · user data ║" echo "╚═══════════════════════════════════════════════════════╝" echo "" echo " Backs up progress / saves / user data — NOT ROMs or game installs." echo " Nothing is stopped: Minecraft worlds are flushed to disk then snapshotted." echo " Run frequently (hourly or every few hours) without disrupting gameplay." echo " Use the 'backup' service for full service recovery (nightly)." echo "" # ── DRY-RUN ────────────────────────────────────────────────────────────── if [ "$DRY_RUN" = true ]; then echo "[DRY-RUN] Would install Kopia from the official apt repository" echo "[DRY-RUN] Would create $BACKUP_DIR (owned by $ACTUAL_USER)" echo "[DRY-RUN] Would create/connect a Kopia repository at $DEFAULT_REPO" echo "[DRY-RUN] Would write config $CONF_FILE and worker $WORKER" echo "[DRY-RUN] Would install systemd service+timer $SVC_NAME (cron fallback)" echo "[DRY-RUN] Would optionally run the first backup" return 0 fi # ── 1. Ensure Kopia is installed ───────────────────────────────────────── if ! command -v kopia >/dev/null 2>&1; then log_info "Kopia not found — installing from the official apt repository..." if command -v apt-get >/dev/null 2>&1; then install -d -m 0755 /etc/apt/keyrings if curl -fsSL https://kopia.io/signing-key \ | gpg --dearmor --yes -o /etc/apt/keyrings/kopia-keyring.gpg; then echo "deb [signed-by=/etc/apt/keyrings/kopia-keyring.gpg] http://packages.kopia.io/apt/ stable main" \ > /etc/apt/sources.list.d/kopia.list apt-get update -y && apt-get install -y kopia fi fi fi if ! command -v kopia >/dev/null 2>&1; then log_error "Kopia is still not installed." echo " Install it manually, then re-run this service:" echo " https://kopia.io/docs/installation/" return 1 fi local KOPIA_BIN; KOPIA_BIN="$(command -v kopia)" log_success "Kopia: $("$KOPIA_BIN" --version 2>/dev/null | head -1)" mkdir -p "$BACKUP_DIR" || return 1 ensure_docker_dir_ownership "$BACKUP_DIR" # ── 2. What to back up ─────────────────────────────────────────────────── echo "" echo "═══════════════════════════════════════════════════════" echo " WHAT TO BACK UP" echo "═══════════════════════════════════════════════════════" echo "" local DEFAULT_MCBASE="$DOCKER_DIR" echo " Each Minecraft instance's world is backed up from its /data folder;" echo " all instances under this folder are detected automatically." echo " (type 'none' to exclude Minecraft)" local MC_BASE_DIR="" prompt_text " Folder containing Minecraft instance(s) [${DEFAULT_MCBASE}]:" "$DEFAULT_MCBASE" MC_BASE_DIR if [ "$MC_BASE_DIR" = none ]; then MC_BASE_DIR="" else MC_BASE_DIR="${MC_BASE_DIR/#\~/$ACTUAL_HOME}"; MC_BASE_DIR="${MC_BASE_DIR%/}" local _found=() d for d in "$MC_BASE_DIR"/*/; do [ -f "${d}Dockerfile" ] && grep -qs itzg "${d}Dockerfile" && [ -d "${d}data" ] \ && _found+=("$(basename "$d")") done if [ "${#_found[@]}" -gt 0 ]; then log_success " Detected Minecraft instance(s): ${_found[*]}" else log_warning " No instances detected yet under $MC_BASE_DIR — picked up once created." fi fi # ── Optional gaming-box sources ────────────────────────────────────────── echo "" echo " The following are only relevant on a gaming box (Wolf + emulators +" echo " Steam). On a plain homelab server you can leave them disabled." local DEFAULT_STORAGE="$ACTUAL_HOME/drives/games" local GAME_STORAGE_DIR="" prompt_text " Game storage dir (ROMs/Steam/saves live here) [${DEFAULT_STORAGE}]:" "$DEFAULT_STORAGE" GAME_STORAGE_DIR GAME_STORAGE_DIR="${GAME_STORAGE_DIR/#\~/$ACTUAL_HOME}" GAME_STORAGE_DIR="${GAME_STORAGE_DIR%/}" echo "" local _a="" prompt_yn " Back up emulator saves ($GAME_STORAGE_DIR/saves)? (y/N):" "n" _a local BACKUP_SAVES; BACKUP_SAVES=$([[ "$_a" =~ ^[Yy]$ ]] && echo yes || echo no) prompt_yn " Back up emulator BIOS/firmware ($GAME_STORAGE_DIR/bios)? (y/N):" "n" _a local BACKUP_BIOS; BACKUP_BIOS=$([[ "$_a" =~ ^[Yy]$ ]] && echo yes || echo no) prompt_yn " Back up RetroArch shaders & overlays ($GAME_STORAGE_DIR/retroarch)? (y/N):" "n" _a local BACKUP_RA_SHADERS; BACKUP_RA_SHADERS=$([[ "$_a" =~ ^[Yy]$ ]] && echo yes || echo no) prompt_yn " Back up Steam user data/saves (game installs excluded)? (y/N):" "n" _a local BACKUP_STEAM; BACKUP_STEAM=$([[ "$_a" =~ ^[Yy]$ ]] && echo yes || echo no) prompt_yn " Back up ES-DE scraped artwork ($GAME_STORAGE_DIR/media)? (y/N):" "n" _a local BACKUP_MEDIA; BACKUP_MEDIA=$([[ "$_a" =~ ^[Yy]$ ]] && echo yes || echo no) echo "" echo " /etc/wolf includes pairing/config AND profile_data — where Wolf stores" echo " every app's home dir (ES-DE settings, controller mappings, RetroArch" echo " saves & save states, standalone-emulator saves)." prompt_yn " Back up Wolf state (/etc/wolf)? (y/N):" "n" _a local BACKUP_WOLF; BACKUP_WOLF=$([[ "$_a" =~ ^[Yy]$ ]] && echo yes || echo no) local WOLF_STATE_DIR="/etc/wolf" # ── 3. Repository location ──────────────────────────────────────────────── echo "" echo "═══════════════════════════════════════════════════════" echo " BACKUP REPOSITORY (local)" echo "═══════════════════════════════════════════════════════" echo "" echo " Backups are stored in a local Kopia repository. You can mirror it to" echo " another computer or the cloud later (see backup.conf, REMOTE_* lines)." echo " Put it on a DIFFERENT drive from your data if you can." echo "" local REPO_DIR="" prompt_text " Repository path [${DEFAULT_REPO}]:" "$DEFAULT_REPO" REPO_DIR REPO_DIR="${REPO_DIR/#\~/$ACTUAL_HOME}" REPO_DIR="${REPO_DIR%/}" echo "" echo " The repository is encrypted. A strong password is generated and stored" echo " in backup.conf (root-only). KEEP A COPY — without it backups cannot be" echo " restored, even by you." echo "" local KOPIA_PASSWORD="" if [ "$UNATTENDED" = true ]; then echo " [auto] Generating a random repository password." else read -rsp " Repository password [Enter = auto-generate]: " KOPIA_PASSWORD; echo fi if [ -z "$KOPIA_PASSWORD" ]; then KOPIA_PASSWORD="$(generate_password 32)" log_info " Generated a random repository password (saved in backup.conf)." fi # ── 4. Retention + schedule ─────────────────────────────────────────────── echo "" echo "═══════════════════════════════════════════════════════" echo " SCHEDULE & RETENTION" echo "═══════════════════════════════════════════════════════" echo "" echo " 1) Daily at 03:00" echo " 2) Every 6 hours" echo " 3) Hourly (recommended for active gaming)" echo " 4) Custom (systemd OnCalendar)" echo "" local _sch="" prompt_text " How often? [3]:" "3" _sch local ONCALENDAR SCHED_LABEL case "${_sch:-3}" in 1) ONCALENDAR="*-*-* 03:00:00"; SCHED_LABEL="daily at 03:00" ;; 2) ONCALENDAR="*-*-* 00,06,12,18:00:00"; SCHED_LABEL="every 6 hours" ;; 4) prompt_text " OnCalendar expression:" "hourly" ONCALENDAR; SCHED_LABEL="$ONCALENDAR" ;; *) ONCALENDAR="hourly"; SCHED_LABEL="hourly" ;; esac echo "" local KEEP_LATEST="" prompt_text " How many recent snapshots to keep (latest)? [24]:" "24" KEEP_LATEST local KEEP_DAILY=7 KEEP_WEEKLY=4 KEEP_MONTHLY=6 # ── Notifications (ntfy) ───────────────────────────────────────────────── echo "" echo "═══════════════════════════════════════════════════════" echo " NOTIFICATIONS (optional)" echo "═══════════════════════════════════════════════════════" echo "" echo " Receive a push notification after every backup (and on failures)." echo " Uses ntfy — free and self-hostable. Create a topic at https://ntfy.sh" echo "" local NTFY_URL="" NTFY_TOKEN="" prompt_text " ntfy topic URL (blank to skip):" "" NTFY_URL if [ -n "$NTFY_URL" ]; then prompt_text " ntfy access token (blank if public/no auth):" "" NTFY_TOKEN fi # ── 5. Write backup.conf ────────────────────────────────────────────────── log_info "Writing $CONF_FILE ..." tee "$CONF_FILE" >/dev/null << CONFEOF # ── gaming-backup config (read by gaming-backup.sh) ────────────────────────── # Generated on $(date '+%F %T'). Safe to hand-edit. KOPIA="$KOPIA_BIN" KOPIA_CONFIG="$KOPIA_CONFIG" KOPIA_CACHE_DIR="$CACHE_DIR" # Repository encryption password — KEEP A COPY somewhere safe. KOPIA_PASSWORD='$KOPIA_PASSWORD' # ── Sources (progress / saves / user data only) ────────────────────────────── # MC_BASE_DIR holds Minecraft instances; every /data with an itzg Dockerfile # is snapshotted automatically (covers multi-server setups). MC_BASE_DIR="$MC_BASE_DIR" GAME_STORAGE_DIR="$GAME_STORAGE_DIR" WOLF_STATE_DIR="$WOLF_STATE_DIR" BACKUP_SAVES="$BACKUP_SAVES" # \$GAME_STORAGE_DIR/saves BACKUP_BIOS="$BACKUP_BIOS" # \$GAME_STORAGE_DIR/bios (emulator BIOS/firmware — user-provided) BACKUP_RA_SHADERS="$BACKUP_RA_SHADERS" # \$GAME_STORAGE_DIR/retroarch/{shaders,overlays} (cores excluded — re-downloadable) BACKUP_STEAM="$BACKUP_STEAM" # \$GAME_STORAGE_DIR/steam (game installs excluded by policy) BACKUP_MEDIA="$BACKUP_MEDIA" # \$GAME_STORAGE_DIR/media (ES-DE scraped artwork) BACKUP_WOLF="$BACKUP_WOLF" # /etc/wolf — config + profile_data # ── Optional offsite mirror ────────────────────────────────────────────────── # Mirror the WHOLE repository to another computer or the cloud after each run. # Leave REMOTE_TYPE=none to stay local-only. # # SFTP: REMOTE_TYPE="sftp" REMOTE_ARGS="--host H --username U --path /srv/..." # B2: REMOTE_TYPE="b2" REMOTE_ARGS="--bucket B --key-id K --key A" # S3: REMOTE_TYPE="s3" REMOTE_ARGS="--bucket B --endpoint E --access-key K --secret-access-key S" # rclone: REMOTE_TYPE="rclone" REMOTE_ARGS="--remote-path myremote:gaming-kopia" # REMOTE_TYPE="none" REMOTE_ARGS="" # ── Notifications (ntfy) ───────────────────────────────────────────────────── # Set NTFY_URL to receive backup success/failure alerts. # Leave blank to disable. NTFY_TOKEN is optional (for private topics). NTFY_URL="$NTFY_URL" NTFY_TOKEN="$NTFY_TOKEN" CONFEOF chown root:root "$CONF_FILE" 2>/dev/null || true chmod 600 "$CONF_FILE" log_success "backup.conf written (chmod 600 — contains the repo password)" # ── 6. Create / connect the repository, set policies ───────────────────── log_info "Preparing repository at $REPO_DIR ..." mkdir -p "$REPO_DIR" "$CACHE_DIR" "$(dirname "$KOPIA_CONFIG")" kp() { env KOPIA_PASSWORD="$KOPIA_PASSWORD" "$KOPIA_BIN" --config-file="$KOPIA_CONFIG" "$@"; } if kp repository status >/dev/null 2>&1; then log_success "Already connected to a repository." elif test -e "$REPO_DIR/kopia.repository.f"; then log_info "Existing repository found — connecting..." kp repository connect filesystem --path="$REPO_DIR" --cache-directory="$CACHE_DIR" \ || { log_error "Failed to connect to existing repository."; return 1; } log_success "Connected to existing repository." else log_info "Creating new repository..." kp repository create filesystem --path="$REPO_DIR" --cache-directory="$CACHE_DIR" \ || { log_error "Failed to create repository."; return 1; } log_success "Repository created." fi log_info "Applying global policy (zstd compression + retention)..." kp policy set --global --compression=zstd >/dev/null kp policy set --global \ --keep-latest="$KEEP_LATEST" \ --keep-daily="$KEEP_DAILY" \ --keep-weekly="$KEEP_WEEKLY" \ --keep-monthly="$KEEP_MONTHLY" \ --keep-annual=0 --keep-hourly=0 >/dev/null log_success "Retention: keep latest $KEEP_LATEST, $KEEP_DAILY daily, $KEEP_WEEKLY weekly, $KEEP_MONTHLY monthly" if [ "$BACKUP_STEAM" = yes ]; then log_info "Setting Steam ignore rules (excluding game installs, keeping saves)..." kp policy set "$GAME_STORAGE_DIR/steam" \ --add-ignore='**/steamapps/common' \ --add-ignore='**/steamapps/downloading' \ --add-ignore='**/steamapps/shadercache' \ --add-ignore='**/steamapps/temp' \ --add-ignore='**/steamapps/workshop' \ --add-ignore='**/depotcache' >/dev/null 2>&1 \ || log_warning "Could not pre-set Steam ignore policy (applies on first snapshot)." fi # ── 7. Install the worker script ───────────────────────────────────────── log_info "Installing worker $WORKER ..." cp "${HERE:-}/extras/backup_gaming.sh" "$WORKER" chmod +x "$WORKER" chown root:root "$WORKER" 2>/dev/null || true log_success "backup_gaming.sh installed" # ── Copy the interactive restore script ─────────────────────────────────── local RESTORE_SRC="${HERE:-}/extras/restore_kopia.sh" local RESTORE_DEST="$BACKUP_DIR/restore_gaming.sh" if [ -f "$RESTORE_SRC" ]; then cp "$RESTORE_SRC" "$RESTORE_DEST" chmod +x "$RESTORE_DEST" chown root:root "$RESTORE_DEST" 2>/dev/null || true log_success "restore_kopia.sh installed" else log_warning "extras/restore_kopia.sh not found — restore script not installed" fi # ── Install test script ─────────────────────────────────────────────────── local TEST_SCRIPT="$BACKUP_DIR/test_backup.sh" local TEST_SRC="${HERE:-}/extras/test_backup.sh" if [ -f "$TEST_SRC" ]; then cp "$TEST_SRC" "$TEST_SCRIPT" chmod +x "$TEST_SCRIPT" chown root:root "$TEST_SCRIPT" 2>/dev/null || true log_success "test_backup.sh installed" else log_warning "extras/test_backup.sh not found — test script not installed" fi # ── 8. Install systemd timer (fallback: cron) ──────────────────────────── local AUTORUN="" if command -v systemctl >/dev/null 2>&1 && [ -d /run/systemd/system ]; then log_info "Installing systemd service + timer ($SCHED_LABEL)..." tee "/etc/systemd/system/${SVC_NAME}.service" >/dev/null << UNITEOF [Unit] Description=Post-install gaming backup (Minecraft world + game saves via Kopia) After=docker.service network-online.target Wants=docker.service [Service] Type=oneshot ExecStart=/bin/bash $WORKER run UNITEOF tee "/etc/systemd/system/${SVC_NAME}.timer" >/dev/null << UNITEOF [Unit] Description=Schedule gaming backup ($SCHED_LABEL) [Timer] OnCalendar=$ONCALENDAR Persistent=true RandomizedDelaySec=300 [Install] WantedBy=timers.target UNITEOF systemctl daemon-reload systemctl enable --now "${SVC_NAME}.timer" log_success "Timer enabled: $SCHED_LABEL" AUTORUN="systemctl list-timers ${SVC_NAME}.timer" else log_warning "systemd not detected — installing a cron job instead." local CRON case "${_sch:-3}" in 1) CRON="0 3 * * *" ;; 2) CRON="0 0,6,12,18 * * *" ;; *) CRON="0 * * * *" ;; esac echo "$CRON root /bin/bash $WORKER run >> /var/log/${SVC_NAME}.log 2>&1" \ > "/etc/cron.d/${SVC_NAME}" log_success "Cron job installed: $CRON" AUTORUN="cat /etc/cron.d/${SVC_NAME}" fi # ── 9. First backup now? ───────────────────────────────────────────────── echo "" local _now="" prompt_yn " Run the first gaming backup now? (Y/n):" "y" _now if [[ ! "$_now" =~ ^[Nn]$ ]]; then /bin/bash "$WORKER" run || log_warning "First backup reported warnings — check the output above." fi # ── Summary ────────────────────────────────────────────────────────────── echo "" echo "═══════════════════════════════════════════════════════" echo " GAMING BACKUP CONFIGURED" echo "═══════════════════════════════════════════════════════" echo "" echo " Repository : $REPO_DIR (encrypted, dedup + zstd)" echo " Schedule : $SCHED_LABEL" echo " Config : $CONF_FILE" echo " Worker : $WORKER" echo " Backing up :" [ -n "$MC_BASE_DIR" ] && echo " • Minecraft worlds $MC_BASE_DIR/*/data (all instances)" [ "$BACKUP_SAVES" = yes ] && echo " • Emulator saves $GAME_STORAGE_DIR/saves" [ "$BACKUP_BIOS" = yes ] && echo " • Emulator BIOS $GAME_STORAGE_DIR/bios" [ "$BACKUP_RA_SHADERS" = yes ] && echo " • RA shaders/overlays $GAME_STORAGE_DIR/retroarch/{shaders,overlays}" [ "$BACKUP_STEAM" = yes ] && echo " • Steam user data $GAME_STORAGE_DIR/steam (game installs excluded)" [ "$BACKUP_MEDIA" = yes ] && echo " • ES-DE scraped art $GAME_STORAGE_DIR/media" [ "$BACKUP_WOLF" = yes ] && echo " • Wolf state $WOLF_STATE_DIR (config + profile_data)" echo " NOT backed up: ROMs, Steam game installs (re-downloadable)." echo "" echo " Commands:" echo " sudo $WORKER back up now" echo " sudo $WORKER snapshots list snapshots" echo " sudo $RESTORE_DEST interactive restore" echo " sudo $RESTORE_DEST --list list all snapshot sources" echo "" echo " Backup test (restore latest, compare, restore-back):" echo " sudo $TEST_SCRIPT test most recent backup" echo " sudo $TEST_SCRIPT --list list testable sources" echo " sudo $TEST_SCRIPT test a specific source" [ -n "${NTFY_URL:-}" ] && echo "" && echo " Notifications: $NTFY_URL" echo "" echo " $AUTORUN" echo "" echo " Tip: also install the 'backup' service for nightly full-service recovery." echo "" log_warning "Save your repository password (in backup.conf) somewhere safe —" log_warning "without it the encrypted backups cannot be restored." echo "" log_success "Gaming backup configured." } # Run immediately when executed directly (deferred until after function definition) [[ "${_RUN_STANDALONE:-0}" == 1 ]] && install_gaming-backup