| Tested on | Red Hat Enterprise Linux 10.2 (Coughlan) |
|---|---|
| Package | podman-5.8.2-5.el10_2.x86_64 |
| Applies to | Any Linux host with Podman installed |
| Privilege | Rootless examples as podtest; rootful examples with sudo podman |
| Scope | Capability comparison between rootless and rootful Podman — privilege model, storage separation, networking defaults, ports, devices, checkpoint, NFS graphroot nuance, cgroups, and workload selection. Does not cover rootless installation, subuid setup, privileged-port fixes, UID mapping depth, or volume permission troubleshooting. |
Choosing rootless or rootful Podman is a workload decision, not a moral score. Rootless caps what a container can do on the host; rootful unlocks operations that require real root privileges. This guide compares what changes between the two modes so you can pick the right default before diving into setup or networking articles.
The lab user is podtest for rootless examples. Rootful commands use sudo podman on the same host.
Rootless vs rootful Podman: quick comparison
| Capability | Rootless | Rootful |
|---|---|---|
| Podman process UID | normal user | root |
| User namespace | always involved | optional |
| Container root = host root | No | potentially yes depending on namespace |
| Local storage | user-specific | system/root storage |
| Default network | pasta | bridge |
| Bind host port <1024 | blocked by default | Yes |
| Create device nodes | No | Yes with required privileges |
| CRIU checkpoint/restore | No | Yes when requirements are met |
| Physical macvlan/ipvlan parent | not a normal rootless path | Yes |
| System-wide network/firewall control | limited | Yes |
| Containers visible across mode | No | No; separate stores |
| NFS-backed default graphroot | unsupported | different rootful constraints |
| Everyday container workloads | usually Yes | Yes |
Rootless reduces available privilege; rootful expands it. Neither mode removes the need for sane mounts, image trust, and kernel patching.
What does rootless Podman actually mean?
Rootless Podman runs the podman command as a normal Linux user. Inside the rootless user namespace:
container UID 0
↓
normal host user's UIDContainer root does not gain host-root capabilities.
Run a container and read IDs inside it:
podman run --rm docker.io/library/alpine:3.20 iduid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),20(dialout),26(tape),27(video)Compare with the host account and the unshare view:
iduid=1014(podtest) gid=1015(podtest) groups=1015(podtest) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023Inside Podman's user namespace the same account appears as root:
podman unshare iduid=0(root) gid=0(root) groups=0(root) context=unconfined_u:unconfined_r:container_runtime_t:s0-s0:c0.c1023uid=0(root) inside the container is namespace-local. On the host you remain podtest. Subuid setup and troubleshooting belong in Rootless Podman.
What does rootful Podman mean?
Rootful Podman runs the CLI with host root privileges. Confirm the mode:
sudo podman info --format '{{.Host.Security.Rootless}}'rootless=falseRootful Podman:
- stores containers in the system graph root
- can configure bridges, firewall rules, and physical-interface network drivers directly
- still respects OCI and container configuration — rootful does not automatically mean every container is
--privileged
A rootful container is not automatically an unrestricted host-root process unless you configure it that way.
Rootless and rootful Podman use separate storage
Rootless and rootful Podman use separate container and image stores. Rootless Podman can also apply per-user configuration on top of system configuration, so sudo podman does not simply elevate or manage the same container state.
Images and containers created in one mode do not appear in the other.
List images as the rootless user:
podman images --format '{{.Repository}}:{{.Tag}}' | head -3docker.io/library/alpine:3.20
quay.io/podman/hello:latestList images as root:
sudo podman images --format '{{.Repository}}:{{.Tag}}' | head -3localhost/copyup-demo:v1
localhost/demo-from-remote:v1
localhost/demo-empty:v1The stores are different. Start a rootless container named web-rootless:
podman run -d --name web-rootless docker.io/library/alpine:3.20 sleep 300It appears in the user's process list:
podman ps --format '{{.Names}}'web-rootlessRootful podman ps does not list it — the container lives only in the user's storage.
Read configured graph roots:
podman info --format 'graphRoot={{.Store.GraphRoot}}'graphRoot=/home/podtest/.local/share/containers/storageRootful storage lives under the system path instead:
sudo podman info --format 'graphRoot={{.Store.GraphRoot}}'graphRoot=/var/lib/containers/storageSwitching to sudo does not let you manage rootless containers. Export images or recreate workloads in the target context.
Remove the lab container when finished:
podman rm -f web-rootlessRootless and rootful networking differences
Networking defaults differ because rootless users cannot configure host networking the same way root can.
| Mode | Default stack | Notes |
|---|---|---|
| Rootless | pasta | User-defined Netavark bridges also available |
| Rootful | bridge (podman0) |
Netavark can configure host firewall rules directly |
Rootful is required for workflows that attach directly to host physical interfaces through normal macvlan or ipvlan parent setups. Pasta behavior, bridge port forwarding, and source-IP trade-offs belong in Rootless Podman networking and Podman networking modes.
Can rootless Podman use ports 80 and 443?
Linux normally reserves host ports below 1024 for privileged processes. A rootless publish to port 80 fails on the lab host:
podman run --rm -p 80:80 docker.io/library/alpine:3.20 echo okError: pasta failed with exit code 1:
Failed to bind port 80 (Permission denied) for option '-t 80-80:80-80'Rootful Podman can bind those ports without changing net.ipv4.ip_unprivileged_port_start. Sysctl tuning, reverse proxies, and firewall redirects belong in Rootless Podman privileged ports.
--privileged does not turn rootless Podman into host root
--privileged removes many engine-imposed restrictions, but it cannot grant host capabilities the user lacks.
Try creating a device node inside a rootless privileged container:
podman run --rm --privileged docker.io/library/alpine:3.20 mknod /tmp/testdev c 1 3mknod: /tmp/testdev: Operation not permittedThe same command inside rootful Podman succeeds silently — mknod can create the node when the host process runs as root.
--privileged rootless is not host root. It only relaxes limits within the user's privilege ceiling.
Rootless device limitations
Rootless Podman can pass through host devices the user may already access, subject to user-namespace, group, and runtime rules. The hard line is creation:
- use an existing accessible device → can be possible
- create a new device node with
mknod→ rootless cannot, even with--privileged
Do not claim rootless Podman cannot use any devices. Distinguish access from creation. Supplementary group access sometimes needs --group-add keep-groups. Volume permission mapping belongs in Fix Podman volume permission denied and Podman user namespaces.
Checkpoint and restore
CRIU-based checkpoint and restore is a rootful-only workflow in current Podman. As a rootless user:
podman container checkpoint web-rootlessError: checkpointing a container requires rootPlan checkpoint/restore on rootful Podman when that capability is a hard requirement.
Rootless storage and NFS
Do not write that users with NFS home directories cannot run rootless Podman at all. The constraint is container storage on filesystems that do not support user-namespace ID mapping.
If default graph root resolves to:
$HOME/.local/share/containers/storageand $HOME is NFS-backed, layer storage can fail. The workable pattern is:
NFS home + local graphroot → can work
NFS graphroot → unsupportedPoint graphroot at local disk through storage.conf as described in Podman storage location.
Rootless resource limits
On cgroups v2 systems with systemd delegation, many rootless CPU and memory limits work. The lab reports the same cgroup stack for both modes:
cgroupManager: systemd
cgroupVersion: v2Do not state as a general modern rule that rootless Podman cannot set resource limits. Historical cgroups v1 rootless setups were far more limited. Inspect podman info on your host before assuming limits are unavailable.
Rootless security advantage
Rootless Podman:
- keeps container processes bounded by the host user's privilege ceiling
- prevents a container escape from automatically beginning as host UID 0
- isolates per-user container state from other Podman users
It does not:
- make containers inherently safe
- remove kernel vulnerability risk
- make
--privilegedharmless
Rootless reduces privilege available to the workload. It does not replace image hygiene, mount discipline, or patching.
When rootless Podman is the better choice
Rootless fits well when:
- developers run local test containers
- applications do not need privileged host operations
- systemd user services or per-user Quadlet units own the workload
- CI jobs run under dedicated service accounts
- published ports stay above 1024 or sit behind a reverse proxy
- storage and bind mounts are user-owned
Default to rootless unless a concrete capability requirement pushes you to rootful.
When rootful Podman is the better choice
Rootful fits when the workload needs:
- CRIU checkpoint or restore
- creation of device nodes inside containers
- host-network configuration that requires root
- direct macvlan or ipvlan on physical interfaces
- true host privileges unavailable to the unprivileged account
- centrally managed system-wide container infrastructure
Do not choose rootful only because a bind mount has wrong ownership. Fix UID mapping first if rootless otherwise fits.
sudo podman is not an upgrade of the same container
If podman ps shows web-rootless, sudo podman ps may list nothing. sudo switches Podman storage and context; it does not elevate an existing rootless container.
The rootless container did not disappear — you are looking at a different store. Recreate the workload rootfully or move images explicitly.
Rootless vs rootful decision table
| Requirement | Better starting point |
|---|---|
| Normal server application | rootless |
| Developer workstation container | rootless |
| systemd user service | rootless |
| Web app behind rootful reverse proxy on 443 | rootless app |
| Direct host port 80 without system configuration | rootful |
| Create device nodes | rootful |
| CRIU checkpoint | rootful |
| Host physical macvlan | rootful |
| User-owned bind mount | rootless often fits |
| NFS home with local Podman graphroot | rootless still possible |
References
Summary
Rootless and rootful Podman are two contexts on the same engine, not a security toggle with a single winner. Rootless maps container UID 0 to your host user, stores state under your home directory, and defaults to pasta networking. Rootful runs as root, uses /var/lib/containers/storage, and can bind privileged ports, create device nodes, and run CRIU checkpoint workflows.
The operational trap is assuming sudo podman manages the same containers as your user account. It does not — stores, images, and running containers are separate. --privileged rootless relaxes engine limits but cannot invent host root capabilities.
Default to rootless for ordinary application containers and move to rootful when a specific capability — ports below 1024 without forwarding, device node creation, checkpoint, or physical macvlan — truly requires it. For subuid setup, migrate after range changes, and first-container verification, start with Rootless Podman. For pasta defaults and bridge trade-offs, continue with Rootless Podman networking.

