Make Manual Backup match the system role (Desktop Only scope)

The Manual Backup screen in the Hub always listed the Node / Server +
Desktop items (nix-bitcoin secrets, /var/lib system service data, and the
database/blockchain caveat), and the backup script mirrored /var/lib and
counted it in the free-space estimate even on the Desktop Only role.
Desktop Only systems run no server or Bitcoin services and have no
internal second data drive, so none of that applies.

Hub UI (support.js):
- 'What gets backed up' is role-aware: Desktop Only lists only the NixOS
  configuration (/etc/nixos) and home directory (/home)
- Database/blockchain note hidden on Desktop Only
- Intro copy corrected: external USB copy is a second location on
  Desktop Only (no internal second drive); third-location wording kept
  for Node / Server + Desktop

Backup script (sovran-hub-backup.sh):
- Desktop Only runs 2 stages (1/2 /etc/nixos, 2/2 /home); secrets and
  /var/lib stages no longer run on that role
- Free-space estimate skips /var/lib on Desktop Only
- BACKUP_MANIFEST.txt sources/exclusions/limitations/restore guidance
  and blockchain note are role-aware
- Completion message role-aware ('second, external location' on
  Desktop Only); header comments updated

Node and Server + Desktop behavior is unchanged. Added CHANGELOG entry.

