Configuring Rootless Podman with UID Mapping for Secure Containers
Rootless Podman uses user namespaces and /etc/subuid mappings to run containers without host root. Learn how to configure subuid ranges, map your host UID with keep-id, and avoid common pitfalls.
30 Dec 2025, 12:23 UTC

If a container process escapes its sandbox while running as root, the attacker lands on the host as root. Podman's rootless mode removes that risk by running the entire container stack as an unprivileged user, using Linux user namespaces to fake root inside the container while the host sees only an ordinary user process. The useful takeaway: rootless mode works out of the box on most distributions, but correct UID mapping via /etc/subuid and /etc/subgid is what determines whether file ownership and in-container users behave the way you expect.
How User Namespaces Map Container UIDs
A user namespace creates a private view of user and group IDs. Inside the container, a process can run as UID 0 (root), but the kernel translates that to an unprivileged UID on the host. Any file the container creates on a mounted volume is owned by that host UID, not by real root.
Because a container often needs more than one internal identity (for example, a web server user and a database user), Podman needs a range of host UIDs to draw from. That range is assigned per user in two files:
/etc/subuid— host UID ranges a user may map into containers/etc/subgid— the same for group IDs
Each line has the format username:start_uid:count. A typical entry looks like devuser:100000:65536, meaning devuser controls 65,536 host UIDs beginning at 100000. Container UID 0 maps to 100000, container UID 1 to 100001, and so on.
Assigning a SubUID Range
Most distributions create these entries automatically when a user account is added. If yours did not, assign a range as root:
# Run on the host as root
sudo usermod --add-subuid 100000-165535 --add-subgid 100000-165535 devuserVerify the assignment:
# Run as any user; no special privileges needed
cat /etc/subuid
cat /etc/subgidYou should see one line per user with a non-overlapping range. If you edit these files by hand, run podman system migrate as the affected user afterward so Podman picks up the new mapping; skipping this step is a common cause of stale-mapping errors.
Worked Example: Keeping the Host UID Inside the Container
The most frequent rootless headache is volume permissions: the container writes files as a mapped UID like 100000, and the host user cannot read them. The --userns=keep-id flag solves this by mapping your own host UID to the same UID inside the container.
# Run as the unprivileged user (e.g., devuser, UID 1000)
podman run --rm --userns=keep-id -v $HOME/data:/data:Z alpine idExpected output resembles:
uid=1000 gid=1000Files written to /data inside the container are then owned by devuser on the host, so no permission fix-ups are needed. The :Z suffix relabels the volume for SELinux; omit it on systems without SELinux. Do not run this against your entire home directory — relabeling changes file contexts recursively.
To confirm the default mapping without keep-id, run:
podman run --rm alpine idThis shows uid=0(root) inside the container, while on the host the process runs as your unprivileged user — the core of the rootless security model.
Limits and Common Mistakes
- Privileged ports: Rootless containers cannot bind ports below 1024 by default. Either map a high host port (
-p 8080:80) or lower the threshold withsudo sysctl net.ipv4.ip_unprivileged_port_start=80(persist it in/etc/sysctl.d/). - Networking overhead: Rootless networking uses slirp4netns (or pasta on newer Podman versions), a userspace network stack. Throughput-heavy workloads see measurably lower performance than bridged rootful networking. Benchmark before committing latency-sensitive services to rootless mode.
- Restricted operations: Mounting certain filesystems, using device nodes, and some
mknodoperations fail rootlessly because the host kernel denies them to unprivileged users. Images requiring these will not work without rootful Podman. - Missing subuid entries: The error
there might not be enough IDs available in the namespacealmost always means/etc/subuidlacks an entry for the user, orpodman system migratewas not run after editing. - Lingering containers and logout: Rootless containers tied to a user session can stop when the user logs out. Enable lingering with
sudo loginctl enable-linger devuserfor long-running services.
Verifying the Setup
Three quick checks confirm a working rootless configuration:
podman info --format '{{.Host.Security.Rootless}}'should printtrue.podman run --rm alpine cat /proc/self/uid_mapshows the actual mapping table; the second column should align with your subuid start (e.g., 100000).- From inside a container,
curl -sI https://example.comconfirms the userspace network stack reaches external endpoints.
These checks assume Podman 4.x or later on a mainstream Linux distribution; flag names and defaults (such as pasta replacing slirp4netns) vary by version, so confirm against podman version on your host.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.