fix(switcher): enumerate containers/ as the old-mode owner mid-switch

The two docker-type-switcher finds run mid-switch, BEFORE
reconcileDockerOwnership, so containers/ is still owned by the OLD mode's
container user while CFG_DOCKER_INSTALL_TYPE is already the target. A
plain runFileOp resolves to the target user, which can't list the
old-mode-owned (751) dir under rootless — so enumerate as the old-mode
owner instead:

- switchMigrateBackupApps: move the find inside the existing
  old_mode/resolveDockerInstallUser window (runFileOp now resolves to the
  old owner). It previously ran as the manager and silently enumerated
  nothing under rootless, so no app got backed up before the switch.
- dockerSwitcherUpdateContainersToDockerType: take old_mode as an arg,
  flip CFG to it only for the find (restore before the per-app socket
  scan + restart, which need the new daemon). Callers in swap_docker_type
  pass $docker_type. The two former rooted/rootless branches were
  byte-identical and are collapsed.

NOTE: the full rooted<->rootless switch round-trip is still unvalidated
on the VM (needs a stateful app + an enabled backup location); this fixes
the container enumeration, not yet the end-to-end migration.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
This commit is contained in:
librelad 2026-05-24 21:51:20 +01:00
parent 936d533fa1
commit e0c7928942
2 changed files with 29 additions and 25 deletions

View File

@ -70,7 +70,7 @@ dockerSwitcherSwap()
installDocker; installDocker;
fi fi
dockerServiceStart rooted; dockerServiceStart rooted;
dockerSwitcherUpdateContainersToDockerType; dockerSwitcherUpdateContainersToDockerType "$docker_type";
reconcileDockerOwnership "$CFG_DOCKER_INSTALL_TYPE"; reconcileDockerOwnership "$CFG_DOCKER_INSTALL_TYPE";
dockerStartAllApps; dockerStartAllApps;
databaseOptionInsert "docker_type" $CFG_DOCKER_INSTALL_TYPE; databaseOptionInsert "docker_type" $CFG_DOCKER_INSTALL_TYPE;
@ -109,7 +109,7 @@ dockerSwitcherSwap()
dockerServiceStop rooted; dockerServiceStop rooted;
fi fi
dockerServiceStart rootless; dockerServiceStart rootless;
dockerSwitcherUpdateContainersToDockerType; dockerSwitcherUpdateContainersToDockerType "$docker_type";
reconcileDockerOwnership "$CFG_DOCKER_INSTALL_TYPE"; reconcileDockerOwnership "$CFG_DOCKER_INSTALL_TYPE";
dockerStartAllApps; dockerStartAllApps;
databaseOptionInsert "docker_type" $CFG_DOCKER_INSTALL_TYPE; databaseOptionInsert "docker_type" $CFG_DOCKER_INSTALL_TYPE;
@ -145,12 +145,15 @@ switchMigrateBackupApps()
return 0 return 0
fi fi
local subdirectories=($(find "$containers_dir" -mindepth 1 -maxdepth 1 -type d))
local saved_type="$CFG_DOCKER_INSTALL_TYPE" local saved_type="$CFG_DOCKER_INSTALL_TYPE"
CFG_DOCKER_INSTALL_TYPE="$old_mode" CFG_DOCKER_INSTALL_TYPE="$old_mode"
resolveDockerInstallUser resolveDockerInstallUser
# Enumerate under the OLD mode — containers/ is still owned by its container
# user here, so runFileOp (now resolved to that user) can list it (the
# manager can't list the 751 dockerinstall-owned dir under rootless).
local subdirectories=($(runFileOp find "$containers_dir" -mindepth 1 -maxdepth 1 -type d))
local failed=() local failed=()
local dir app_name local dir app_name
for dir in "${subdirectories[@]}"; do for dir in "${subdirectories[@]}"; do

View File

@ -2,27 +2,28 @@
dockerSwitcherUpdateContainersToDockerType() dockerSwitcherUpdateContainersToDockerType()
{ {
if [[ $CFG_DOCKER_INSTALL_TYPE == "rooted" ]]; then # Called mid-switch (new daemon up, BEFORE reconcileDockerOwnership), so
# Scannning the containers folder # containers/ is still owned by the OLD mode's container user. Enumerate as
local subdirectories=($(find "$containers_dir" -maxdepth 1 -type d)) # that user — containers/ isn't list-readable by the manager under rootless,
for dir in "${subdirectories[@]}"; do # and CFG is already the TARGET mode — by flipping CFG to old_mode just for
dockerSwitcherScanContainersForSocket "$dir" # the find, then restoring it so the per-app socket scan + restart below talk
if [[ $docker_socket_file_updated == "true" ]]; then # to the NEW daemon. (The two former rooted/rootless branches were identical.)
dockerRestartAppViaInstall $(basename $dir); local old_mode="$1"
fi
docker_socket_file_updated="false"
done
fi
if [[ $CFG_DOCKER_INSTALL_TYPE == "rootless" ]]; then local saved_type="$CFG_DOCKER_INSTALL_TYPE"
# Scannning the containers folder if [[ -n "$old_mode" ]]; then
local subdirectories=($(find "$containers_dir" -maxdepth 1 -type d)) CFG_DOCKER_INSTALL_TYPE="$old_mode"
for dir in "${subdirectories[@]}"; do resolveDockerInstallUser
dockerSwitcherScanContainersForSocket "$dir"
if [[ $docker_socket_file_updated == "true" ]]; then
dockerRestartAppViaInstall $(basename $dir);
fi
docker_socket_file_updated="false"
done
fi fi
local subdirectories=($(runFileOp find "$containers_dir" -maxdepth 1 -type d))
CFG_DOCKER_INSTALL_TYPE="$saved_type"
resolveDockerInstallUser
for dir in "${subdirectories[@]}"; do
dockerSwitcherScanContainersForSocket "$dir"
if [[ $docker_socket_file_updated == "true" ]]; then
dockerRestartAppViaInstall $(basename $dir);
fi
docker_socket_file_updated="false"
done
} }