#!/bin/sh # Script to allow starting an X server inside an LXC container on ubuntu 16.04 # Run once OUTSIDE the container like this: # $0 host containername # and once INSIDE the container like this: # $0 guest # cf. # http://unix.stackexchange.com/questions/18003/linux-lxc-deploying-images-with-tiniest-possible-x11 # https://mraw.org/blog/2011/04/05/Running_X_from_LXC/ # http://unix.stackexchange.com/questions/191289/docker-how-to-run-x-desktop-in-a-container # https://github.com/ustuehler/lxc-desktop/blob/master/usr/share/lxc/hooks/desktop-autodev # http://www.joshh.info/2016/01/running-x-server-inside-docker-container.html set -x do_host() { container=$1; shift # Pass the devices through tee -a /var/lib/lxc/$container/config <<_EOF_ # Added by install-x.sh # Do not edit next line, the value of #use_x is sensed by bvslave-lxc.sh #use_x=1 lxc.cgroup.devices.allow = c 4:9 rwm # /dev/tty9 X Desktop lxc.cgroup.devices.allow = c 10:63 rwm # /dev/vga_arbiter lxc.cgroup.devices.allow = c 13:* rwm # /dev/input/* input devices lxc.cgroup.devices.allow = c 29:0 rwm # /dev/fb0 lxc.cgroup.devices.allow = c 226:0 rwm # /dev/dri/card0 lxc.cgroup.devices.allow = c 226:64 rwm # /dev/dri/controlD64 lxc.cgroup.devices.allow = c 226:128 rwm # /dev/dri/renderD128 # Proprietary drivers lxc.cgroup.devices.allow = c 195:* rwm # /dev/nvidia Graphics card _EOF_ } do_guest() { # Create entries for the devices mknod -m 666 /dev/tty9 c 4 9 mknod -m 666 /dev/vga_arbiter c 10 63 mkdir -p /dev/input chmod 755 /dev/input mknod -m 666 /dev/input/mice c 13 63 mknod -m 666 /dev/input/event0 c 13 64 mknod -m 666 /dev/input/event1 c 13 65 mknod -m 666 /dev/input/event2 c 13 66 mknod -m 666 /dev/input/event3 c 13 67 mknod -m 666 /dev/input/event4 c 13 68 mknod -m 666 /dev/input/event5 c 13 69 mknod -m 666 /dev/input/event6 c 13 70 mknod -m 666 /dev/input/event7 c 13 71 mknod -m 666 /dev/input/event8 c 13 72 mknod -m 666 /dev/input/event9 c 13 73 mknod -m 666 /dev/fb0 c 29 0 mkdir -p /dev/dri chmod 755 /dev/dri mknod -m 666 /dev/dri/card0 c 226 0 mknod -m 666 /dev/dri/controlD64 c 226 64 mknod -m 666 /dev/dri/renderD128 c 226 128 # Proprietary drivers mknod -m 666 /dev/nvidia0 c 195 0 mknod -m 666 /dev/nvidiactl c 195 255 set -e # Now install X... all the X. Well, all the free X. apt-get install -y \ pciutils \ mesa-utils \ xinit \ xterm \ xserver-xorg-input-evdev \ xserver-xorg-video-intel-dbg \ xserver-xorg-video-radeon-dbg \ xserver-xorg-video-amdgpu-dbg \ # if lspci | egrep -i "vga.*amd" then # On ati, we have to run X as root (so it can have at /proc/mtrr?), see # https://lists.linuxcontainers.org/pipermail/lxc-users/2016-September/012285.html # Setuid root xorg is still supported, but off to the side in xserver-xorg-legacy # So make sure that's installed, and # /etc/X11/Xwrapper.config is set to run X as root. if ! test -f /etc/X11/Xwrapper.config then sudo apt-get install -y xserver-xorg-legacy fi if ! grep "needs_root_rights = yes" /etc/X11/Xwrapper.config then cat > lines.txt.tmp <<_EOF_ allowed_users = anybody needs_root_rights = yes _EOF_ sudo cat lines.txt.tmp >> /etc/X11/Xwrapper.config fi fi cat > /usr/share/X11/xorg.conf.d/10-lxc-input.conf <<_EOF_ Section "ServerFlags" Option "AutoAddDevices" "False" EndSection _EOF_ ( cd /dev/input for input in event* do cat >> /usr/share/X11/xorg.conf.d/10-lxc-input.conf <<_EOF_ Section "InputDevice" Identifier "$input" Option "Device" "/dev/input/$input" Option "AutoServerLayout" "true" Driver "evdev" EndSection _EOF_ done ) echo "Test mouse input with 'cat /dev/input/mice' to verify you get garbage when the mouse moves." echo "Then create ~/.xinitrc containing the line 'exec xterm'" echo "Then start X with 'startx -- vt9'" echo "See https://lists.linuxcontainers.org/pipermail/lxc-users/2011-April/001817.html for more tips." echo "Problem: for some reason, with radeon, starting X inside lxc fails with" echo " Fatal server error: AddScreen/ScreenInit failed for driver 0" echo "Running startx as root works around this, but that's ugly." } case "$1" in host) shift; lxcname=$1; shift; do_host $lxcname;; guest) do_guest;; *) echo "usage: $0 [host lxc-container-name|guest]" esac