Run Podman containers rootless on Linux without root privileges
A practical guide to running Podman containers rootless on Linux: set up user namespaces, enable systemd user socket, run and verify a container, and recover from permission and networking issues.
23 Aug 2026, 12:03 UTC

Problem: you need containers but you can't run as root
Running containers as root expands the blast radius of a compromise and blocks multi-tenant use on shared hosts. Podman rootless mode maps the container user to an unprivileged UID range on the host, so the container runtime never needs root. The practical takeaway is a working rootless setup with systemd socket activation, verified UID mapping, and a recovery path when permissions or networking break.
Desired outcome
A non-root Linux user can start, stop and inspect containers, publish a host port, and have the Podman socket survive logout. Containers run under user namespaces with storage in the user home, no root processes spawned for the runtime.
Prerequisites
Run all checks on the target host as the unprivileged user unless noted.
- Linux kernel 4.11+ with unprivileged user namespaces enabled. Some distros gate this via
/proc/sys/kernel/unprivileged_userns_clone. - User namespace ranges configured in
/etc/subuidand/etc/subgid. Podman needs a contiguous range for mapping. - Podman 3.0+ installed. 4.0+ uses Netavark for networking; pre-4.0 used CNI.
- systemd user session active. Socket activation requires a lingering user session.
Setup user namespace and socket
Verify subuid/subgid entries exist for the user. This requires no elevated rights to read.
grep ^$(whoami): /etc/subuid /etc/subgid
Enable lingering so the user systemd instance stays up after logout. Run as root or with sudo.
loginctl enable-linger $(whoami)
Start and enable the user Podman socket. Run as the target user in a terminal where systemd --user is reachable.
systemctl --user enable --now podman.socket
Check the socket is active.
systemctl --user status podman.socket
Run a rootless container
Pull and run an image with a published port. Rootless port forwarding uses slirp4netns or pasta; ports below 1024 need extra privileges.
podman run -d --name web -p 8080:80 docker.io/library/nginx:alpine
List containers.
podman ps
Verify the container is rootless.
podman info --format '{{.Host.Security.Rootless}}'
Check the UID inside the container is non-zero.
podman exec web id -u
Test connectivity.
curl http://localhost:8080
Expected checks
podman psshows the container with status Up.podman inforeports rootless true.podman exec web id -ureturns a non-zero UID, typically mapped from the user range.ss -tlnp | grep 8080shows the listening process owned by the user, not root./proc/$(podman inspect -f '{{.State.Pid}}' web)/uid_mapshows a valid mapping for the container PID.
Common issues and recovery
Container fails to start or logs errors.
podman logs web
Permission errors on bind mounts. Container UID mapping must match host file ownership. On SELinux systems add :z or :Z to volume flags.
Socket activation lost after logout. Re-enable lingering and restart the user socket.
systemctl --user restart podman.socket
Corrupted storage. This is destructive and removes all local images and containers for the user.
podman system reset
Rootless storage lives in ~/.local/share/containers/storage. Backing up this directory is the practical disaster recovery path.
Limitations
User namespaces add mapping overhead and slirp4netns networking is slower than host networking. High-throughput workloads may be better served rootful.
Binding host directories requires matching UID/GID or relabeling. Ports <1024 are blocked by default; change net.ipv4.ip_unprivileged_port_start or use authbind.
Systemd user session must stay active. SSH sessions without lingering lose socket access after logout.
Optional systemd management
Quadlet .container files allow systemd to manage rootless containers with auto-start and dependencies, without root.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.