I was lazy, try turn to proxmox forum for help to run wayland in unprivileged LXC. But after search, I found 2 posts’ reply indicating the people who replied the post knows how to run wayland in privileged LXC, but they didn’t organize and publish howto do it, they just keep secret to themself. I was very very angry, so I didn’t ask for help.
With AI’s help, I just learnt how to use unprivileged LXC. I can tell you what wayland need to run in unprivileged LXC is the same as in privileged LXC with some extra permission tweak.
I will show you how to run it in ubuntu server 26.04.
Part unprivileged LXC
Step install:
sudo apt install lxc bridge-utils uidmap -y
Ubuntu will config /etc/subuid and /etc/subgid and lxcbr0 for us.
Step allow user to use lxcbr0:
echo "$(id -un) veth lxcbr0 10" | sudo tee -a /etc/lxc/lxc-usernet
Step user preparation:
mkdir -p ~/.config/lxc
cp /etc/lxc/default.conf ~/.config/lxc/default.conf
UID_START=$(awk -F: -v u="$USER" '$1 == u {print $2; exit}' /etc/subuid)
UID_COUNT=$(awk -F: -v u="$USER" '$1 == u {print $3; exit}' /etc/subuid)
GID_START=$(awk -F: -v u="$USER" '$1 == u {print $2; exit}' /etc/subgid)
GID_COUNT=$(awk -F: -v u="$USER" '$1 == u {print $3; exit}' /etc/subgid)
cat >> ~/.config/lxc/default.conf <<EOF
lxc.idmap = u 0 $UID_START $UID_COUNT
lxc.idmap = g 0 $GID_START $GID_COUNT
EOF
# change USERNAME to your username
chmod +x /home/USERNAME
Step create unprivileged LXC:
Choose whatever dist you want, choose whatever name you like. I’m using debian 13, CT name is debian13.
lxc-create --name debian13 --template download -- --dist debian --release trixie --arch amd64
I don’t know why I can’t just start it, I have to edit the config, change lxc.apparmor.profile = generated to lxc.apparmor.profile = unconfined , so it can start. My CT name is debian13, so the config is in ~/.local/share/lxc/debian13/.
Step permission tweak:
cat /etc/group | grep -e tty -e video -e render -e audio -e input
tty:x:5:
audio:x:29:
video:x:44:
input:x:995:
render:x:991:
That’s what in ubuntu, I don’t know what they will be in other OS, change below to fit you environment. We need to add them in /etc/subgid, for example my user is test:
test:100000:65536
test:5:1
test:29:1
test:44:1
test:991:1
test:995:1
Add them in the unprivileged LXC config:
# DO comment this line:
# lxc.idmap = g 0 100000 65536
# Container GID 0-5 -> host GID 100000-100005
lxc.idmap = g 0 100000 5
# audio: container GID 5 -> host GID 5
lxc.idmap = g 5 5 1
# Container GID 6-28 -> host GID 100006-100028
lxc.idmap = g 6 100006 23
# audio: container GID 29 -> host GID 29
lxc.idmap = g 29 29 1
# Container GID 30-43 -> host GID 100030-100043
lxc.idmap = g 30 100030 14
# video: container GID 44 -> host GID 44
lxc.idmap = g 44 44 1
# Container GID 45-990 -> host GID 100045-100990
lxc.idmap = g 45 100045 946
# render: container GID 991 -> host GID 991
lxc.idmap = g 991 991 1
# Container GID 992-994 -> host GID 100992-100994
lxc.idmap = g 992 100992 3
# input: container GID 995 -> host GID 995
lxc.idmap = g 995 995 1
# Container GID 996-65535 -> host GID 100996-165535
lxc.idmap = g 996 100996 64540
Part wayland
The rest part is exactly the same in:
Because it’s unprivileged LXC, it will not change tty0 and tty7’s permission, so we can sudo chmod 0660 /dev/tty0 /dev/tty7 in host, then start the unprivileged LXC, get into it, change to the user, start the wayland compositor. Do remember change to tty7.