Mastering Mounts and Storage Permissions in Proxmox LXC: A Guide to UID/GID Mapping
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:nogroupinside 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
- 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.
- 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 -non 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 |