Creating an LXD container for graphics applications

Setting up LXD containers for headless applications is pretty straight forward. Using the graphics display doesn’t work out of the box without additional setup. There are different ways to provide graphics access to a container and which one to choose depends on the need of the application. Is audio needed? Is hardware acceleration (OpenGL) needed? This all boils down to grant permission to host specific resources that isn’t there by default.

In general there are two means of providing resources to the container, either give access to the host resources through lxd device configurations or use network protocols. For basic graphics that don’t depend on hardware acceleration we can use the X server capability of accepting remote connections. That’s what we are going to use in this post to setup a container for running Firefox that can be launched as any regular application. It’s assumed that you have a basic LXD setup. See Using Linux containers and LXD.

Container setup

First we need a basic container setup.

lxc launch images:ubuntu/trusty/amd64 x11gfx
lxc exec x11gfx /bin/bash
apt-get install openssh-server firefox
adduser firefox
exit

X11 setup

X11 forwarding can be used through ssh by just giving the -X flag when invoking ssh. This will encrypt all X11 traffic which isn’t needed since no traffic will enter the network. Instead, we will enable X remote access on the host and make sure that the container can access it. Most Linux distributions these days doesn’t allow remote access to the X server by default. Depending on the distribution this is configured in different ways. The pure X11 way of setting this up is to modify /etc/X11/xinit/xserverrc. Simply remove the “-nolisten tcp” from this line in that file:

exec /usr/bin/X -nolisten tcp "$@"

Usually, starting the X server is controlled by the display manager of the system so the above will not work in that case. Linux Mint is using the Multi Display Manager (MDM) which is targeted below. Similar setup is done for other display managers, e.g. gdm. Add this to /etc/mdm/mdm.conf:

[security]
DisallowTCP=false

This will remove the “-nolisten tcp” command line flag when starting the X server. We also need to give the container access rights to the X server. Grab the ip adress of the container:

lxc info x11gfx | grep eth0
  eth0:   IPV4    10.0.3.9

Grant access rights with xhost:

xhost +10.0.3.9

Try that the setup works. The host ip address from the container is 10.0.3.1 in this setup:

ssh firefox@10.0.3.9 DISPLAY=10.0.3.1:0 firefox

To make this xhost settings stick after reboot, add the container to the /etc/X<N>.hosts file where <N> is typically 0 for display 0. Add to /etc/X0.hosts:

10.0.3.9

Application script

Create a startup script as follows:

#!/bin/sh

lxc start x11gfx &> /dev/null
ssh firefox@10.0.3.9 DISPLAY=10.0.3.1:0 firefox --no-remote

The --no-remote switch is needed to avoid that firefox opens up a new tab in an existing instance on the same X server, the host in this case. This is a quite surprising behavior which will override the purpose of the sandbox container. Anyway, the switch solves the problem. What’s left is that we don’t want to supply our password every time we start the browser. This can be solved in several ways. One solution is to add your ssh key to the container.

ssh-copy-id firefox@10.0.3.9

Desktop binding

The following desktop file will put your new sandboxed browser in the start menu:

[Desktop Entry]
Exec=/path/to/start_script
Icon=/home/user/icons/coolicon.png
Type=Application
Terminal=false
Comment=Run firefox in an LXD container
Name=Firebox
GenericName=Sandboxed Firefox
StartupNotify=false
Categories=Network;WebBrowser;

Put the above content in the file /usr/share/applications/firebox.desktop. I think this shall work for most distributions/desktop environments. It works on Ubuntu at least.

Next time we will look at audio.

For a follow up post that addresses some of the security issues with this setup, please have a look at Run LXD container apps on separate X server.

Tagged with: , , ,
Posted in linux
3 comments on “Creating an LXD container for graphics applications
  1. Alex says:

    Does removing exec -nolisten tcp open up the xserver to anything on the network?

    Maybe using the x2go server might be better.
    add-apt-repository ppa:x2go/stable
    apt-get update
    apt-get install x2goserver x2goserver-xsession

    Like

  2. Peter Gloor says:

    Great and most complete article about the topic I’ve come across. Actually all I was missing was the -X in the ssh command (grumble… grumble…). Thank you for sahring this!

    Like

Leave a comment