Fix rootless Podman lchown EINVAL by ensuring uidmap and fresh service
Two root causes for "invalid argument" when chowning non-root UIDs/GIDs in image layers: 1. Missing uidmap package: without setuid newuidmap/newgidmap binaries, Podman can only map a single UID (0 → current user) in the user namespace. Any layer file owned by gid=42 (shadow) or similar then has no mapping and lchown returns EINVAL. Now install uidmap if absent. 2. Stale Podman service: a service started before subuid/subgid entries existed silently keeps the single-UID mapping for its lifetime even after the entries are added and podman system migrate is run. Now always kill and restart the service on each start.sh run so it always reads the current subuid/subgid configuration. https://claude.ai/code/session_01FKCW3FDjNFj6jve4niMFXH
This commit is contained in:
parent
b64195c58a
commit
b5e6c8fcd3
1 changed files with 29 additions and 10 deletions
|
|
@ -59,6 +59,16 @@ EOF
|
|||
|
||||
echo "[hiy] Generated proxy/caddy.json for ${DOMAIN_SUFFIX}"
|
||||
|
||||
# ── Ensure newuidmap/newgidmap setuid binaries are present ────────────────────
|
||||
# These binaries (from the 'uidmap' package) allow rootless Podman to map a
|
||||
# full range of UIDs/GIDs in user namespaces. Without them Podman can only
|
||||
# map UID 0 → the calling user and any layer file owned by a non-zero UID/GID
|
||||
# (e.g. gid=42 for /etc/shadow) will cause an "invalid argument" lchown error.
|
||||
if ! command -v newuidmap &>/dev/null; then
|
||||
echo "[hiy] Installing uidmap (provides newuidmap/newgidmap)…"
|
||||
sudo apt-get install -y uidmap
|
||||
fi
|
||||
|
||||
# ── Ensure subuid/subgid entries exist for rootless Podman ────────────────────
|
||||
# Rootless Podman maps UIDs/GIDs inside containers using subordinate ID ranges
|
||||
# from /etc/subuid and /etc/subgid. Without a sufficient range, pulling or
|
||||
|
|
@ -72,7 +82,7 @@ fi
|
|||
if ! grep -q "^${_HIY_USER}:" /etc/subgid 2>/dev/null; then
|
||||
echo "${_HIY_USER}:100000:65536" | sudo tee -a /etc/subgid > /dev/null
|
||||
fi
|
||||
# Always migrate so Podman storage reflects the current subuid/subgid mappings.
|
||||
# Migrate storage so Podman picks up the current subuid/subgid mappings.
|
||||
podman system migrate
|
||||
|
||||
# ── Allow rootless processes to bind ports 80/443 ─────────────────────────────
|
||||
|
|
@ -102,16 +112,25 @@ export XDG_RUNTIME_DIR="$_HIY_XDG"
|
|||
PODMAN_SOCK="${_HIY_XDG}/podman.sock"
|
||||
export PODMAN_SOCK
|
||||
export DOCKER_HOST="unix://${PODMAN_SOCK}"
|
||||
if [ ! -S "$PODMAN_SOCK" ]; then
|
||||
echo "[hiy] Starting Podman socket via podman system service…"
|
||||
podman system service --time=0 "unix://${PODMAN_SOCK}" &
|
||||
# Wait up to 5 s for the socket to appear
|
||||
for i in 1 2 3 4 5; do
|
||||
|
||||
# Always (re)start the Podman socket service so it reflects the current
|
||||
# subuid/subgid configuration. A stale service started before the entries
|
||||
# existed will silently fall back to single-UID mapping and cause lchown
|
||||
# failures when extracting image layers that contain non-root UIDs/GIDs.
|
||||
if [ -S "$PODMAN_SOCK" ]; then
|
||||
echo "[hiy] Restarting Podman socket service (refreshing user namespace config)…"
|
||||
pkill -f "podman system service.*${PODMAN_SOCK}" 2>/dev/null || true
|
||||
# Give the process a moment to exit and release the socket.
|
||||
sleep 1
|
||||
rm -f "$PODMAN_SOCK"
|
||||
fi
|
||||
echo "[hiy] Starting Podman socket via podman system service…"
|
||||
podman system service --time=0 "unix://${PODMAN_SOCK}" &
|
||||
for i in 1 2 3 4 5; do
|
||||
[ -S "$PODMAN_SOCK" ] && break
|
||||
sleep 1
|
||||
done
|
||||
[ -S "$PODMAN_SOCK" ] || { echo "ERROR: Podman socket did not appear"; exit 1; }
|
||||
fi
|
||||
done
|
||||
[ -S "$PODMAN_SOCK" ] || { echo "ERROR: Podman socket did not appear"; exit 1; }
|
||||
|
||||
# ── Build images ───────────────────────────────────────────────────────────────
|
||||
make -C "$SCRIPT_DIR" build
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue