Skip to content

🔐 LXC Storage Sharing & UID/GID Mapping ​

Storage sharing across unprivileged LXC containers on PVE-1 does not rely on slow network file systems (NFS/CIFS). Instead, it uses direct host ZFS Bind Mounts paired with POSIX ACLs.


🧩 How Unprivileged LXC ID Mapping Works ​

Proxmox unprivileged containers isolate root and users by shifting container IDs into an unprivileged namespace starting at 100000 on the host:

$$\text{Host ID} = 100000 + \text{Container ID}$$

EntityContainer ID (Inside LXC)Host ID (On PVE-1 Host)Account Name / Purpose
Container RootUID 0 / GID 0UID 100000 / GID 100000Unprivileged root
Standard User (rayman-ssh)UID 1000 / GID 1000 (or 1001)UID 101000 (or 101001)Primary admin/docker user
Standard User (admin-ssh)UID 1001 / GID 1001 (or 1000)UID 101001 (or 101000)Secondary admin user
Shared Storage GroupGID 10000GID 110000nas_shares group

👥 Dual-User Access Policy (rayman-ssh & admin-ssh) ​

IMPORTANT

Operational Requirement: Both rayman-ssh AND admin-ssh must have full rwx permissions across all files and folders in /mnt/media_root.

Because UID 1000 vs 1001 varies between containers (e.g. rayman-ssh is UID 1000 on docker-media but UID 1001 on docker-edge and docker-admin), permissions cannot rely on file ownership (USER_OBJ). Full dual-user access is guaranteed by:

  1. Giving both users membership in group nas_shares (GID 10000).
  2. The POSIX ACL on tank/media_root which grants GROUP:110000:rwx on access and default inheritance.

📜 POSIX ACL Implementation ​

On the PVE-1 host, tank/media_root has default and access POSIX ACLs configured:

text
system.posix_acl_access:
  USER_OBJ::rwx
  USER:<smbuser_uid_on_host>:rwx
  USER:<nfsuser_uid_on_host>:rwx
  GROUP_OBJ::rwx
  GROUP:110000:rwx  <--- Maps to GID 10000 inside unprivileged LXCs (nas_shares)
  MASK::rwx
  OTHER::r-x

system.posix_acl_default:
  USER_OBJ::rwx
  USER:<smbuser_uid_on_host>:rwx
  USER:<nfsuser_uid_on_host>:rwx
  GROUP_OBJ::rwx
  GROUP:110000:rwx  <--- Automatically inherited by all newly created files & directories
  MASK::rwx
  OTHER::r-x

Applying Host ACLs ​

To apply or restore these ACL permissions recursively on PVE-1:

bash
# On PVE-1 Host:
setfacl -R -m u:100000:rwx,d:u:100000:rwx,g:110000:rwx,d:g:110000:rwx /tank/media_root

⚠️ LXC GID Consistency Note ​

  • Inside an unprivileged LXC, nas_shares must always be GID 10000 (which maps to host 110000).
  • If an LXC mistakenly set sudo groupmod -g 110000 nas_shares, inside the unprivileged container that maps to host GID 210000, losing the group ACL pass-through.
  • Always verify that getent group nas_shares reports GID 10000.

Container Verification Commands ​

Inside any LXC guest:

bash
# 1. Verify GID is 10000:
getent group nas_shares

# 2. Add users to nas_shares:
sudo usermod -aG nas_shares rayman-ssh
sudo usermod -aG nas_shares admin-ssh

# 3. Test write access:
touch /mnt/media_root/test_rw && rm /mnt/media_root/test_rw

Authoritative operational repository and DR hub.