Fixing the “Permission denied” error when mounting a host directory into a rootless Podman container

Rootless Podman runs containers as an unprivileged user, so a bind‑mount that works for root often fails with “Permission denied.” That error is usually a mismatch between the host directory’s ownership/permissions and the container’s user namespace. Below is a quick checklist that gets the mounts working again while keeping the isolation tight.

Common Causes

Cause Why it happens Typical symptom
File ownership The host directory is owned by root or another UID that the container’s user can’t read/write. mount: permission denied or open /data/file: Permission denied inside the container.
SELinux/AppArmor context The host directory’s security context blocks the container’s process. Same “Permission denied” even when file permissions look right.
User‑namespace mapping Podman maps container UID 0 to a non‑zero host UID. If the host directory is owned by root, the mapped UID has no rights. Error appears only when --userns=keep-id is omitted.
Mount options Using :Z/:z incorrectly or omitting them when SELinux is enabled. SELinux denies the mount, causing the error.

Quick Fixes

  1. Match ownership

    # Assume container runs as UID 1000
    sudo chown -R 1000:1000 /home/user/data
    

    Or give the specific UID access without changing the owner:

    setfacl -R -m u:1000:rwx /home/user/data
    
  2. Adjust SELinux context

    # For a read‑write bind
    sudo chcon -Rt svirt_sandbox_file_t /home/user/data
    # Or use the :Z option in the mount
    podman run --userns=keep-id \
               -v /home/user/data:/data:Z \
               myimage
    
  3. Keep the host UID inside the container

    podman run --userns=keep-id \
               -v /home/user/data:/data \
               myimage
    

    keep-id maps the current host UID to UID 0 inside the container, eliminating the mapping mismatch. It does expose the host UID to the container, but it keeps the container from running as root.

  4. Use --mount syntax for clarity

    podman run --userns=keep-id \
               --mount type=bind,source=/home/user/data,target=/data,options=Z \
               myimage
    

Advanced Options

  • Read‑only mounts reduce attack surface.

    podman run -v /home/user/data:/data:ro myimage
    
  • Temporary mounts for secrets:

    podman run --tmpfs /run/secrets:rw,size=1m \
               -v /etc/secret.key:/run/secrets/key:ro \
               myimage
    
  • Podman‑systemd integration: when launching via systemd-run, add --userns=keep-id and -v options to the unit file.

Security Trade‑offs

Option Risk Mitigation
--userns=keep-id Host UID visible inside container Use only for trusted images; avoid privileged containers.
:Z/:z SELinux context change may affect other processes Verify context with ls -Z /home/user/data.
Read‑only mounts Prevents accidental writes Use when data is static; avoid for logs.

Rootless containers already give a solid isolation boundary. Adding keep-id or tweaking SELinux contexts should only happen when you need it. Don’t run containers as root unless you’re sure it’s necessary.

Troubleshooting Checklist

  1. Verify host permissions

    ls -ld /home/user/data
    
  2. Check SELinux context

    ls -Z /home/user/data
    
  3. Inspect Podman user‑namespace mapping

    podman info | grep -i userns
    
  4. Re‑run with verbose output

    podman run -it --rm --log-level=debug \
               -v /home/user/data:/data:Z \
               myimage
    

If the error keeps showing up after aligning ownership and SELinux, think about whether the host directory lives on a filesystem that doesn’t support the needed mount options (e.g., NFS with noexec). In those cases, switch to a local directory or tweak the NFS export.

For deeper dives into user namespaces and SELinux, the kernel documentation is a reliable reference:


See also