Files
windmill/docker
Ruben Fiszel dcb9e40ea2 fix(extra): make the extra container runnable as a non-root UID (#10173)
* fix(extra): make extra container runnable as a non-root UID

The root-run installs in DockerfileExtra inherit UV_CACHE_DIR
(/tmp/windmill/cache/uv) and XDG_CACHE_HOME (/pyls/.cache) from the base
image and write to them *after* the base image's world-writable pass,
leaving ~320 root-owned 0755 dirs. A non-root UID then fails to debug:

  uv venv failed: Failed to write to the client cache
  Caused by: Permission denied (os error 13)
    at path "/tmp/windmill/cache/uv/simple-v21/pypi/.tmpWxWzTi"

Re-apply the base image's world-writable convention after the installs,
and add the windmill UID/GID 1000 account the app image already has so
runAsUser: 1000 resolves to a real user with a writable $HOME. The
entrypoint also wrote $NETRC to the 0700 /root under `set -e`, killing
the container at startup; redirect $HOME when it is not writable.

Verified against the published image as root, uid 1000, and uid 4567:0:
all four services start and `windmill prepare-deps` succeeds in each.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(extra): scope the HOME fallback per-UID and cover non-root in CI

Review findings on the previous commit:

- `${HOME:-/root}` was used in the writability test but not the assignment,
  so an unset HOME (writable /root, redirect skipped) silently wrote the
  netrc to `/.netrc` instead of `/root/.netrc`. Normalize HOME once.
- `mkdir -p` succeeds on a dir owned by another UID, so a root-created
  /tmp/windmill-home on a shared /tmp reintroduced the startup death this
  fix exists to prevent. Scope the fallback to /tmp/windmill-home-$(id -u).
- The extra image's smoke test only ran as root, so nothing exercised the
  non-root path this PR is about. Add a --user 1000 run of the same suite
  plus a prepare-deps assertion, which is where the EACCES surfaced.

Also correct the DockerfileExtra comment: the proven requirement is the uv
cache, not runtime writes by gopls.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(extra): keep /tmp/monaco code read-only for non-root UIDs

Review nit: /tmp/monaco holds node_modules (code, not cache), so it is not
covered by the base image's world-writable cache convention. Give it a+rX
files with 777 dirs -- enough for the go.mod / ruff.toml the entrypoint and
pyls_launcher write into it -- instead of a+rw on every file.

/tmp/windmill and /pyls/.cache keep a+rw: that is the base convention for
caches (DockerfileSlimEe:69 chmod -R a+rw /tmp/windmill/cache; Dockerfile:339
"cache files already have 666"), and uv rewrites cache entries in place.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore(extra): drop the non-root CI smoke test

Reverts publish_extra.yml to its root-only smoke test; the DockerfileExtra
and entrypoint fix is unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 15:44:57 +02:00
..
2023-05-30 21:05:59 +02:00