Container direct display X11 in host

It’s a summary of https://discuss.linuxcontainers.org/t/its-possible-to-run-containerlized-x11-without-nesting-or-vnc-or-rdp-but-i-need-help-with-input/

To do it, your incus/lxd server only need a mouse and a keyboard and a monitor and a gpu discrete or Integrated.

Use lspci | grep VGA to get the pci address, my is 00:02.0, add it to profile something like this:

config: {}
description: Hardware acceleration
devices:
  mygpu:
    gid: "44"
    gputype: physical
    mode: "0770"
    pci: 0000:00:0f.0
    type: gpu

Use ls -l /dev/input/by-path/ to get your mouse and keyboard address, here is mine:

pci-0000:00:15.0-usb-0:1:1.2-event-kbd → ../event1
pci-0000:00:15.0-usb-0:1:1.3-event-mouse → ../event2
pci-0000:00:15.0-usb-0:1:1.3-mouse → ../mouse0
pci-0000:00:15.0-usb-0:1:1.4-event → ../event3
platform-i8042-serio-0-event-kbd → ../event0
platform-INT33D5:00-event → ../event9
platform-pcspkr-event-spkr → ../event11

And I don’t know which one is which, so I add them all, with addition /run/udev/ and /dev/input/mice, and My container use debian 13, the gid of input is 995:

config: {}
description: input devices
devices:
  udev:
    path: /run/udev/
    source: /run/udev/
    type: disk
  mice:
    gid: "995"
    mode: "0666"
    path: /dev/input/mice
    source: /dev/input/mice
    required: "false"
    type: unix-char
  kbd-event-1:
    gid: "995"
    mode: "0666"
    path: /dev/input/event1
    source: pci-0000:00:15.0-usb-0:1:1.2-event-kbd
    required: "false"
    type: unix-char
  mouse-event:
    gid: "995"
    mode: "0666"
    path: /dev/input/event2
    source: pci-0000:00:15.0-usb-0:1:1.3-event-mouse
    required: "false"
    type: unix-char
  mouse:
    gid: "995"
    mode: "0666"
    path: /dev/input/mouse0
    source: pci-0000:00:15.0-usb-0:1:1.3-mouse
    required: "false"
    type: unix-char
  kbd-event-0:
    gid: "995"
    mode: "0666"
    path: /dev/input/event0
    source: /dev/input/by-path/platform-i8042-serio-0-event-kbd
    required: "false"
    type: unix-char
  INT33D5:
    gid: "995"
    mode: "0666"
    path: /dev/input/event9
    source: /dev/input/by-path/platform-INT33D5:00-event
    required: "false"
    type: unix-char
  dev-spkr:
    gid: "995"
    mode: "0666"
    path: /dev/input/event11
    source: /dev/input/by-path/platform-pcspkr-event-spkr
    required: "false"
    type: unix-char

Create a container, and add gpu profile to it, and install xorg and a desktop environment, I’m using mate.

apt install xorg --install-recommends -y
apt install mate-desktop-environment --no-install-recommends -y

This line you can read above link to know why:

sed -i ‘s/console/anybody/g’ /etc/X11/Xwrapper.config

Create a user with video and input group.

useradd -m -G video,sudo,input -s /bin/bash username

And exit container shell. And add input profile to it every time after it fresh started, so /run/udev/data/ is really containing host’s /run/udev/data/.

incus/lxc profile add containername input

because container x11 is not able to lock input as normal host started x11 does, so every keyboard input will also be applied to host tty, but tty7 doesn’t have a shell, so every keyboard input won’t be recived by host

chvt 7 | incus/lxc exec containername -- su -c “startx” username

And it’s impossible to run wayland this way.

2 Likes

Some changes.

For max capabilities, should change input device’s mode to 0777.

/run/udev should mount at /mnt/udev at container. Use this systemd mount to auto mount host’s /run/udev at container’s /run/udev:

nano /etc/systemd/system/run-udev.mount

[Unit]
Description=Bind mount /mnt/udev over /run/udev
After=systemd-udevd.service
RequiresMountsFor=/run/udev/data

[Mount]
What=/mnt/udev
Where=/run/udev
Type=bind
Options=bind

[Install]
WantedBy=multi-user.target

systemctl daemon-reload

systemctl enable run-udev.mount

systemctl start run-udev.mount

If you want container desktop environment to auto start after host started. Here is how:

In host:

Sudo nano /etc/systemd/system/autoswitch-to-tty7.service

[Unit]
Description=Auto Switch to TTY7
After=systemd-user-sessions.service

[Service]
Type=oneshot
ExecStart=/usr/bin/chvt 7

sudo systemctl daemon-reload

sudosystemctl enable autoswitch-to-tty7.service

In container:

sudo nano /etc/systemd/system/xorg-start.service

[Unit]
Description=Start X11 with startx
After=network.target
After=run-udev.mount

[Service]
Type=simple
Group=(USERNAME)
User=(USERNAME)
ExecStart=/usr/bin/startx
WorkingDirectory=/home/(USERNAME)
Restart=on-failure
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

Remember to change (USERNAME) to you ct username.

sudo systemctl daemon-reload

sudo systemctl enable xorg-start.service