Hi everyone.
I've been using Proxmox for about 30 days, and I came up with a different way to make `idmap` work more transparently.
Most of the posts I found explain how to customize `idmap` so that the host users and groups match those inside the container, allowing the container to access host devices.
This usually results in a configuration like this:
If you need to add another user or group, you often have to adjust multiple lines to keep the mapping consistent.
In my opinion, this approach forces the container to adapt to the host permissions. It is difficult to read, harder to maintain, more error-prone, and also depends on the Linux template's users and groups never changing.
I looked for a different solution and remembered that POSIX ACLs allow multiple permissions to be assigned to the same device.
So here's the idea: instead of changing the ID mapping to fit the permissions, change the permissions to fit a simple ID mapping.
For my container (ID 200), I map every user and group into the range `<container-id>00000`, except for root:
Then I use `lxc.hook.pre-start` to automatically update the configuration and apply the required ACLs when the container starts.
Add the container UID range to `/etc/subuid`:
This results in a much cleaner and easier-to-maintain configuration. On the host, you only need to install the ACL package:
Using this approach, I finally have a container running a full desktop environment using the host GPU for display output, with LightDM, the MATE desktop, Steam, and emulators. Xorg automatically detects the keyboard and mouse. Still working on joystick support.
The only issue I still have is that keyboards input occasionally leaks to the host virtual terminal. I'm still investigating that.
Important !!!!!!!!!
When you first create the container, all users and groups are mapped into the default `100000` range. Before switching to this mapping scheme, stop the container and update the ownership of the files inside the container filesystem.
To list all UIDs and GIDs currently in use:
After checking the generated lists, convert the ownerships:
Don't forget to adjust the container ID and directory paths to match your own setup.
This approach has worked well for me so far, and I find it much easier to understand and maintain than a complex `idmap` configuration.
I'd be interested to hear if anyone sees any drawbacks to this approach or has suggestions for improving it.
I've been using Proxmox for about 30 days, and I came up with a different way to make `idmap` work more transparently.
Most of the posts I found explain how to customize `idmap` so that the host users and groups match those inside the container, allowing the container to access host devices.
This usually results in a configuration like this:
lxc.idmap: u 0 100000 65536
lxc.idmap: g 0 100000 44
lxc.idmap: g 44 44 1
lxc.idmap: g 45 100045 62
lxc.idmap: g 107 104 1
lxc.idmap: g 108 100108 65428
If you need to add another user or group, you often have to adjust multiple lines to keep the mapping consistent.
In my opinion, this approach forces the container to adapt to the host permissions. It is difficult to read, harder to maintain, more error-prone, and also depends on the Linux template's users and groups never changing.
I looked for a different solution and remembered that POSIX ACLs allow multiple permissions to be assigned to the same device.
So here's the idea: instead of changing the ID mapping to fit the permissions, change the permissions to fit a simple ID mapping.
For my container (ID 200), I map every user and group into the range `<container-id>00000`, except for root:
lxc.idmap: u 0 100000 1
lxc.idmap: g 0 100000 1
lxc.idmap: u 1 20000001 65535
lxc.idmap: g 1 20000001 65535
Then I use `lxc.hook.pre-start` to automatically update the configuration and apply the required ACLs when the container starts.
Add the container UID range to `/etc/subuid`:
Add the container GID range to `/etc/subgid`:lxc.hook.pre-start: /bin/bash -c 'file="/etc/subuid"; find_string="root:${LXC_NAME}00000:65536"; grep -xFq "${find_string}" ${file} || echo "${find_string}" >> ${file}'
Grant the `input` group inside the container access to the input devices:lxc.hook.pre-start: /bin/bash -c 'file="/etc/subgid"; find_string="root:${LXC_NAME}00000:65536"; grep -xFq "${find_string}" ${file} || echo "${find_string}" >> ${file}'
Grant the `audio` group inside the container access to the sound devices:lxc.hook.pre-start: /bin/bash -c 'setfacl -R -m u:100000:rw,g:${LXC_NAME}00101:rw /dev/input/*'
lxc.hook.pre-start: /bin/bash -c 'setfacl -R -m u:100000:rw,g:${LXC_NAME}00029:rw /dev/snd/*'
This results in a much cleaner and easier-to-maintain configuration. On the host, you only need to install the ACL package:
sudo apt update && sudo apt install acl
Using this approach, I finally have a container running a full desktop environment using the host GPU for display output, with LightDM, the MATE desktop, Steam, and emulators. Xorg automatically detects the keyboard and mouse. Still working on joystick support.
The only issue I still have is that keyboards input occasionally leaks to the host virtual terminal. I'm still investigating that.
Important !!!!!!!!!
When you first create the container, all users and groups are mapped into the default `100000` range. Before switching to this mapping scheme, stop the container and update the ownership of the files inside the container filesystem.
To list all UIDs and GIDs currently in use:
TARGET_DIR="<YOUR_CONTAINER_DIR>"; sudo find "$TARGET_DIR" -printf "%u\n" 2>/dev/null | sort -u | awk '$1 >= 100001' > uids.txt
TARGET_DIR="<YOUR_CONTAINER_DIR>"; sudo find "$TARGET_DIR" -printf "%g\n" 2>/dev/null | sort -u | awk '$1 >= 100001' > gids.txt
After checking the generated lists, convert the ownerships:
TARGET_DIR="<YOUR_CONTAINER_DIR>"; CONTAINER=<CONTAINER_ID>; while read -r id; do [ -n "$id" ] && echo "UID: $id -> $((id-100000+${CONTAINER}00000))" && sudo find "$TARGET_DIR" -uid "$id" -exec chown "$((id-100000+${CONTAINER}00000))" {} +; done < uids.txt
TARGET_DIR="<YOUR_CONTAINER_DIR>"; CONTAINER=<CONTAINER_ID>; while read -r id; do [ -n "$id" ] && echo "GID: $id -> $((id-100000+${CONTAINER}00000))" && sudo find "$TARGET_DIR" -gid "$id" -exec chgrp "$((id-100000+${CONTAINER}00000))" {} +; done < gids.txt
Don't forget to adjust the container ID and directory paths to match your own setup.
This approach has worked well for me so far, and I find it much easier to understand and maintain than a complex `idmap` configuration.
I'd be interested to hear if anyone sees any drawbacks to this approach or has suggestions for improving it.