fix: rootless containerd UID-remap fixes for /tmp/.cache and /home/leerie#85
Open
up_the_irons wants to merge 2 commits into
Open
fix: rootless containerd UID-remap fixes for /tmp/.cache and /home/leerie#85up_the_irons wants to merge 2 commits into
up_the_irons wants to merge 2 commits into
Conversation
Under rootless containerd, container-entry.sh's privilege drop (`unshare --user --map-user=$(id -u leerie)`) remaps only outer UID 0 to inner leerie. A directory explicitly chowned to leerie's own non-zero UID — as /tmp/.cache was, for mise's build-time cache — is not covered by that remap and appears owned by nobody to the privilege-dropped process: traversable via mode-755 "other" bits, but not writable. This silently broke any tool that tries to create its own subdir under XDG_CACHE_HOME (observed live for tree-sitter-language-pack's download-cache lock, following the corepack incident that motivated COREPACK_HOME's own dedicated cache dir). Chasing each offending tool down individually doesn't scale, so this makes /tmp/.cache itself world-writable with the sticky bit — the same posture /tmp itself already has — at both the Dockerfile (build time, the layer rootless relies on exclusively) and container-entry.sh (a runtime safety net for the rootful/Fly path). Verified live: the exact `unshare --user --map-user=...` mechanism reproduces the reported `mkdir: Permission denied` against the pre-fix image and succeeds against the fixed one, including the real tree_sitter_language_pack probe. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ootless Same bug class as the /tmp/.cache fix (c7b11fb), hit directly this time: pip install --user failing with EACCES: /home/leerie/.local/lib. Under rootless containerd, container-entry.sh's privilege drop (`unshare --user --map-user=$(id -u leerie)`) remaps only outer UID 0 to inner leerie. The Dockerfile chowned /home/leerie, .local, .cache, and .gnupg to leerie's own non-zero UID at build time — not covered by that remap, so they appeared owned by nobody to the privilege-dropped process: traversable, not writable. Unlike /tmp/.cache (an arbitrary-tool XDG_CACHE_HOME, fixed by making it world-writable), these are a fixed, known set of pre-created dirs, so the fix is more surgical: leave them root-owned at build time — outer UID 0 is the one value the remap does translate correctly, the same mechanism that already makes bind-mounted host dirs writable with no chown at all — and chown them to leerie at runtime in container-entry.sh's existing rootful- only guard instead, since the rootful `runuser -u leerie` drop is a real UID switch with no remap to rely on. Also adds /home/leerie/.local/bin to the image's PATH. Console scripts installed there via `pip install --user` (e.g. pre-commit) otherwise have no fallback path when a git hook's embedded interpreter path doesn't resolve to a Python that has the package installed (e.g. a host-side commit against a hook generated inside the container, or vice versa). tests/test_home_leerie_ownership.py pins both sides source-coupled (mirroring test_tmp_cache_writable.py), including a guard that the /tmp/.cache fix is unaffected. Docs updated: IMPLEMENTATION.md's container-entry.sh row and the two Selenium-cache mentions that previously described the old chown-at-build-time behavior. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
up_the_irons
force-pushed
the
fix-rootless-home-leerie-ownership
branch
from
July 19, 2026 11:29
26f0e86 to
1e80898
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two fixes for the same root cause, bundled together since the second
directly builds on the first's code and docs:
1.
/tmp/.cacheworld-writable (cherry-picked from arpnetworks/leerie, not yet upstream)container-entry.sh's privilege drop (unshare --user --map-user=$(id -u leerie)) remaps only outer UID 0 to inner leerie./tmp/.cachewas chowned to leerie's own non-zero UID, which isn't covered by that remap — broke corepack andtree-sitter-language-pack's download cache withEACCES./tmp/.cacheworld-writable with the sticky bit (mirroring/tmp's owndrwxrwxrwt), at both the Dockerfile andcontainer-entry.sh's rootful-path runtime safety net.2.
/home/leerie/.local,.cache,.gnupgownership (new)pip install --userfailing withEACCES: /home/leerie/.local/lib./tmp/.cache(an arbitrary-toolXDG_CACHE_HOME), these are a fixed, known set of pre-created dirs, so the fix is more surgical: leave them root-owned at build time (outer UID 0 is the one value the remap does translate correctly — the same mechanism that already makes bind-mounted host dirs writable with no chown), and chown them to leerie at runtime incontainer-entry.sh's existing rootful-only guard instead./home/leerie/.local/binto the image'sPATH, sopip install --user-installed console scripts (e.g.pre-commit) have a working fallback when a git hook's embedded interpreter path doesn't resolve to a Python that has the package installed.Test plan
tests/test_tmp_cache_writable.pyandtests/test_home_leerie_ownership.py— source-coupling tests pinning both Dockerfile andcontainer-entry.shsides.pytest tests/passes..leerie-setup.shdoingpip install --break-system-packages --user pre-commitfailed withEACCESon the pre-fix image and succeeded after rebuilding with this fix.docs/IMPLEMENTATION.mdandCLAUDE.mdupdated for both fixes.🤖 Generated with Claude Code