Verified: bash -n / node --check, 6 role-detection cases, manifest
generation for both role groups (non-desktop output identical to
before), and simulated UI renders for all three roles.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
This commit is contained in:
naturallaw777
2026-07-30 21:49:04 +00:00
co-authored by arena-agent
parent 670cfb9acd
commit 94e4412e67
3 changed files with 188 additions and 84 deletions
+13
View File
@@ -7,6 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
---
## [Unreleased]
### Fixed
- **Manual Backup now matches the system role**: on the Desktop Only role the Hub's
"What gets backed up" list no longer shows Node / Server + Desktop items
(nix-bitcoin secrets, `/var/lib` system service data, and the database/blockchain
caveats), and the backup script skips those stages entirely — Desktop Only backups
now mirror only the NixOS configuration (`/etc/nixos`) and home directory (`/home`).
The free-space estimate, stage numbering, backup manifest, and completion message
are all role-aware; Node and Server + Desktop backups are unchanged.
---
## [1.0.4] - 2026-07-29
### Added
@@ -3,10 +3,18 @@
# Backs up Sovran_SystemsOS data to an external USB hard drive using rsync.
# Designed for the Hub web UI (no GUI dependencies).
#
# Your Sovran Pro already backs up your data automatically to its
# internal second drive (BTCEcoandBackup at /run/media/Second_Drive).
# This script creates an additional copy on an external USB drive —
# storing your data in a third location for maximum protection.
# On Server + Desktop and Node systems, your Sovran Pro already backs up
# your data automatically to its internal second drive (BTCEcoandBackup at
# /run/media/Second_Drive); this script stores a copy in a third location.
# Desktop Only systems have no internal second drive, so the external copy
# is the second location.
#
# What gets mirrored depends on the system role:
# - Node / Server + Desktop: /etc/nixos, /etc/nix-bitcoin-secrets,
# /home, and /var/lib (minus databases, blockchain data, logs, caches).
# - Desktop Only: /etc/nixos and /home. Desktop Only runs no server or
# Bitcoin services, so there are no nix-bitcoin secrets or system
# service data to back up.
#
# The external drive must be formatted as ext4. Files are stored as
# directly browsable files under Sovran_SystemsOS_Backup/current/.
@@ -344,6 +352,19 @@ case "$ROLE" in
esac
log "Detected role: $ROLE_LABEL"
# Backup scope depends on the role. Desktop Only systems run no server or
# Bitcoin services, so only the NixOS configuration and home directory are
# mirrored (2 stages). Node and Server + Desktop systems also mirror the
# nix-bitcoin secrets and /var/lib system service data (4 stages).
if [[ "$ROLE" == "desktop" ]]; then
TOTAL_STAGES=2
HOME_STAGE_NUM=2
log "Desktop Only role: backing up the NixOS configuration (/etc/nixos) and home directory (/home) only."
else
TOTAL_STAGES=4
HOME_STAGE_NUM=3
fi
# ── Detect target drive ──────────────────────────────────────────
if [[ -n "${BACKUP_TARGET:-}" ]]; then
@@ -385,22 +406,25 @@ log "Backup destination: $BACKUP_DIR"
ETC_NIXOS_BYTES=$(estimate_path_bytes /etc/nixos)
HOME_BYTES=$(estimate_path_bytes /home --exclude='*/.cache' --exclude='*/.local/share/Trash' --exclude='*/Trash')
# nix-bitcoin secrets and /var/lib system service data exist only on the
# Node and Server + Desktop roles — they are skipped entirely on Desktop Only.
SECRETS_BYTES=0
VAR_LIB_BYTES=0
if [[ "$ROLE" != "desktop" ]]; then
SECRETS_BYTES=$(estimate_path_bytes /etc/nix-bitcoin-secrets)
VAR_LIB_BYTES=$(estimate_path_bytes /var/lib \
--exclude='postgresql' \
--exclude='mysql' \
--exclude='mariadb' \
--exclude='bitcoind' \
--exclude='electrs' \
--exclude='*/log' \
--exclude='*/logs' \
--exclude='*/cache' \
--exclude='*/tmp')
fi
VAR_LIB_BYTES=$(estimate_path_bytes /var/lib \
--exclude='postgresql' \
--exclude='mysql' \
--exclude='mariadb' \
--exclude='bitcoind' \
--exclude='electrs' \
--exclude='*/log' \
--exclude='*/logs' \
--exclude='*/cache' \
--exclude='*/tmp')
ESTIMATED_BYTES=$(( ETC_NIXOS_BYTES + HOME_BYTES + SECRETS_BYTES + VAR_LIB_BYTES ))
# Require 20% growth headroom plus a fixed 1 GiB safety margin.
# Later incremental runs need far less space, but a conservative first-run
@@ -418,10 +442,10 @@ log "Free space on drive: ${FREE_GB} GB"
(( FREE_BYTES >= REQUIRED_BYTES )) || \
fail "Not enough free space on drive (${FREE_GB} GB available, ${REQUIRED_GB} GB required)."
# ── Stage 1/4: NixOS configuration ──────────────────────────────
# ── Stage 1: NixOS configuration ────────────────────────────────
log ""
log "── Stage 1/4: NixOS configuration (/etc/nixos) ──────────────"
log "── Stage 1/${TOTAL_STAGES}: NixOS configuration (/etc/nixos) ──────────────"
if [[ -d /etc/nixos ]]; then
sync_tree "/etc/nixos" no /etc/nixos/ "$BACKUP_DIR/etc/nixos/"
log "Stage 1 complete."
@@ -429,26 +453,30 @@ else
log "WARNING: /etc/nixos not found — skipping."
fi
# ── Stage 2/4: Secrets ──────────────────────────────────────────
# ── Stage 2: Secrets ────────────────────────────────────────────
# Only applies to the Node and Server + Desktop roles. Desktop Only systems
# run no nix-bitcoin services, so there are no secrets to back up and this
# stage does not exist for them.
log ""
log "── Stage 2/4: Secrets (/etc/nix-bitcoin-secrets) ───────────"
if [[ "$ROLE" == "desktop" ]]; then
log "Skipping /etc/nix-bitcoin-secrets — not applicable for Desktop Only role."
elif [[ -e /etc/nix-bitcoin-secrets ]]; then
sync_tree "/etc/nix-bitcoin-secrets" no /etc/nix-bitcoin-secrets/ "$BACKUP_DIR/etc/nix-bitcoin-secrets/"
else
log "(not found: /etc/nix-bitcoin-secrets — skipping)"
if [[ "$ROLE" != "desktop" ]]; then
log ""
log "── Stage 2/${TOTAL_STAGES}: Secrets (/etc/nix-bitcoin-secrets) ───────────"
if [[ -e /etc/nix-bitcoin-secrets ]]; then
sync_tree "/etc/nix-bitcoin-secrets" no /etc/nix-bitcoin-secrets/ "$BACKUP_DIR/etc/nix-bitcoin-secrets/"
else
log "(not found: /etc/nix-bitcoin-secrets — skipping)"
fi
log "Stage 2 complete."
fi
log "Stage 2 complete."
# ── Stage 3/4: Home directory ───────────────────────────────────
# ── Home directory ──────────────────────────────────────────────
# Stage 2/2 on Desktop Only, stage 3/4 on Node and Server + Desktop.
# Rsync exit code 24 (vanished source files) is treated as nonfatal here
# because the desktop may be active and files can disappear between the
# directory scan and the copy. All other nonzero exit codes remain fatal.
log ""
log "── Stage 3/4: Home directory (/home) ───────────────────────"
log "── Stage ${HOME_STAGE_NUM}/${TOTAL_STAGES}: Home directory (/home) ───────────────────────"
if [[ -d /home ]]; then
sync_tree "/home" yes /home/ "$BACKUP_DIR/home/" \
--exclude='.cache/' \
@@ -467,32 +495,36 @@ if [[ -d /home ]]; then
--exclude='.thumbnails/' \
--exclude='.xsession-errors' \
--exclude='.xsession-errors.old'
log "Stage 3 complete."
log "Stage ${HOME_STAGE_NUM} complete."
else
log "WARNING: /home not found — skipping."
fi
# ── Stage 4/4: System data ──────────────────────────────────────
# ── Stage 4: System data ────────────────────────────────────────
# Only applies to the Node and Server + Desktop roles — Desktop Only systems
# run no server services, so /var/lib holds no service data worth mirroring.
# PostgreSQL/MariaDB raw database directories are excluded. Application
# databases must be backed up separately with native database tools.
# Bitcoin/Electrs data are excluded; they live on the internal second drive.
log ""
log "── Stage 4/4: System data (/var/lib) ───────────────────────"
if [[ -d /var/lib ]]; then
sync_tree "/var/lib" no /var/lib/ "$BACKUP_DIR/var/lib/" \
--exclude='postgresql/' \
--exclude='mysql/' \
--exclude='mariadb/' \
--exclude='bitcoind/' \
--exclude='electrs/' \
--exclude='*/log/' \
--exclude='*/logs/' \
--exclude='*/cache/' \
--exclude='*/tmp/'
log "Stage 4 complete."
else
log "WARNING: /var/lib not found — skipping."
if [[ "$ROLE" != "desktop" ]]; then
log ""
log "── Stage 4/${TOTAL_STAGES}: System data (/var/lib) ───────────────────────"
if [[ -d /var/lib ]]; then
sync_tree "/var/lib" no /var/lib/ "$BACKUP_DIR/var/lib/" \
--exclude='postgresql/' \
--exclude='mysql/' \
--exclude='mariadb/' \
--exclude='bitcoind/' \
--exclude='electrs/' \
--exclude='*/log/' \
--exclude='*/logs/' \
--exclude='*/cache/' \
--exclude='*/tmp/'
log "Stage 4 complete."
else
log "WARNING: /var/lib not found — skipping."
fi
fi
# ── Generate manifest ────────────────────────────────────────────
@@ -517,23 +549,29 @@ MANIFEST_FILE="$BACKUP_DIR/BACKUP_MANIFEST.txt"
echo "- /etc/nix-bitcoin-secrets (when present) → current/etc/nix-bitcoin-secrets/"
fi
echo "- /home → current/home/"
echo "- /var/lib → current/var/lib/"
if [[ "$ROLE" != "desktop" ]]; then
echo "- /var/lib → current/var/lib/"
fi
echo ""
echo "Exclusions:"
echo "- /var/lib/postgresql (PostgreSQL raw database files — not included)"
echo "- /var/lib/mysql, /var/lib/mariadb (MariaDB raw database files — not included)"
echo "- /var/lib/bitcoind (Bitcoin blockchain — excluded; lives on internal second drive)"
echo "- /var/lib/electrs (Electrs index — excluded; lives on internal second drive)"
echo "- /run/media/Second_Drive (internal second drive — never traversed)"
echo "- /var/lib/*/log, /var/lib/*/logs, /var/lib/*/cache, /var/lib/*/tmp"
if [[ "$ROLE" != "desktop" ]]; then
echo "- /var/lib/postgresql (PostgreSQL raw database files — not included)"
echo "- /var/lib/mysql, /var/lib/mariadb (MariaDB raw database files — not included)"
echo "- /var/lib/bitcoind (Bitcoin blockchain — excluded; lives on internal second drive)"
echo "- /var/lib/electrs (Electrs index — excluded; lives on internal second drive)"
echo "- /run/media/Second_Drive (internal second drive — never traversed)"
echo "- /var/lib/*/log, /var/lib/*/logs, /var/lib/*/cache, /var/lib/*/tmp"
fi
echo "- Browser disk caches, thumbnail caches, trash directories, X session error logs"
echo ""
echo "Important limitations:"
echo "- PostgreSQL and MariaDB/MySQL application databases are NOT included in this"
echo " backup. If you use Nextcloud, Matrix/Synapse, or other database-backed"
echo " applications, their data must be backed up separately using native tools."
echo "- Bitcoin blockchain data and Electrs indexes are NOT included; they are"
echo " reconstructable or stored on the internal second drive."
if [[ "$ROLE" != "desktop" ]]; then
echo "- PostgreSQL and MariaDB/MySQL application databases are NOT included in this"
echo " backup. If you use Nextcloud, Matrix/Synapse, or other database-backed"
echo " applications, their data must be backed up separately using native tools."
echo "- Bitcoin blockchain data and Electrs indexes are NOT included; they are"
echo " reconstructable or stored on the internal second drive."
fi
echo "- This is a live file-level mirror, not a transactional database backup."
echo " Files being written during the backup may be in an inconsistent state."
echo ""
@@ -542,7 +580,9 @@ MANIFEST_FILE="$BACKUP_DIR/BACKUP_MANIFEST.txt"
echo "- To restore a directory:"
echo " sudo rsync -aAXH --numeric-ids current/etc/nixos/ /etc/nixos/"
echo " sudo rsync -aAXH --numeric-ids current/home/ /home/"
echo " sudo rsync -aAXH --numeric-ids current/var/lib/ /var/lib/"
if [[ "$ROLE" != "desktop" ]]; then
echo " sudo rsync -aAXH --numeric-ids current/var/lib/ /var/lib/"
fi
echo "- To copy individual files:"
echo " sudo cp -a current/home/username/ /home/username/"
echo "- When restoring /etc/nixos to replacement hardware, regenerate"
@@ -556,10 +596,12 @@ MANIFEST_FILE="$BACKUP_DIR/BACKUP_MANIFEST.txt"
echo "- $warning"
done
fi
echo ""
echo "Note: Bitcoin blockchain and Electrs index data are intentionally excluded"
echo "from manual external backup because they already live on the internal second drive"
echo "(/run/media/Second_Drive) and are reconstructable/internal-backup data."
if [[ "$ROLE" != "desktop" ]]; then
echo ""
echo "Note: Bitcoin blockchain and Electrs index data are intentionally excluded"
echo "from manual external backup because they already live on the internal second drive"
echo "(/run/media/Second_Drive) and are reconstructable/internal-backup data."
fi
} > "$MANIFEST_FILE"
log "Manifest written to $MANIFEST_FILE"
@@ -576,7 +618,11 @@ if [[ "${#RSYNC_WARNINGS[@]}" -gt 0 ]]; then
log "vanished during backup, which is normal on an active desktop."
log ""
fi
log "All Finished! Your data is now backed up to a third location."
if [[ "$ROLE" == "desktop" ]]; then
log "All Finished! Your data is now backed up to a second, external location."
else
log "All Finished! Your data is now backed up to a third location."
fi
log "Files are directly browsable on the drive under: ${BACKUP_DIR}"
log "Please eject the drive safely before removing it from your Sovran Pro."
+64 -19
View File
@@ -473,19 +473,73 @@ function renderBackupReady(drives) {
].join("");
}
// ── Role-aware backup description ─────────────────────────────
// Desktop Only systems run no server or Bitcoin services and have no
// internal second drive, so the backup mirrors only the NixOS configuration
// and home directory. nix-bitcoin secrets, /var/lib system service data,
// and the database/blockchain caveats apply only to the Node and
// Server + Desktop roles.
var isDesktopOnly = (_currentRole === "desktop");
var introHtml;
if (isDesktopOnly) {
introHtml = [
'<div class="support-wallet-box support-wallet-protected" style="margin-bottom:16px;">',
'<p class="support-wallet-desc">',
'This manual backup lets you create a copy of your system on an external USB drive \u2014 ',
'storing your data in a second location, outside the computer, for maximum protection ',
'against hardware failure or physical damage.',
'</p>',
'</div>',
].join("");
} else {
introHtml = [
'<div class="support-wallet-box support-wallet-protected" style="margin-bottom:16px;">',
'<p class="support-wallet-desc">',
'Your Sovran Pro already backs up your data automatically to its internal second drive. ',
'This manual backup lets you create an additional copy on an external USB drive \u2014 ',
'storing your data in a third location, outside the computer, for maximum protection ',
'against hardware failure or physical damage.',
'</p>',
'</div>',
].join("");
}
var backupItemsHtml;
if (isDesktopOnly) {
backupItemsHtml = [
'<li>NixOS configuration (<code>/etc/nixos</code>)</li>',
'<li>Home directory (<code>/home</code>)</li>',
].join("");
} else {
backupItemsHtml = [
'<li>NixOS configuration (<code>/etc/nixos</code>)</li>',
'<li>nix-bitcoin secrets (<code>/etc/nix-bitcoin-secrets</code>)</li>',
'<li>System service data (<code>/var/lib</code>) — excluding databases and blockchain data (see note below)</li>',
'<li>Home directory (<code>/home</code>)</li>',
].join("");
}
// The database/blockchain caveat is only relevant when server services exist.
var dbNoteHtml = "";
if (!isDesktopOnly) {
dbNoteHtml = [
'<div class="support-wallet-box support-wallet-warning">',
'<div class="support-wallet-header">',
'<span class="support-wallet-icon">\u2139\ufe0f</span>',
'<span class="support-wallet-title">Database and Blockchain Data</span>',
'</div>',
'<p class="support-wallet-desc">Application databases stored in PostgreSQL or MariaDB/MySQL are <strong>not included</strong> in Manual Backup. Bitcoin blockchain and Electrs index data are also excluded (they are stored on the internal second drive). If you use Nextcloud, Matrix, or other database-backed applications, back up those databases separately with their native tools.</p>',
'</div>',
].join("");
}
$supportBody.innerHTML = [
'<div class="support-section">',
'<div class="support-icon-big">\ud83d\udcbe</div>',
'<h3 class="support-heading">Manual Backup</h3>',
'<div class="support-wallet-box support-wallet-protected" style="margin-bottom:16px;">',
'<p class="support-wallet-desc">',
'Your Sovran Pro already backs up your data automatically to its internal second drive. ',
'This manual backup lets you create an additional copy on an external USB drive \u2014 ',
'storing your data in a third location, outside the computer, for maximum protection ',
'against hardware failure or physical damage.',
'</p>',
'</div>',
introHtml,
'<div class="support-steps">',
'<div class="support-steps-title">Requirements</div>',
@@ -500,20 +554,11 @@ function renderBackupReady(drives) {
'<div class="support-steps">',
'<div class="support-steps-title">What gets backed up</div>',
'<ol class="support-backup-steps">',
'<li>NixOS configuration (<code>/etc/nixos</code>)</li>',
'<li>nix-bitcoin secrets (<code>/etc/nix-bitcoin-secrets</code>)</li>',
'<li>System service data (<code>/var/lib</code>) — excluding databases and blockchain data (see note below)</li>',
'<li>Home directory (<code>/home</code>)</li>',
backupItemsHtml,
'</ol>',
'</div>',
'<div class="support-wallet-box support-wallet-warning">',
'<div class="support-wallet-header">',
'<span class="support-wallet-icon">\u2139\ufe0f</span>',
'<span class="support-wallet-title">Database and Blockchain Data</span>',
'</div>',
'<p class="support-wallet-desc">Application databases stored in PostgreSQL or MariaDB/MySQL are <strong>not included</strong> in Manual Backup. Bitcoin blockchain and Electrs index data are also excluded (they are stored on the internal second drive). If you use Nextcloud, Matrix, or other database-backed applications, back up those databases separately with their native tools.</p>',
'</div>',
dbNoteHtml,
'<div class="support-wallet-box support-wallet-protected">',
'<div class="support-wallet-header">',