Join our Newsletter — 33% off our NHI Course
Home› Guides› Podman Security: Run Rootless, Protect the Socket and…
Guide Cloud & Workload Identity

Podman Security: Run Rootless, Protect the Socket and Isolate Containers

← All guides
By NHI Mgmt Group, edited by Lalit Choda Updated 8 November 2026 13 min read
On this page

Podman gives every Linux user the ability to build and run containers, so the security of a Podman host depends on how user namespaces, the API socket, SELinux labelling and secrets are configured for each of those users. Podman runs containers as child processes of the invoking user, with no setuid binary, and can run them rootless, mapping container root to an unprivileged account. Those are strong foundations, and they hold best when subordinate ID ranges, socket activation, Quadlet unit settings and image trust policy are set deliberately. This guide covers each of those with exact file paths and option names from the Podman project documentation. It is written for Linux, platform and security engineers running Podman on RHEL-family and other distributions, on servers and developer workstations. For runtime security concepts that apply to every engine, see the Container Runtime Security Guide.

This is an independent guide from NHI Mgmt Group, based on the Podman project's public documentation as of November 2026. It is not sponsored or reviewed by the Podman project. Product features change, so confirm settings against the Podman project's current documentation.

Key takeaways

  • Run rootless wherever you can. Container root maps to the invoking user, and a rootless container cannot gain more privileges than that user, so a container escape lands in an unprivileged account.
  • Subordinate ID ranges are an access control. Entries in /etc/subuid and /etc/subgid must not overlap, and must never subordinate another active user's ID, or one user can act as another.
  • The Podman API socket equals the user's shell. The documentation states the API grants full access to Podman functionality and allows code execution as the service user; keep it on the Unix socket or behind SSH or mutual TLS.
  • Keep SELinux labelling on. label = true is the default in containers.conf; relabel volumes with :Z rather than reaching for label=disable.
  • Set an image trust policy. The containers-policy documentation strongly recommends a default of reject in policy.json, with signed images allowed per registry.

How identity and access work in Podman

Podman has no central service that every user talks to. Each podman command runs as the user who typed it, and the containers it starts are that user's processes. Identity on a Podman host therefore comes down to Linux accounts, the user namespace mapping for each account, and the SELinux or AppArmor confinement applied to containers.

Rootful and rootless

AspectRootful PodmanRootless Podman
Runs asrootAn ordinary user
Container root maps toHost root unless --userns is setThe invoking user's UID
Image storage/etc/containers/storage.conf graphroot${XDG_DATA_HOME}/containers/storage (rootless ignores system graphroot and runroot)
API socket/run/podman/podman.sock$XDG_RUNTIME_DIR/podman/podman.sock
Registry credentialsRoot's auth file${XDG_RUNTIME_DIR}/containers/auth.json by default
Quadlet units/etc/containers/systemd/~/.config/containers/systemd/
Typical useWorkloads needing host devices or privileged networkingMost services, CI runners and developer use

User namespaces and subordinate IDs

Rootless Podman uses user namespaces. The setuid helpers newuidmap and newgidmap set up the mapping from /etc/subuid and /etc/subgid, whose entries take the form USERNAME:UID:RANGE and are added by root with usermod --add-subuids and --add-subgids. Container UID 0 maps to the user; container UID 1 maps to the first subordinate ID. The rootless tutorial makes four points that matter for security:

  • No overlap: overlapping ranges let one user enter another user's namespace and corrupt it.
  • No active IDs: subordinating an active user's ID to someone else enables impersonation; subordinating a group ID lets the user act as that group inside containers.
  • Local files: the files must be local; network-provided sources such as LDAP or Active Directory are not used for these ranges, so manage them with configuration management.
  • Apply changes cleanly: after edits, run podman system migrate as the user to stop containers and the pause process.

Within a host, --userns=keep-id maps the user's own UID into the container so a non-root container user can write to bind mounts. For rootful workloads, consider userns options in containers.conf (default host, alternative private) or a per-container UserNS= in Quadlet so container root is not host root. See the Linux Namespaces and cgroups Security Guide.

Admin roles and privileged access

