From 22eb4d13f73de232cd2d7d0841125148d7ad18f2 Mon Sep 17 00:00:00 2001 From: Ben Date: Wed, 27 May 2026 15:17:00 +1000 Subject: [PATCH] fix(docker): chown ui-tui and node_modules on UID remap so TUI esbuild works (#28851) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When HERMES_UID remaps the hermes user from 10000 to another UID (e.g. matching the host user's UID for bind-mount ergonomics), the TUI launcher's esbuild step fails: ✘ [ERROR] Failed to write to output file: open /opt/hermes/ui-tui/dist/entry.js: permission denied TUI build failed. This is because the Dockerfile's build-time `chown -R hermes:hermes` on `/opt/hermes/{.venv,ui-tui,node_modules}` (line 154) wrote UID 10000, and stage2-hook.sh only re-chowned `.venv` on UID remap — leaving the TUI build trees still owned by the old UID. Extend the stage2 re-chown to include the same set as the build-time chown: `.venv`, `ui-tui`, `node_modules`. These are the runtime-writable trees under $INSTALL_DIR; everything else under /opt/hermes is read-only at runtime so keeping it root-owned is fine. Original fix targeted docker/entrypoint.sh which is now a deprecated shim; retargeted to docker/stage2-hook.sh where the .venv chown moved during the s6-overlay rework. Co-authored-by: Andreas Steffan <623481+deas@users.noreply.github.com> --- docker/stage2-hook.sh | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/docker/stage2-hook.sh b/docker/stage2-hook.sh index 510acf54319..131c76f77da 100755 --- a/docker/stage2-hook.sh +++ b/docker/stage2-hook.sh @@ -68,12 +68,26 @@ if [ "$needs_chown" = true ]; then echo "[stage2] Warning: chown $HERMES_HOME/$sub failed (rootless container?) — continuing" fi done - # The .venv must also be re-chowned when UID is remapped, otherwise - # lazy_deps.py cannot install platform packages (discord.py, etc.). - # This is under $INSTALL_DIR, not $HERMES_HOME, so the bind-mount + # Hermes-owned trees under $INSTALL_DIR must be re-chowned when the UID + # is remapped — otherwise: + # - .venv: lazy_deps.py cannot install platform packages (discord.py, + # telegram, slack, etc.) with EACCES (#15012, #21100) + # - ui-tui: esbuild rebuilds dist/entry.js on every TUI launch (when + # the source mtime is newer than dist/ or when HERMES_TUI_FORCE_BUILD + # is set) and writes to ui-tui/dist/. Without this chown the new + # hermes UID can't write the build output (#28851). + # - node_modules: root-level dependencies (puppeteer, web tooling) + # that runtime code may walk/update. + # The set mirrors the build-time `chown -R hermes:hermes` line in the + # Dockerfile — keep them in sync if the Dockerfile chown set changes. + # These are under $INSTALL_DIR (not $HERMES_HOME), so the bind-mount # concern doesn't apply — recursive is fine. - chown -R hermes:hermes "$INSTALL_DIR/.venv" 2>/dev/null || \ - echo "[stage2] Warning: chown .venv failed (rootless container?) — continuing" + chown -R hermes:hermes \ + "$INSTALL_DIR/.venv" \ + "$INSTALL_DIR/ui-tui" \ + "$INSTALL_DIR/node_modules" \ + 2>/dev/null || \ + echo "[stage2] Warning: chown of build trees failed (rootless container?) — continuing" fi # Always reset ownership of $HERMES_HOME/profiles to hermes on every