From 21c8870c0d369f025f8f9fc2fb0e86424307bdc1 Mon Sep 17 00:00:00 2001 From: Andreas Wrede Date: Tue, 4 Aug 2026 20:28:51 -0400 Subject: [PATCH] =?UTF-8?q?failover:=20add=20sync-sd-backup.sh=20=E2=80=94?= =?UTF-8?q?=20script=20the=20post-push=20SD=20fallback=20refresh?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The SD card (mmcblk0p2) is refreshed as a live boot-fallback clone of NVMe root after pushes, but that rsync was being hand-typed each time and its exclude list didn't cover /etc/fstab. That let it clobber the SD's own fstab with the NVMe's PARTUUIDs, breaking SD-only boot (only mounts correctly if the NVMe happens to also be present). Also excludes /etc/machine-id and /var/log so the clone doesn't inherit the NVMe's identity/journal history. Co-Authored-By: Claude Sonnet 5 --- failover/sync-sd-backup.sh | 48 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100755 failover/sync-sd-backup.sh diff --git a/failover/sync-sd-backup.sh b/failover/sync-sd-backup.sh new file mode 100755 index 0000000..86c4ac1 --- /dev/null +++ b/failover/sync-sd-backup.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash +# Refresh the SD card (mmcblk0p2) as a live boot-fallback clone of the +# running root filesystem. Run manually after a push: +# sudo ./failover/sync-sd-backup.sh +# +# EEPROM BOOT_ORDER falls back to the SD card if the primary boot disk +# (NVMe) doesn't come up. /etc/fstab, /etc/machine-id, and /var/log are +# excluded from the sync so the clone keeps its own partition identity +# (PARTUUIDs differ per disk) and boot/journal history instead of +# inheriting the source disk's — see failover/README or repo memory +# "sd-fallback-fstab-clobber" for what breaks if those leak across. +set -euo pipefail + +[ "$(id -u)" -eq 0 ] || { echo "Run as root (sudo)." >&2; exit 1; } + +SD_ROOT_PART=/dev/mmcblk0p2 +MOUNT_POINT=/mnt/sd-backup-root + +root_src=$(findmnt -no SOURCE /) +if [ "$root_src" = "$SD_ROOT_PART" ]; then + echo "Currently booted from $SD_ROOT_PART — refusing to sync SD onto itself." >&2 + exit 1 +fi + +mkdir -p "$MOUNT_POINT" +mounted_here=0 +if ! mountpoint -q "$MOUNT_POINT"; then + mount "$SD_ROOT_PART" "$MOUNT_POINT" + mounted_here=1 +else + mount -o remount,rw "$MOUNT_POINT" +fi + +cleanup() { + if [ "$mounted_here" -eq 1 ]; then + umount "$MOUNT_POINT" + fi +} +trap cleanup EXIT + +rsync -aHAX --numeric-ids --delete \ + --exclude=/proc/* --exclude=/sys/* --exclude=/dev/* --exclude=/run/* \ + --exclude=/tmp/* --exclude=/mnt/* --exclude=/media/* --exclude=/lost+found \ + --exclude=/boot/firmware/* --exclude=/swapfile \ + --exclude=/etc/fstab --exclude=/etc/machine-id --exclude=/var/log/* \ + --stats / "$MOUNT_POINT/" + +echo "SD backup ($SD_ROOT_PART) synced from $root_src."