From 4c8bcf0580fb281a6484ef2a1a29b8aae72b3432 Mon Sep 17 00:00:00 2001 From: librelad Date: Sun, 24 May 2026 14:13:15 +0100 Subject: [PATCH] fix(rootless): don't stamp the deployed WebUI tree with the repo-clone uid MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dockerCopyBuildContext rsync'd the install template into the container dir with -a, which preserves owner/group — so the deployed WebUI tree (frontend/ included) inherited the repo clone's owner (the human user, uid ~1000) on every install. The trailing chown used the $docker_install_user global, which is stale/empty in this context, so it silently no-op'd and uid 1000 survived (visible as frontend/ owned by 1000 with the template's mtime). Add --no-owner --no-group so the copy doesn't carry source ownership, and chown via the config-authoritative dockerContainerOwner (rooted -> manager, rootless -> docker install user) through runSystem. The deployed tree now lands owned by the mode's container owner. Co-Authored-By: Claude Opus 4.7 Signed-off-by: librelad --- scripts/docker/compose/copy_build_context.sh | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/scripts/docker/compose/copy_build_context.sh b/scripts/docker/compose/copy_build_context.sh index c31153b..0ef1380 100644 --- a/scripts/docker/compose/copy_build_context.sh +++ b/scripts/docker/compose/copy_build_context.sh @@ -36,8 +36,12 @@ dockerCopyBuildContext() # Use rsync if available so re-installs only diff what changed; fall # back to cp -R for systems without rsync. Either way we exclude the # files that have their own copy lifecycle. + # --no-owner --no-group: don't carry the install template's ownership (the + # repo clone is owned by the human user, uid ~1000) onto the deployed + # container dir — the chown below sets the correct owner. Without this the + # rsync re-stamps the WebUI tree as uid 1000 every install. if command -v rsync >/dev/null 2>&1; then - sudo rsync -a \ + sudo rsync -a --no-owner --no-group \ --exclude="docker-compose.yml" \ --exclude="docker-compose.${app_name}.yml" \ --exclude="${app_name}.config" \ @@ -52,6 +56,11 @@ dockerCopyBuildContext() sudo rm -f "$target_dir/${app_name}.config" "$target_dir/${app_name}.tools.json" fi - sudo chown -R "$docker_install_user:$docker_install_user" "$target_dir" + # Own the deployed tree as the mode's container owner (config-authoritative, + # never the stale/empty $docker_install_user global that let uid 1000 slip + # through before). + local owner + owner="$(dockerContainerOwner)" + runSystem chown -R "$owner:$owner" "$target_dir" isSuccessful "Build context copied for $app_name." }