Podman Rootless Container Execution: An Architecture Note
An architecture note on Podman's rootless mode: what it requires, the minimal design, trust boundaries, operational checks, failure modes, and when to redesign.
05 Jul 2026, 17:57 UTC

Requirements
Podman's rootless mode lets an unprivileged user run containers by creating a user namespace and mapping container IDs to non-root host IDs. It depends on a small set of kernel and system components:
- A kernel built with
CONFIG_USER_NS=y(common since Linux 3.8; 4.x or newer recommended for reliablemax_user_namespaceshandling). - The set-uid root binaries
newuidmapandnewgidmap, which safely assign subordinate ID ranges. - Per-user entries in
/etc/subuidand/etc/subgidproviding at least one contiguous ID range (commonly 65536 IDs). - The
slirp4netnshelper for unprivileged networking. - A storage driver that works without root:
fuse-overlayfs(preferred) withvfsas a fallback.
The Smallest Suitable Design
Each container runs inside a user namespace owned by the invoking user. There is no daemon; the Podman client directly invokes conmon and an OCI runtime (crun or runc) inside that namespace.
- UID 0 inside the container maps to a non-root host UID drawn from the user's
/etc/subuidentry; GID 0 maps the same way via/etc/subgid. - Networking is handled by
slirp4netns, a user-space TCP/IP stack attached to the container's network namespace, so no privilegedCAP_NET_ADMINis needed. - Storage uses
fuse-overlayfs, a FUSE filesystem that provides copy-on-write image layers without privileged mount calls. If FUSE is unavailable, Podman falls back tovfs, which copies full layers and is noticeably slower.
Trust and Data Boundaries
The primary trust boundary is the user-namespace ID mapping:
- A process inside the container can only use UIDs/GIDs within the mapped range. Attempts to act as an unmapped host UID fail with
EPERM, so a container "root" cannot modify files owned by real host root. - Filesystem access is limited to explicitly bind-mounted volumes (
--volume) and temporary storage owned by the invoking user (for example under$XDG_RUNTIME_DIR). - Host devices that need privileged capabilities (such as
/dev/kvmor GPU nodes) stay inaccessible unless passed with--deviceand permitted by cgroup rules; even then, the user namespace can block ioctls that require capabilities against the host.
Operational Checks
Run these as the unprivileged user (no sudo) before relying on rootless workloads:
- Subordinate IDs exist:
grep ^$(whoami): /etc/subuid /etc/subgid # expected: username:100000:65536 (one line per file) - Set-uid helpers are correct:
ls -l $(which newuidmap newgidmap) # expected: -rwsr-xr-x 1 root root ...If the set-uid bit is missing, ID mapping fails; fixing it requires root (
chmod u+s), which is the one privileged step in this setup. - Network helper works:
slirp4netns --version - Rootless mode and storage driver confirmed:
podman info --format '{{.Host.Security.Rootless}} {{.Store.GraphDriverName}}' # expected: true overlay (fuse-overlayfs reports as overlay) - End-to-end mapping test:
podman run --rm docker.io/library/alpine id # inside the container: uid=0(root) gid=0(root)On the host, that container process appears as the user's subordinate UID (for example 100000), which you can confirm with
ps -o user= -C conmonor by inspecting/proc/<pid>/uid_mapwhile the container runs.
Failure Modes
- User-namespace creation denied: startup errors such as
operation not permittedwhen creating a namespace, caused by missingCONFIG_USER_NS, a restrictive sysctl, or exhaustion of/proc/sys/user/max_user_namespacesunder high concurrency. Raising that sysctl (root required) is the usual fix. - Missing or malformed subuid/subgid: Podman refuses to start because it cannot map IDs. Add the entries with
usermod --add-subuids/--add-subgids(root required). - slirp4netns failure: the container may start without working networking. Check
podman logsand the container's inspect output; on newer Podman versionspastais an alternative unprivileged network backend. - Storage fallback to vfs: image pulls and builds slow down sharply because layers are fully copied. Confirm the driver with
podman infoand installfuse-overlayfsif you seevfs. - SELinux/AppArmor denials: confined policies can block user-namespace operations or FUSE mounts; denials appear in the audit log (
ausearch -m avc -ts recent) and require policy adjustment rather than Podman changes.
Conditions That Would Change the Design
- If the kernel lacks user namespaces or policy forbids them, rootless mode is impossible; the alternatives are rootful Podman or a VM-based isolation layer.
- If FUSE is prohibited on a hardened host, storage must move to
vfs(accepting the performance cost) or to a rootful overlayfs setup. - Workloads that genuinely need host devices (KVM, GPUs) or binding to ports below 1024 may outgrow rootless mode; low ports can sometimes be allowed by raising
net.ipv4.ip_unprivileged_port_start, but device access often pushes the design toward rootful containers or dedicated VMs. - Future kernel features such as unprivileged virtio-fs or broader eBPF access inside user namespaces could replace
fuse-overlayfsandslirp4netns, improving performance without changing the trust model.
Version note: behavior described here reflects Podman 4.x/5.x on mainstream Linux distributions. Verify specifics against your installed version with podman version and podman info, since defaults such as the network backend have changed across releases.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.