container-nesting
| Version | 2026.185.1940 |
| Repo | superproject |
Rootless nested podman/buildah/skopeo inside a rootless outer container – zero added capabilities, no –privileged.
Ports quay.io/podman/stable’s canonical rootless-in-rootless configuration
into the candy system. Installs podman + crun + buildah + skopeo +
fuse-overlayfs, writes containers.conf with every namespace=host (the
userns=host line is what bypasses the kernel mount_too_revealing /proc
check), a two-range subuid layout that fits the keep-id window,
newuidmap/newgidmap file caps, policy.json and storage.conf – so an inner
podman run of a fresh container succeeds with no cap_add and no
–privileged. Every artifact below is observable in the built image; the
end-to-end nested run is provable on a live deployment.
Packages
Section titled “Packages”Installed on every distro:
buildahfuse-overlayfsskopeo
Acceptance plan
Section titled “Acceptance plan”This candy’s plan: — the runnable spec charly check executes against a live deployment. check: steps are idempotent probes; run: steps change state.
| Intent | Step |
|---|---|
run |
command=touch /etc/subuid /etc/subgid sed -i “/^root:/d” /etc/subuid /etc/subgid echo “root:1:65535” >> /etc/subuid echo “root:1:65535” >> /etc/subgid uid1000=$(getent passwd 1000 2>/dev/null | cut -d: -f1 || true) if [ -n “${uid1000}” ] && [ “${uid1000}” != “root” ]; then sed -i “/^${uid1000}:/d” /etc/subuid /etc/subgid { echo “${uid1000}:1:999” echo “${uid1000}:1001:64535” } >> /etc/subuid { echo “${uid1000}:1:999” echo “${uid1000}:1001:64535” } >> /etc/subgid fi |
run |
grant cap_setuid/cap_setgid to newuidmap/newgidmap AND strip the setuid-root bit. Debian/Ubuntu’s uidmap package ships these binaries setuid-root (mode 4755); a newuidmap that is BOTH setuid-root AND file-capability’d fails inside a nested rootless user namespace with “newuidmap: open of uid_map failed: Permission denied”. Fedora/Arch ship them cap-only (no setuid bit), so chmod u-s makes every distro match that working posture and is a no-op where the bit is already absent. RDD-confirmed 2026-06-16. |
run |
mkdir=/etc/containers |
run |
mkdir=${HOME}/.config/containers |
run |
write=/etc/containers/containers.conf |
run |
write=${HOME}/.config/containers/containers.conf |
run |
write=/etc/containers/policy.json |
run |
write=${HOME}/.config/containers/policy.json |
run |
write=/etc/containers/storage.conf |
run |
write=${HOME}/.config/containers/storage.conf |
check |
the podman container engine is installed for in-container use |
check |
the buildah image-build tool is installed |
check |
the skopeo image-copy tool is installed |
check |
containers.conf pins userns=host so the inner /proc mount is not rejected by the kernel mount_too_revealing check |
check |
policy.json is present so podman pull/run accepts an image signature policy |
check |
newuidmap carries the cap_setuid file capability so a nested user namespace can be delegated |
check |
newuidmap is NOT setuid-root — only the cap_setuid file capability remains; a binary that is BOTH setuid-root (Debian/Ubuntu’s uidmap default) AND cap-bearing fails to write uid_map inside a nested rootless user namespace |
check |
/etc/subuid declares the username:start:count delegation ranges the inner podman maps from |
agent-check |
a fresh rootless podman run of an inner container succeeds end-to-end with no added capabilities and no –privileged |
check |
command=/usr/bin/podman –version |
check |
command=/usr/bin/buildah –version |
check |
command=/usr/bin/skopeo –version |
check |
file=/usr/bin/newuidmap |
check |
file=/usr/bin/newgidmap |
check |
file=/usr/bin/tailscale |
check |
command=/usr/bin/tailscale version |
check |
the uid-1000 user has exactly two subuid delegation ranges (cross-distro — the user is user on fedora/arch but ubuntu/debian under adopt user-policy, so resolve the name via getent rather than hardcoding user:) |
check |
command=grep -E ‘^userns\s*=\s*“host”’ ${HOME}/.config/containers/containers.conf |
check |
command=sh -c ‘env | grep -q “^_CONTAINERS_USERNS_CONFIGURED=”’ |
check |
command=sh -c ‘env | grep -qx “BUILDAH_ISOLATION=chroot”’ |
check |
command=podman run –rm quay.io/libpod/alpine:latest /bin/true |