Sync upstream and build images / sync-and-build (push) Successful in 1m45s
Verifying the pushed -r1 image found one hole: only dsh was wrapped, so a root 'docker exec <c> pnpm ...' created PNPM_HOME/XDG_CONFIG_HOME owned by root inside the state volume — which the unprivileged dsh could not then use for plugin installs (self-healing on the next restart, since the entrypoint re-chowns, but broken until then). The wrapper is now generic (execs the resolved target directly; dsh's bin.js is +x with a node shebang and pnpm's bin is an ELF, so no node prefix is needed) and is installed over dsh, pnpm, pnpx, pn and pnx. Renamed dsh-wrapper.sh -> run-as-runtime-user.sh to match what it does. Verified: root 'docker exec pnpm --version' + 'pnpm store path' + 'dsh plugin add' leave zero root-owned files in the volume; 23-case matrix still green. Ships as 0.1.1-rc.2-r2. Co-Authored-By: Claude Fable 5 <[email protected]>
24 lines
939 B
Bash
24 lines
939 B
Bash
#!/bin/sh
|
|
# Wrapper installed over the `dsh` and `pnpm`-family bins so that a ROOT
|
|
# invocation re-execs as the runtime user.
|
|
#
|
|
# The container starts as root (see docker-entrypoint.sh) to repair bind-mount
|
|
# ownership, which also makes `docker exec <container> …` default to root. Left
|
|
# alone, the documented plugin workflow would then drop root-owned files into
|
|
# the state volume — `dsh plugin … add` writes the profile, and pnpm writes
|
|
# PNPM_HOME / XDG_CONFIG_HOME — and the unprivileged dsh process could not read
|
|
# or replace them on its next start. Re-exec'ing as PUID:PGID keeps the volume
|
|
# consistent however these tools are invoked.
|
|
#
|
|
# Set DSH_ALLOW_ROOT=1 to bypass (diagnostics only).
|
|
set -eu
|
|
|
|
BIN=__TARGET__
|
|
|
|
if [ "$(id -u)" = 0 ] && [ "${DSH_ALLOW_ROOT:-0}" != 1 ]; then
|
|
exec setpriv --reuid "${PUID:-1000}" --regid "${PGID:-1000}" --init-groups \
|
|
env HOME=/home/node "$BIN" "$@"
|
|
fi
|
|
|
|
exec "$BIN" "$@"
|