From 3d09105ed5f16090f93c0e3e55055af6d448d567 Mon Sep 17 00:00:00 2001 From: librelad Date: Tue, 26 May 2026 21:47:12 +0100 Subject: [PATCH] fix(update): define backup_install_dir + correct gitCleanInstallBackups find MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three small bugs in the legacy git-update flow that all hung off the same never-set variable: 1. backup_install_dir was referenced in 4 files (reset_git_backup, install_git_backup, use_git_backup, config_git_check) but DEFINED nowhere — never has been, in any branch or tag. Resolved to "", so "$backup_install_dir/$backupFolder" became "/backup_" (filesystem root, perm denied). Add it to libreportalDerivePaths beside the other roots, point it at $backup_dir/install (a sibling of restic's per- location subdirs at $backup_dir/), and add it to initFolders so it exists on first install. 2. gitCleanInstallBackups' find expression was find ... -mindepth 1 -type f ! -name '*.zip' -o -type d ! -name '*.zip' -exec rm -rf {} + `-o` binds looser than the implicit -a, so the -exec only applied to the second clause. That meant: every non-.zip DIR anywhere under the tree got deleted; every non-.zip FILE got matched and ignored. Even once $backup_install_dir resolved correctly the cleanup would've wrecked unrelated dirs. Collapsed to `-mindepth 1 -maxdepth 1 ! -name '*.zip' -exec rm -rf {} +` — direct children of $backup_install_dir, kill everything that isn't a zip, let -rf take care of the dirs. Synthetic-tree smoke test confirms only the .zip files survive. 3. use_git_backup.sh had a typo'd doubled var: copyFolders "$backup_install_dir$backup_install_dir/$backup_file_without_zip/" ... Reduced to the single $backup_install_dir/$backup_file_without_zip/. All three only fire in the manual-update path (libreportal update apply under git/local install mode); the install-blocking path is unaffected. Co-Authored-By: Claude Opus 4.7 Signed-off-by: librelad --- init.sh | 7 ++++++- scripts/update/backup/install_git_backup.sh | 9 ++++++++- scripts/update/backup/use_git_backup.sh | 2 +- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/init.sh b/init.sh index 8910fe4..80b2ea9 100755 --- a/init.sh +++ b/init.sh @@ -172,6 +172,11 @@ libreportalDerivePaths() { install_scripts_dir="$script_dir/scripts/" containers_dir="$LP_CONTAINERS_DIR/" backup_dir="$LP_BACKUPS_DIR" + # Pre-update install snapshots (configs + logs zipped before the legacy + # git-update reset_git → checkout cycle). Distinct from restic's per- + # location subdirs which live at $backup_dir/. Used by + # gitPerformUpdate / gitCleanInstallBackups / use_git_backup / config_git_check. + backup_install_dir="$backup_dir/install" # Control-plane manager user (configurable; default libreportal). sudo_user_name="${LP_MANAGER_USER:-${sudo_user_name:-libreportal}}" @@ -969,7 +974,7 @@ initRootHelpers() initFolders() { isHeader "LibrePortal Folder Creation" - folders=("$docker_dir" "$containers_dir" "$ssl_dir" "$ssh_dir" "$wireguard_dir" "$logs_dir" "$configs_dir" "$backup_dir" "$restore_dir" "$migrate_dir" "$script_dir") + folders=("$docker_dir" "$containers_dir" "$ssl_dir" "$ssh_dir" "$wireguard_dir" "$logs_dir" "$configs_dir" "$backup_dir" "$backup_install_dir" "$restore_dir" "$migrate_dir" "$script_dir") for folder in "${folders[@]}"; do if [ ! -d "$folder" ]; then sudo mkdir "$folder" diff --git a/scripts/update/backup/install_git_backup.sh b/scripts/update/backup/install_git_backup.sh index a697d4b..5bfba8c 100755 --- a/scripts/update/backup/install_git_backup.sh +++ b/scripts/update/backup/install_git_backup.sh @@ -2,7 +2,14 @@ gitCleanInstallBackups() { - local result=$(runInstallOp find "$backup_install_dir" -mindepth 1 -type f ! -name '*.zip' -o -type d ! -name '*.zip' -exec rm -rf {} +) + # Remove the unzipped backup_/ snapshot dirs we just rolled up, keeping + # the .zip files themselves. `-mindepth 1 -maxdepth 1` limits to direct + # children of $backup_install_dir; `-exec rm -rf {} +` handles dirs via + # -r. The previous `-type f ! -name '*.zip' -o -type d ! -name '*.zip'` + # mis-applied the -exec to only the second clause (-o binds looser than + # the implicit -a), so it deleted every non-.zip dir under the WHOLE tree + # while matching no files at all. + local result=$(runInstallOp find "$backup_install_dir" -mindepth 1 -maxdepth 1 ! -name '*.zip' -exec rm -rf {} +) checkSuccess "Cleaning up install backup folders." local result=$(cd "$backup_install_dir" && find . -maxdepth 1 -type f -name '*.zip' | xargs ls -t | tail -n +6 | xargs -r rm) checkSuccess "Deleting old install backup and keeping the latest 5." diff --git a/scripts/update/backup/use_git_backup.sh b/scripts/update/backup/use_git_backup.sh index 93a8292..31925bf 100755 --- a/scripts/update/backup/use_git_backup.sh +++ b/scripts/update/backup/use_git_backup.sh @@ -12,7 +12,7 @@ gitUseExistingBackup() gitReset; - local result=$(copyFolders "$backup_install_dir$backup_install_dir/$backup_file_without_zip/" "$docker_dir" "$sudo_user_name") + local result=$(copyFolders "$backup_install_dir/$backup_file_without_zip/" "$docker_dir" "$sudo_user_name") checkSuccess "Copy the backed up folders back into the installation directory" gitCleanInstallBackups;