diff options
| author | benj <benj@rse8.com> | 2026-04-01 22:14:57 +0800 |
|---|---|---|
| committer | benj <benj@rse8.com> | 2026-04-01 22:14:57 +0800 |
| commit | 511733d2e11566bd85dec9728403baff3ad2e62b (patch) | |
| tree | f0fd1d6c7ffc2a590eb934672be19fe8b2b19417 /backup | |
| parent | dd6884a7e290bfedf94ba8c8088ace6df43af02a (diff) | |
| download | mycfg-master.tar mycfg-master.tar.gz mycfg-master.tar.bz2 mycfg-master.tar.lz mycfg-master.tar.xz mycfg-master.tar.zst mycfg-master.zip | |
Diffstat (limited to '')
| -rw-r--r-- | backup/ad3/.restic-env | 4 | ||||
| -rw-r--r-- | backup/ad3/README.org | 111 | ||||
| -rwxr-xr-x | backup/ad3/backup-cloud | 30 | ||||
| -rw-r--r-- | backup/ad3/backup-cloud.service | 10 | ||||
| -rw-r--r-- | backup/ad3/backup-cloud.timer | 10 | ||||
| -rw-r--r-- | backup/ad3/restic-exclude.txt | 77 |
6 files changed, 242 insertions, 0 deletions
diff --git a/backup/ad3/.restic-env b/backup/ad3/.restic-env new file mode 100644 index 0000000..f5fb078 --- /dev/null +++ b/backup/ad3/.restic-env @@ -0,0 +1,4 @@ +export B2_ACCOUNT_ID="" +export B2_ACCOUNT_KEY="" +export RESTIC_REPOSITORY="b2:benj-ad3" +export RESTIC_PASSWORD=""
\ No newline at end of file diff --git a/backup/ad3/README.org b/backup/ad3/README.org new file mode 100644 index 0000000..abb96b9 --- /dev/null +++ b/backup/ad3/README.org @@ -0,0 +1,111 @@ +* Overview +# sudo cp /root/.restic-env +# sudo cp /root/restic-exclude.txt +# sudo chmod 600 /root/.restic-env +# sub the values for /root/.restic-env + +You need to initialize the restic repository first before you can back up to it. This is a one-time step: + +#+begin_src sh +sudo bash -c 'source /root/.restic-env && restic init' +#+end_src + +sudo systemctl daemon-reload +sudo systemctl enable --now backup-cloud.timer + +# Verify +systemctl list-timers backup-cloud.timer + +** Restoring from Restic + +#+begin_src sh +sudo bash -c 'source /root/.restic-env && restic snapshots' # list snapshots +sudo bash -c 'source /root/.restic-env && restic ls latest /home/benj' # browse +sudo bash -c 'source /root/.restic-env && restic restore latest --target /tmp/restore' # full restore +sudo bash -c 'source /root/.restic-env && restic restore latest --target /tmp/restore --include /home/benj/somefile' # specific file +#+end_src + +** Disaster Recovery ISO + +This creates a bootable ISO that contains your disk layout, bootloader config, and everything needed to do a bare-metal restore onto a new or wiped machine. + +*** Install + +#+begin_src sh +# From AUR +paru -S rear # or yay -S rear +#+end_src + +*** Configure + +Edit =/etc/rear/local.conf=: + +#+begin_src conf +OUTPUT=ISO +OUTPUT_URL=file:///root/rear-output/ +BACKUP=NETFS +BACKUP_URL=file:///mnt/backup/rear/ +BACKUP_PROG_EXCLUDE=("${BACKUP_PROG_EXCLUDE[@]}" '/var/lib/docker' '/var/cache/pacman/pkg' '/home/benj/.cache' '/home/benj/.rustup' '/home/benj/.ghcup' '/home/benj/.stack' '/home/benj/.espressif' '/home/benj/go/pkg' '/home/benj/Android' '/home/benj/.npm/_cacache' '/home/benj/.cargo/registry' '/home/benj/.cargo/git' '/home/benj/.android/avd' '/var/log/journal' '/var/lib/systemd/coredump') +#+end_src + +*** Create Recovery ISO + +#+begin_src sh +# With external drive mounted at /mnt/backup: +sudo mkdir -p /root/rear-output /mnt/backup/rear +sudo rear -v mkbackup +#+end_src + +This produces: +- =/root/rear-output/rear-*.iso= — bootable recovery ISO +- =/mnt/backup/rear/= — the backup archive + +*/ Using Rear to Restore + +1. Write the ISO to a USB stick: =sudo dd if=/root/rear-output/rear-*.iso of=/dev/sdX bs=4M status=progress= +2. Boot from it on the new/wiped machine +3. Select "Recover" from the menu +4. Rear automatically: + - Recreates your partition layout + - Sets up LUKS (it will ask for your passphrase) + - Creates LVM + - Restores all files + - Installs the bootloader +5. Reboot into your restored system + +** When to Regenerate the ISO + +- After major system changes (new partitions, bootloader changes) +- Monthly alongside your regular backups +- After adding/removing LUKS keyslots + +** Verification (Montly) + +Create =/usr/local/bin/backup-verify=: + +#+begin_src bash +#!/bin/bash +set -euo pipefail +source /root/.restic-env + +echo "=== B2 Snapshots ===" +restic snapshots --latest 10 + +echo "" +echo "=== Repository Integrity (sampling 5%) ===" +restic check --read-data-subset=5% + +echo "" +echo "=== Repository Size ===" +restic stats + +echo "" +echo "=== Rear ISO ===" +ls -lh /root/rear-output/rear-*.iso 2>/dev/null || echo "WARNING: No Rear ISO found! Run: sudo rear -v mkbackup" + +echo "" +echo "=== LUKS Header Backup ===" +ls -lh /root/luks-header-backup 2>/dev/null || echo "WARNING: No LUKS header backup! Run the backup immediately." +#+end_src + + diff --git a/backup/ad3/backup-cloud b/backup/ad3/backup-cloud new file mode 100755 index 0000000..82b5a1b --- /dev/null +++ b/backup/ad3/backup-cloud @@ -0,0 +1,30 @@ +set -euo pipefail + +if [ "$(id -u)" -ne 0 ]; then + echo "Run with sudo" + exit 1 +fi + +source /root/.restic-env + +# Backup LUKS header into a location restic will pick up +cryptsetup luksHeaderBackup /dev/nvme0n1p2 \ + --header-backup-file /root/luks-header-backup.tmp +mv /root/luks-header-backup.tmp /root/luks-header-backup + +# Run backup (/ and /boot since /boot is a separate partition) +restic backup / /boot \ + --exclude-file=/home/benj/.mycfg/backup/ad3/restic-exclude.txt \ + --exclude-caches \ + --verbose + +# Retention: 4 weekly, 6 monthly, 1 yearly +restic forget \ + --keep-weekly 4 \ + --keep-monthly 6 \ + --keep-yearly 1 \ + --prune + +echo "" +echo "=== Latest snapshots ===" +restic snapshots --latest 5
\ No newline at end of file diff --git a/backup/ad3/backup-cloud.service b/backup/ad3/backup-cloud.service new file mode 100644 index 0000000..472ea75 --- /dev/null +++ b/backup/ad3/backup-cloud.service @@ -0,0 +1,10 @@ +[Unit] +Description=Restic backup to Backblaze B2 +Wants=network-online.target +After=network-online.target + +[Service] +Type=oneshot +ExecStart=/home/benj/.mycfg/backup/ad3/backup-cloud +Nice=19 +IOSchedulingClass=idle
\ No newline at end of file diff --git a/backup/ad3/backup-cloud.timer b/backup/ad3/backup-cloud.timer new file mode 100644 index 0000000..e67bbfd --- /dev/null +++ b/backup/ad3/backup-cloud.timer @@ -0,0 +1,10 @@ +[Unit] +Description=Weekly cloud backup to B2 + +[Timer] +OnCalendar=Sun 02:00 +RandomizedDelaySec=1h +Persistent=true + +[Install] +WantedBy=timers.target
\ No newline at end of file diff --git a/backup/ad3/restic-exclude.txt b/backup/ad3/restic-exclude.txt new file mode 100644 index 0000000..4d19e57 --- /dev/null +++ b/backup/ad3/restic-exclude.txt @@ -0,0 +1,77 @@ +# Virtual/temp +/dev +/proc +/sys +/tmp +/run +/mnt +/media +/lost+found +/swapfile + +# Caches +/var/lib/docker +/var/cache/pacman/pkg +/var/cache/man +/var/cache/fontconfig +/var/cache/fwupd +/var/log/journal +/var/lib/systemd/coredump +/home/benj/.cache +/home/benj/.local/share/Trash +/home/benj/.local/share/Steam + +# Home caches and toolchains +/home/benj/.rustup +/home/benj/.cargo/registry +/home/benj/.cargo/git +/home/benj/.ghcup +/home/benj/.stack +/home/benj/.cabal +/home/benj/.espressif +/home/benj/.nvm +/home/benj/.npm +/home/benj/.virtualenvs +/home/benj/.opam +/home/benj/.gradle +/home/benj/.m2 +/home/benj/go/pkg +/home/benj/Android +/home/benj/.android/avd +/home/benj/.local/share/uv + +/home/benj/.config/Slack/Service Worker +/home/benj/.config/Slack/Cache +/home/benj/.config/chromium/Profile 1 +/home/benj/.config/chromium/Default/Service Worker +/home/benj/.config/chromium/GrShaderCache +/home/benj/.config/chromium/component_crx_cache +/home/benj/.config/chromium/extensions_crx_cache +/home/benj/.config/discord/Cache +/home/benj/.config/discord/0.0.60 +/home/benj/.config/figma-linux/Code Cache +/home/benj/.config/Insomnia/responses +/home/benj/.config/Signal/attachments.noindex + +/home/benj/.claude +/home/benj/Downloads + +**/target +**/node_modules +**/build +**/CMakeFiles +**/__pycache__ +**/.tox +**/dist +**/*.egg-info +**/.gradle +**/.cabal-sandbox + +/home/benj/.cabal +/home/benj/.gradle +/home/benj/.m2 +/home/benj/.nvm +/home/benj/.virtualenvs +/home/benj/.opam +/home/benj/.npm +/home/benj/.claude
\ No newline at end of file |
