Mastering Mounts and Storage Permissions in Proxmox LXC: A Guide to UID/GID Mapping

Mastering Mounts and Storage Permissions in Proxmox LXC: A Guide to UID/GID Mapping
Photo by Jainath Ponnala / Unsplash

Introduction

Bind-mounting host directories into LXC containers in Proxmox is essential for sharing data, running services like media servers, and integrating with external storage. However, users often encounter permission issues—files appear as nobody:nogroup or users cannot write to mounted directories inside the container. This guide explains why these issues occur, how LXC UID/GID mapping works, and the solutions that provide secure, predictable access.


Why Permissions Break: Understanding LXC UID/GID Mapping

Proxmox LXC containers, especially unprivileged containers, use user and group ID remapping for security. By default:

  • Host UID/GID = Container UID/GID + 100000

For example:

  • UID 0 (root) inside the container maps to UID 100000 on the host.
  • UID 1000 inside the container maps to UID 101000 on the host.

This means if you mount /mnt/data from the host into the container, files owned by root:root (0:0) on the host will appear as nobody:nogroup inside the container, unless the IDs align.


Common Symptoms

  • Files and directories show up as nobody:nogroup inside the container.
  • Permission denied errors when accessing or writing to mounted storage from inside the container.
  • Only root inside the container can access files, while regular users cannot.

Solution 1: Change Host Directory Ownership to Mapped UID/GID

When to Use

  • Quick fix for single-purpose containers.
  • When you do not require matching user IDs between host and container.

How It Works

Change the ownership of the host directory to the mapped UID/GID expected by the container user.

Example

Suppose:

  • Host path: /mnt/my-data-pool
  • Container mount path: /mnt/host-data
  • Container ID: 101
  • Inside container, user UID/GID: 1000

By default, container UID 1000 maps to host UID 101000.

Steps

  1. Restart the container.

Add the bind mount in /etc/pve/lxc/101.conf:

mp0: /mnt/my-data-pool,mp=/mnt/host-data

Change ownership of the host directory:

chown 101000:101000 /mnt/my-data-pool -R

After this, files inside /mnt/host-data will be owned by the correct user inside the container.

Pros & Cons

  • Pros: Simple, no changes to container config beyond the mount.
  • Cons: Host directory ownership appears as a "high" UID/GID (e.g., 101000), which may confuse other host processes or admins. Not ideal when sharing data with non-containerized host users.

Solution 2: Custom UID/GID Mapping (Identity Mapping)

When to Use

  • You want matching user IDs between the host and the container.
  • You need flexible, fine-grained control over which UIDs/GIDs are mapped.

How It Works

You modify the container's UID/GID mapping in /etc/pve/lxc/<id>.conf to map specific container UIDs directly to host UIDs.

Example

Suppose:

  • You want container user with UID 1000 to map to host UID 1000.

Steps

    • This means container UID 1000 maps to host UID 1000; all others use the default offset.
  1. Restart the container.

Add the mount point in the container config:

mp0: /mnt/my-data-pool,mp=/mnt/host-data

On the host, ensure the directory is owned by UID 1000:

chown 1000:1000 /mnt/my-data-pool -R

Edit the container config /etc/pve/lxc/101.conf:Add custom mappings:

lxc.idmap = u 0 100000 1000
lxc.idmap = u 1000 1000 1
lxc.idmap = u 1001 101001 64536
lxc.idmap = g 0 100000 1000
lxc.idmap = g 1000 1000 1
lxc.idmap = g 1001 101001 64536

Now, the user with UID 1000 in the container sees files as owned by them, and the host recognizes the same ownership.

Pros & Cons

  • Pros: Clean, predictable permissions for both host and container users. Essential for seamless integration (e.g., Docker-in-LXC, NFS shares).
  • Cons: Security risk: If the container is compromised, the mapped host user is also at risk. Only map UIDs/GIDs you trust and need.

Troubleshooting Permission Denied Errors

  • Check UID/GID mapping with ls -n on both host and container.
  • Ensure the user inside the container matches the mapped UID/GID.
  • Restart the container after changing mappings or mount points.
  • For NFS or network shares: Permissions must be correct on both the underlying storage and the host mount point.

Advanced Topics

Using ID-Mapped Mounts (shiftfs, idmap)

  • LXD and recent kernel features allow for "id-mapped" mounts, which can provide flexible mapping without changing files on disk.
  • Not all Proxmox/LXC setups support this out-of-the-box—consult your kernel and LXC/LXD version documentation.

Security Considerations

  • Never map root (UID 0) in the container to root on the host in unprivileged containers; this would break the security model.
  • Map only the minimum set of UIDs/GIDs needed for your application.

Summary Table: Methods Comparison

Method Host Ownership Appears As Container Ownership Appears As Security Implication Use Case
Change host dir to mapped UID/GID High UID/GID (e.g., 101000) Correct user inside container Minimal (unprivileged container) Quick fix, isolated data
Custom UID/GID mapping (lxc.idmap) Matches host (e.g., UID 1000) Matches container user Host user exposed if container leaks Shared data, host and container synergy