An LXC as a desktop - ether42/bootable-usb GitHub Wiki

An LXC as a desktop

FIXME: WIP (but functional)

Setup

Note that the following syntax works only for /dev mounts (for example /run is later mounted as a tmpfs and as such everything previously mounted in it will be hidden), but looks kinda clunky:

lxc.hook.autodev = sh -c 'mkdir -p "$LXC_ROOTFS_MOUNT"/dev/dri && mount --bind /dev/dri "$LXC_ROOTFS_MOUNT"/dev/dri'

For the moment I prefer to bind mount everything two times...

A simple LXC configuration should include:

lxc.cgroup.devices.allow = c 4:7 rwm
lxc.hook.autodev = sh -c 'mknod "$LXC_ROOTFS_MOUNT"/dev/tty7 c 4 7'

lxc.cgroup.devices.allow = c 13:* rwm
lxc.mount.entry = /dev/input mnt/dev/input none bind,create=dir

lxc.cgroup.devices.allow = c 116:* rwm
lxc.mount.entry = /dev/snd mnt/dev/snd none bind,create=dir

lxc.cgroup.devices.allow = c 226:* rwm
lxc.mount.entry = /dev/dri mnt/dev/dri none bind,create=dir

lxc.mount.entry = /run/udev mnt/run/udev none bind,create=dir

To complete the setup, execute the following commands in the LXC and restart it:

systemctl enable getty@tty7
cat > /etc/fstab << EOF
/mnt/dev/input /dev/input none bind,create=dir
/mnt/dev/snd /dev/snd none bind,create=dir
/mnt/dev/dri /dev/dri none bind,create=dir
/mnt/run/udev /run/udev none bind,create=dir
EOF

The seventh virtual terminal should now be available from the host, showing the LXC's console.

For X or Wayland to work, they must at least access to the input & video devices and a virtual terminal. Depending on the hardware, access to /dev/mem may be required and as such you may need to tweak lxc.cap.drop. For example, this is required under VirtualBox if the Guest Additions aren't available, if they are /dev/dri is populated and multiple monitors should work.

X and Wayland must also know which device is an input and they do so by looking at /run/udev/data. The difference may be seen between the host and the LXC by running udevadm info /dev/input/eventX: the host, having /run/udev/data, will clearly show more information than the LXC, being deprived of udev's information. Therefore, /run/udev must also be bind mounted.

However this won't solve all the problems: when a device disconnects, X won't be told if the device later reappers without a runnig udev (this is easily seen by stracing X: epoll_wait won't returns after a keyboard disconnection). It seems than running udev in the container fixes this problem but many online resources tell that udev shouldn't be run inside, so let's get rid of X hotplugging.

Ensure X runs properly:

apt-get install xinit
startx # -- :0 tty7

If it does, dump the automatic configuration as root:

Xorg -configure # you may need to do that on the host
cp /root/xorg.conf.new /etc/X11/xorg.conf

Prepend to the configuration to disable hotplugging:

Section "ServerFlags"
  Option "AutoAddDevices" "False"
EndSection

In my configuration, I have the kbd and mouse input devices, so I should install the corresponding plugins:

apt-get install xserver-xorg-input-kbd xserver-xorg-input-mouse

This should be enough for X to gracefully recover of disconnecting devices, at the expense of having a static configuration... (you could get rid of the udev mounts if you don't need them anymore).

You may need to append to /etc/X11/Xwrapper.config so X can start with a regular user:

needs_root_rights=yes

You may need to add yourself to the video group to dynamically load drivers via /dev/dri (with libGL for example).

The keyboard setup may be done in /etc/X11/xorg.conf instead of relying on setxkbmap:

Section "InputDevice"
  Identifier "Keyboard0"
  Driver "kbd"
  Option "XkbLayout" "us_intl"
EndSection

The monitors setup may be done in /etc/X11/xorg.conf instead of reyling on xrandr:

Section "Monitor"
  Identifier "VGA1"
  Option "Primary" "True"
EndSection

Section "Monitor"
  Identifier "DP1"
  Option "RightOf" "VGA1"
EndSection

Section "Screen"
  Identifier "Screen0"
  Device "Card0"
  Monitor "VGA1"
  Monitor "DP1"
  # ...
EndSection
Firefox

Firefox now requires PulseAudio (you may need to add yourself to the audio group):

apt-get install pulseaudio # dbus-x11 # pulseaudio tries to start dbus-launch
pulseaudio --start

For now Firefox doesn't officially support native Wayland but a Flatpak repository exists.

For an X-based system:

wget 'https://download.mozilla.org/?product=firefox-devedition-latest-ssl&os=linux64&lang=en-US'
apt-get install libgtk3.0 libdbus-glib-1-2

You may also want to install a couple of fonts, like ttf-mscorefonts-installer from the contrib repository.

FIXME: may hang on systemd-tty-ask-password-agent --watch for rtkit & dbus installation...

PulseAudio

PulseAudio may not refresh the device list because udev isn't available in the container.

The devices may be forcibly fetched again by using:

pacmd unload-module module-udev-detect
pacmd load-module module-udev-detect
KVM & QEMU

Enabling KVM in the LXC is similar:

lxc.cgroup.devices.allow = c 10:232 rwm
lxc.hook.autodev = sh -c 'mknod "$LXC_ROOTFS_MOUNT"/dev/kvm c 10 232'

To create TAP devices, access to /dev/net/tun is required (don't forget to add the directory to the fstab):

lxc.cgroup.devices.allow = c 10:200 rwm
lxc.mount.entry = /dev/net mnt/dev/net none bind,create=dir
⚠️ **GitHub.com Fallback** ⚠️