From 1ff12d6643156499d1e2e0a5af1e0d5220a8bd05 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 21 Aug 2026 04:05:27 +0000 Subject: [PATCH] ai-stack: chown the stack dir back to ACTUAL_USER after every installer run MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit local-ai-setup.sh runs as whoever invoked this wrapper — root, since setup.sh itself runs under sudo — so every file it generates (docker-compose.yml, .env, requirements.txt, server.py, mcp_server.py, pull-models.sh, start/stop/status.sh) came out root-owned. Nothing handed that back to ACTUAL_USER unconditionally: the only existing ensure_docker_dir_ownership call was inside the cloud-provider wiring block, so it silently never ran at all for anyone who skipped cloud providers. Confirmed live: this repo's own "Skipped. Run later: cd $AS_DIR && bash local-ai-setup.sh" message tells the user to re-run it directly later as themselves (no sudo) — which then fails with "Permission denied" on any file root created during the original sudo run, e.g. requirements.txt. Same root cause class as a stray root-owned .git/FETCH_HEAD blocking a plain `git pull` — a root-run leaving files a later unprivileged run can't touch. Fix: call ensure_docker_dir_ownership "$AS_DIR" unconditionally right after the installer-run block, not only on the cloud-provider path. --- services/ai-stack.sh | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/services/ai-stack.sh b/services/ai-stack.sh index b3c4821..13e8f0b 100644 --- a/services/ai-stack.sh +++ b/services/ai-stack.sh @@ -124,6 +124,17 @@ install_ai-stack() { log_info "Skipped. Run later: cd $AS_DIR && bash local-ai-setup.sh" fi + # local-ai-setup.sh runs as whoever invoked this wrapper — root, since + # setup.sh itself is run via sudo — so everything it just generated + # (docker-compose.yml, .env, requirements.txt, server.py, pull-models.sh, + # etc.) comes out root-owned. Hand it back to ACTUAL_USER unconditionally, + # not just on the cloud-provider path below. Confirmed live: without this, + # re-running local-ai-setup.sh directly later (the update path, plain user, + # no sudo — exactly what its own "run later" message above tells you to do) + # fails with "Permission denied" on any file the first root-run created, + # e.g. requirements.txt. + ensure_docker_dir_ownership "$AS_DIR" + # ── Wire cloud providers into the generated compose ─────────────────────── if [ ${#CLOUD_NAMES[@]} -gt 0 ] && [ -f "$AS_DIR/docker-compose.yml" ]; then # Prepend the local RAG connection so RAG keeps working, then the clouds.