diff options
| author | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-05-19 18:38:39 +0200 |
|---|---|---|
| committer | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-05-19 18:38:39 +0200 |
| commit | e8cf42f2f17151378574ee5b50f29904a1067bee (patch) | |
| tree | 86b4db80971ecf9818ad769bd8b7fa337d218731 /shield-backup | |
| parent | c3bfa44d1b6da88c184fc3312944cf47d1dfd7f2 (diff) | |
| download | bin-e8cf42f2f17151378574ee5b50f29904a1067bee.tar.gz bin-e8cf42f2f17151378574ee5b50f29904a1067bee.zip | |
Diffstat (limited to 'shield-backup')
| -rwxr-xr-x | shield-backup | 175 |
1 files changed, 126 insertions, 49 deletions
diff --git a/shield-backup b/shield-backup index ccaff5b..1c95a5d 100755 --- a/shield-backup +++ b/shield-backup @@ -2,7 +2,7 @@ set -euo pipefail export PATH="/usr/sbin:/sbin:/usr/bin:/bin:$PATH" -RCLONE_CONFIG="$HOME/.config/rclone/rclone.conf" + #################### CONFIG – EDIT THESE #################### # LUKS2 block device @@ -23,59 +23,141 @@ BACKUP_ITEMS=( # Machine identifier (destination subdir on the LUKS volume) MACHINE_DIR="T480" -#################### INTERNALS – NO NEED TO EDIT ############ - -RSYNC_EXCLUDES_FILE="/tmp/rsync_excludes_$$.txt" - -cat > "${RSYNC_EXCLUDES_FILE}" <<'EOF' +# rsync exclude patterns (passed via stdin to --exclude-from=-) +# Paths are relative to each rsync source root (i.e. $HOME for the home backup). +read -r -d '' RSYNC_EXCLUDES <<'EOF' || true +# === Top-level junk === downloads/ -# Caches & regenerable state +Downloads/ +tmp/ +.tmp/ + +# === All caches (3.9G in .cache alone) === .cache/ + +# === Browsers (rebuilt on next launch) === +.mozilla/ +.mullvad-browser/ + +# === Shell / history / runtime state === .fasd .viminfo -.zcompdump +.zcompdump* +.lesshst .sqlite_history +.python_history +.node_repl_history .wget-hsts -.dbus/ +.xsession-errors* .Xauthority +.ICEauthority +.dbus/ .pki/ -tmp/ +.gvfs/ + +# === Trash === +.local/share/Trash/ +.Trash-*/ + +# === Claude Code old versions (884M, current one re-fetches) === +.local/share/claude/versions/ + +# === Haskell / cabal (1.9G total, fully regenerable) === +.cache/cabal/ +.local/state/cabal/ + +# === Rust / cargo registry (152M, regenerable from Cargo.lock) === +.cargo/registry/ +.cargo/git/ + +# === Python: venvs, caches, bytecode (anywhere in tree) === +__pycache__/ +*.pyc +*.pyo +.mypy_cache/ +.pytest_cache/ +.ruff_cache/ +.tox/ +.venv/ +venv/ +.virtualenvs/ +.local/share/pipx/ + +# === Node / JS === +node_modules/ +.npm/ +.yarn/cache/ +.pnpm-store/ + +# === Build artifacts in repos === +build/ +dist/ +target/ +.gradle/ +.m2/repository/ -# Browser internals -.mozilla/firefox/*/cache2/ -.mozilla/firefox/*/storage/ -.mozilla/firefox/*/datareporting/ -.mullvad-browser/*/cache2/ -.mullvad-browser/*/storage/ +# === LaTeX caches === +.texlive*/texmf-var/ +.texlive*/texmf-cache/ -# Crypto node data (re-syncs) +# === Java runtime junk === +.java/ + +# === Notmuch index (668M, rebuild with `notmuch new`) === +.local/share/mail/.notmuch/xapian/ + +# === Whisper.cpp models (754M, redownloadable) === +git/whisper.cpp/models/ +git/whisper.cpp/build/ + +# === Reinstallable third-party software in ~/opt === +opt/tor-browser/ +opt/monero-gui-*/ +opt/Electrum-*/ + +# === Themes (509M, reinstall from upstream) === +.themes/gruvbox-gtk-theme/ + +# === Crypto node chain data (re-syncs) === .bitmonero/ .shared-ringdb/ +.ethereum/geth/chaindata/ +.bitcoin/blocks/ +.bitcoin/chainstate/ -# Large reinstallable tooling -.cargo/registry -.cargo/git -.texlive2025/ +# === Electron / chat app caches === +.config/Signal/Cache/ +.config/Code/Cache/ +.config/Code/CachedData/ +.config/Code/logs/ -# Java runtime junk -.java/ +# === Flatpak / Snap caches === +.var/app/*/cache/ +snap/*/common/.cache/ + +# === OS junk === +.DS_Store +Thumbs.db +*.swp +*.swo +*~ +core +core.* EOF +#################### INTERNALS – NO NEED TO EDIT ############ + need_cmd() { command -v "$1" >/dev/null 2>&1 || { echo "ERROR: missing command: $1" >&2; exit 1; }; } cleanup() { echo echo ">>> Cleaning up..." - rm -f "${RSYNC_EXCLUDES_FILE}" - - # Try to unmount, if mounted if mountpoint -q "${LUKS_MOUNTPOINT}"; then echo ">>> Unmounting ${LUKS_MOUNTPOINT}..." sudo umount "${LUKS_MOUNTPOINT}" || true fi - # Close LUKS mapping if it exists if [ -e "/dev/mapper/${LUKS_NAME}" ]; then echo ">>> Closing LUKS mapping ${LUKS_NAME}..." sudo cryptsetup close "${LUKS_NAME}" || true @@ -84,17 +166,15 @@ cleanup() { trap cleanup EXIT need_cmd cryptsetup -need_cmd rclone need_cmd rsync need_cmd mountpoint -# Cache sudo credentials early to avoid surprises mid-run +# Cache sudo credentials early sudo -v echo ">>> Ensuring mountpoint exists: ${LUKS_MOUNTPOINT}" sudo mkdir -p "${LUKS_MOUNTPOINT}" -# Check if already open if [ -e "/dev/mapper/${LUKS_NAME}" ]; then echo ">>> WARNING: /dev/mapper/${LUKS_NAME} already exists, assuming already open." else @@ -102,13 +182,11 @@ else sudo cryptsetup open "${LUKS_DEVICE}" "${LUKS_NAME}" fi -# At this point /dev/mapper/${LUKS_NAME} must exist if [ ! -e "/dev/mapper/${LUKS_NAME}" ]; then echo "ERROR: /dev/mapper/${LUKS_NAME} not found after cryptsetup open." >&2 exit 1 fi -# Mount if not already mounted if mountpoint -q "${LUKS_MOUNTPOINT}"; then echo ">>> WARNING: ${LUKS_MOUNTPOINT} already mounted." else @@ -118,21 +196,8 @@ fi echo ">>> LUKS volume mounted at ${LUKS_MOUNTPOINT}" -# Ensure SharePoint destinations exist in root of shield -sudo mkdir -p \ - "${LUKS_MOUNTPOINT}/SP_Administration" \ - "${LUKS_MOUNTPOINT}/SP_Operations" \ - "${LUKS_MOUNTPOINT}/SP_Skyscale" - -echo ">>> Starting rclone syncs (SharePoint -> ${LUKS_MOUNTPOINT}/SP_*)..." -rclone --config "$RCLONE_CONFIG" sync 'SP_Administration:' "${LUKS_MOUNTPOINT}/SP_Administration" --create-empty-src-dirs --fast-list --progress -rclone --config "$RCLONE_CONFIG" sync 'SP_Operations:' "${LUKS_MOUNTPOINT}/SP_Operations" --create-empty-src-dirs --fast-list --progress -rclone --config "$RCLONE_CONFIG" sync 'SP_SkyscaleCommerce:' "${LUKS_MOUNTPOINT}/SP_Skyscale" --create-empty-src-dirs --fast-list --progress -echo ">>> All rclone syncs finished." - echo ">>> Starting rsync backups of local folders -> ${LUKS_MOUNTPOINT}/${MACHINE_DIR}/..." -# Ensure machine root exists sudo mkdir -p "${LUKS_MOUNTPOINT}/${MACHINE_DIR}" for SRC in "${BACKUP_ITEMS[@]}"; do @@ -158,12 +223,24 @@ for SRC in "${BACKUP_ITEMS[@]}"; do sudo mkdir -p "${DEST}" echo ">>> rsync: ${SRC} -> ${DEST}" - rsync -a --delete --progress \ - --exclude-from="${RSYNC_EXCLUDES_FILE}" \ + set +e + sudo rsync -a --delete --progress \ + --exclude-from=- \ "${SRC%/}/" \ - "${DEST}/" + "${DEST}/" <<< "${RSYNC_EXCLUDES}" + RSYNC_RC=$? + set -e + case "${RSYNC_RC}" in + 0) ;; + 23|24) + echo ">>> rsync finished with code ${RSYNC_RC} (some files skipped/vanished); continuing." + ;; + *) + echo "ERROR: rsync failed with code ${RSYNC_RC} on ${SRC}" >&2 + exit "${RSYNC_RC}" + ;; + esac done echo ">>> All rsync backups finished." echo ">>> Unmounting and closing LUKS (via trap)..." -# cleanup() will run automatically on script exit |