On a Podman host the privileged roles are Linux roles. Map them explicitly:

  • Root and sudoers: can run rootful containers, edit /etc/containers/* (including policy.json, registries.conf and containers.conf) and change subordinate ID files. Restrict sudo rules to named commands and review them. See the Red Hat Enterprise Linux Security Hardening Guide.
  • Service accounts running rootless containers: create a dedicated non-login account per service, give it its own subordinate range, and enable lingering only for accounts that run Quadlet services at boot. See the Linux Service Accounts and Keytab Management Guide.
  • Developers: rootless Podman lets them work without sudo. Keep it that way, and avoid adding them to groups that grant access to rootful sockets.

Privilege flags to control

SettingEffect per the Podman docsGuidance
--privilegedTurns off capability dropping, device limits, read-only mount points, AppArmor or SELinux separation and seccompReserve for named exceptions; rootless privileged containers still cannot exceed the user
--cap-addAdds to the default set; docs flag CAP_SYS_ADMIN, CAP_SYS_PTRACE, CAP_MKNOD, CAP_SYS_MODULE as particularly dangerous outside a user namespaceReview each addition; prefer --cap-drop all then add what is needed
--security-opt label=disableTurns off SELinux label separationUse :Z or :z volume options instead
--security-opt seccomp=unconfinedRemoves the seccomp filterSupply a custom profile with seccomp=profile.json instead
--security-opt unmask=ALLUnmasks default-masked paths such as /proc/kcore, /proc/keys and /sys/firmwareKeep defaults; unmask specific paths only when justified
--env-hostPasses the whole host environment into the containerAvoid; it can carry host secrets

The default capability set in containers.conf (default_capabilities) is CHOWN, DAC_OVERRIDE, FOWNER, FSETID, KILL, NET_BIND_SERVICE, SETFCAP, SETGID, SETPCAP, SETUID and SYS_CHROOT. See the Linux Capabilities Guide for trimming it further.

Integrations, API tokens and service accounts

The Podman API socket

podman system service serves a Docker-compatible and native REST API. The documentation is direct about the risk: the API grants full access to Podman functionality, allows arbitrary code execution as the user running the service, and offers no way to limit or audit that access. By default, Unix socket file permissions mean only the service's user can connect.

  • Prefer socket activation: podman.socket (system or user unit) starts the service on demand, and the service exits after the inactivity timeout (--time, default 5 seconds; 0 means never). Keep the timeout short rather than running a permanent listener.
  • Remote access: forward the Unix socket over SSH, as the docs recommend, and restrict which keys can reach the account.
  • TCP: the docs strongly recommend against network exposure without mutual TLS. If TCP is unavoidable, set --tls-cert, --tls-key and --tls-client-ca so clients must present a certificate from your CA. See the mTLS Guide.
  • Mounting the socket into containers: any container given the socket can start containers as that user. Treat such tools (CI agents, reverse proxies, dashboards) as holding the user's full privileges, and prefer running them under a dedicated rootless account.

Podman secrets

podman secret create stores secrets outside images: they are not included in podman commit output or podman export archives, and each is limited to 512 kB.

DriverStorage per the docsWhen to use
file (default)A read-protected fileSingle host with disk encryption and tight account separation
passGPG-encrypted fileWhere secrets must be encrypted at rest on the host
shellYour scripts for list, lookup, store and deleteFetch from an enterprise secrets manager at run time

Consume secrets as files: --secret source=name,type=mount,uid=1001,gid=1001,mode=0400 places them at /run/secrets/name. Set mode explicitly, because mounted secrets default to mode 0444 owned by UID 0. type=env is available but environment variables are easier to leak through process listings and crash dumps. Secrets are written when the container is created, and --replace affects only containers created afterwards, so rotation means recreating containers. Our recommendation: rotate application secrets at least every 90 days and on any staff or host change, and drive rotation through a Quadlet restart. See the Secrets Management Guide.

Registry credentials

podman login writes to the user's auth file, by default under ${XDG_RUNTIME_DIR}/containers/ for rootless users. Use registry robot or service accounts scoped to pull, never a person's credentials, on servers. Podman secrets can also hold registry credentials. See the Container Registry Security Guide.

Logging and detection

  • Podman events: events_logger defaults to journald (alternatives file or none; never use none in production). Filter with journalctl SYSLOG_IDENTIFIER=podman and the PODMAN_EVENT field, or stream podman events --format json to your collector.
  • Container logs: with log_driver empty, Podman uses journald when the journal is available and k8s-file otherwise. Journald gives central forwarding without per-container files.
  • API activity: the default podman.socket units log API calls at info level, which helps reconstruct remote actions.
  • Host audit: watch /etc/subuid, /etc/subgid, /etc/containers/ and Quadlet directories with auditd or file integrity monitoring. See the Linux Logging and auditd for Defenders Guide.
EventWhy it mattersATT&CK
Container exec into a production containerInteractive access outside deployment pipelinesT1609
Container create or start with privileged options or host mountsPossible preparation for host escapeT1610, T1611
Image pull from an unexpected registry or pull-error due to policyUntrusted image or a blocked attemptT1525
secret create or remove outside change windowsCredential tamperingT1552.001
New listener on the Podman API over TCPRemote control path openedT1552.007

Metrics that show progress: share of containers running rootless; count of containers with --privileged or label=disable (target zero outside approved exceptions); hosts with policy.json default reject; Podman API sockets reachable over TCP (target zero); median age of secrets in use.

Hardening baseline

Host configuration

  • SELinux enforcing: keep label = true in containers.conf. Relabel bind mounts with :Z for a single container or :z when several containers share the content; never relabel system directories such as /home or /usr. See the SELinux Guide.
  • Seccomp and AppArmor: keep seccomp_profile at the shipped /usr/share/containers/seccomp.json or a tighter profile; on AppArmor systems keep apparmor_profile = "container-default".
  • Process limits: keep cgroups = "enabled" and set a pids_limit; confirm the current default value in the containers.conf documentation for your release.
  • Image trust: in /etc/containers/policy.json set "default": [{"type": "reject"}], then allow your registries under the docker transport with sigstoreSigned (a keyPath, or fulcio with rekorPublicKeyPath) or signedBy. A user's $HOME/.config/containers/policy.json takes precedence for that user, so monitor for it on servers. See the Sigstore Guide.

Quadlet unit baseline

Quadlet turns .container files into systemd services. Quadlet units do not use systemd's User=, Group= or DynamicUser= for rootless operation; place rootless units in the user's search path instead. A hardened [Container] section looks like this:

  • User= a numeric non-root UID, and UserNS= where rootful
  • NoNewPrivileges=true (default false)
  • DropCapability=all plus only the AddCapability= entries the service needs
  • ReadOnly=true (default false), with ReadOnlyTmpfs=true for scratch paths
  • Secret= for credentials, never Environment=
  • Pull= and AutoUpdate=registry only for images covered by your signature policy
  • No SecurityLabelDisable=, no SeccompProfile=unconfined, and PodmanArgs= only where unavoidable, as the docs advise

Combine this with systemd sandboxing on the unit where compatible. See the systemd Service Hardening Guide.

Rollout order

  1. Inventory hosts, accounts with subordinate ranges, rootful containers and any enabled podman.socket or TCP service.
  2. Fix subordinate ID overlaps and remove ranges that cover active IDs; run podman system migrate per user.
  3. Move rootful services to rootless Quadlet units under dedicated accounts, one service at a time, keeping the old unit disabled for rollback.
  4. Deploy policy.json in a pilot with signed images, watch for pull-error events, then roll out.
  5. Apply the Quadlet baseline and SELinux relabelling, testing each service in staging first.
  6. Forward Podman events and journald to the SIEM and set alerts for the events above.

Apply Podman security updates from your distribution promptly and watch the Podman security advisories.

Common misconfigurations

  • Overlapping or hand-edited subordinate ranges. Users can reach each other's namespaces. Fix: generate ranges centrally and check for overlap.
  • A permanent API listener. --time 0 or a TCP endpoint without mutual TLS leaves a code execution path open. Fix: socket activation, SSH forwarding, mTLS.
  • SELinux turned off to fix a volume error. Fix: :Z relabelling or a targeted label type, keeping separation on.
  • Secrets in environment variables or images. Fix: Podman secrets mounted as files with explicit mode, or the shell driver to an enterprise vault.
  • An accept-anything trust policy. Fix: default reject with signed registries allowed.
  • Privileged containers for convenience. Fix: add specific capabilities or devices and document each exception.
Control areaNIST SP 800-53 Rev 5CIS Controls v8.1ISO/IEC 27001:2022 Annex A
Rootless operation and capability limitsAC-6, SC-394 Secure ConfigurationA.8.2, A.8.9
API socket protectionAC-3, SC-84 Secure Configuration, 6 Access Control ManagementA.8.5, A.8.20
Secrets and registry credentialsIA-5, SC-283 Data ProtectionA.5.17, A.8.24
Image signature policySI-7, SR-112 Inventory and Control of Software AssetsA.8.19
Events and logsAU-2, AU-128 Audit Log ManagementA.8.15, A.8.16

Practitioner checklist

  • Run services rootless under dedicated accounts and use Quadlet units in the user search path.
  • Audit /etc/subuid and /etc/subgid for overlap and active IDs; manage them centrally.
  • Keep the Podman API on the Unix socket with socket activation; use SSH or mutual TLS for remote access.
  • Keep SELinux enforcing with label = true; relabel volumes with :Z or :z.
  • Set NoNewPrivileges=true, DropCapability=all and ReadOnly=true in Quadlet units, adding back only what is needed.
  • Set policy.json default to reject and allow signed images from approved registries.
  • Store credentials as Podman secrets mounted with explicit mode, or via the shell driver to your vault.
  • Forward Podman events and container logs to the SIEM and alert on exec, privileged creates and policy pull errors.
  • Track Podman security advisories and your distribution's container-tools updates.

Standards and references

Related NHI Mgmt Group resources: Container Runtime Security Guide · Container Security Guide · SELinux Guide · Container Image Security Guide

Free weekly newsletter

Subscribe to the NHI & AI Identity Journal

The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.

Bonus 33% off our NHI Course when you subscribe.

NHIMG Editorial Note
Researched and written by the NHI Mgmt Group editorial team using AI tools, under the editorial direction of Lalit Choda. Facts are drawn from the sources listed on this page and checked by our automated quality process. Last updated 8 November 2026. Spotted an error? Use our contact page.
NHI Mgmt Group, the independent authority on Non-Human Identity, IAM and Agentic AI security. nhimg.org