Difficulty running X applications in unprivileged container

I tried following the blog post by Stéphane but got stuck at this error:

root@guibox:/# glxinfo
name of display: :0.0
libGL error: No matching fbConfigs or visuals found
libGL error: failed to load driver: swrast
Error: couldn't find RGB GLX visual or fbconfig

Looks like there might be an issue accessing the drivers. I’m using an Ubuntu 17.10 host with Nvidia 384.90 drivers.

My container config looks as follows:

lxc.include = /usr/share/lxc/config/ubuntu.common.conf
lxc.include = /usr/share/lxc/config/ubuntu.userns.conf
lxc.arch = x86_64

lxc.include = /etc/lxc/default.conf

lxc.idmap = u 0 100000 1000
lxc.idmap = g 0 100000 1000
lxc.idmap = u 1000 1000 1
lxc.idmap = g 1000 1000 1
lxc.idmap = u 1001 101001 64535
lxc.idmap = g 1001 101001 64535

lxc.rootfs.path = dir:/ssdpool/lxc/guibox
lxc.uts.name = guibox

lxc.mount.entry = tmpfs tmp tmpfs defaults   # https://github.com/lxc/lxc/issues/434
lxc.mount.entry = /dev/dri dev/dri none bind,optional,create=dir
lxc.mount.entry = /tmp/.X11-unix/ tmp/.X11-unix/ none bind,optional,create=dir
lxc.mount.entry = /home/adrian/.Xauthority home/gui/.Xauthority none bind,optional,create=dir

I basically threw everything I could find at it, but I don’t entirely know what I’m doing.

p.s. There is an apparent lack of up-to-date LXC documentation and examples. Will this change in the future, or are all efforts being put into LXD now, meaning LXC is no longer intended for direct use?

Hi Adrian,

You are running Ubuntu 17.10, which means that it may be with Wayland or X.Org.
But since you have the Nvidia closed-source drivers, you are running with X.Org.
Therefore, the instructions by Stephane apply here.

However, have a look at

for updated instructions that make use of features introduced in newer versions of LXD. It is simpler this way.

Have a go and I can guide you through any pitfalls.

Hello Simos,

thank you for your reply. Your blog was one of the first things I found when searching for the topic, but I’m using LXC without the LXD daemon, so unfortunately most of the advice doesn’t apply in my case.

However, it looks like I have gotten things to work now (unless it’s some fluke). I plan to post a reply tomorrow with the details, so others looking for an LXC solution can find it.

Alright, here is my little guide. It’s for an Ubuntu host with proprietary Nvidia drivers. I plan to create my own tech related blog, so maybe this will motivate me to finally do it and make an article out of this.

  zfs create tank/lxc/gbox

  # allow user's unprivileged container to be written there
  chown user:user /tank/lxc/gbox    
  # I pick OS identical to my host
  lxc-create -n gbox --dir /tank/lxc/gbox -t download -- -d ubuntu -r artful -a amd64    

  # Fix permissions for 1:1 uid binding (upcoming¹)
  sudo chown -R user:user /tank/lxc/gbox/home/ubuntu   

Edit .local/share/lxc/gbox/config:

# Distribution configuration
lxc.include = /usr/share/lxc/config/ubuntu.common.conf
lxc.include = /usr/share/lxc/config/ubuntu.userns.conf
lxc.arch = x86_64

# Container specific configuration
lxc.include = /etc/lxc/default.conf
lxc.rootfs.path = dir:/tank/lxc/gbox
lxc.uts.name = gbox

# ID mappings (u/g container_id host_id id_range)
lxc.idmap = u 0 100000 1000
lxc.idmap = g 0 100000 1000
lxc.idmap = u 1000 1000 1    # ¹Here we map container user 1000 to host user 1000
lxc.idmap = g 1000 1000 1    # This means that it's not quite as "unprivileged" as
                             # regular uid bindings.
lxc.idmap = u 1001 101001 64535
lxc.idmap = g 1001 101001 64535

# X11
lxc.mount.entry = /dev/dri dev/dri none bind,create=dir
lxc.mount.entry = /tmp/.X11-unix tmp/.X11-unix none bind,create=dir

# Cgroup access
# My container seems to work fine without these, but I've seen them in multiple guides/posts.
# "ls -l /dev/" to query the devices, then adopt the relevant cgroups
lxc.cgroup.devices.allow = c 195:* rwm    # /dev/nvidia0 /dev/nvidiactl /dev/nvidia-modeset
lxc.cgroup.devices.allow = c 226:* rwm    # /dev/dri/card0
lxc.cgroup.devices.allow = c 240:* rwm    # /dev/nvidia-uvm

# GPU drivers (acceleration)
lxc.mount.entry = /dev/nvidia0 dev/nvidia0 none bind,create=file
lxc.mount.entry = /dev/nvidiactl dev/nvidiactl none bind,create=file
lxc.mount.entry = /dev/nvidia-modeset dev/nvidia-modeset none bind,create=file
lxc.mount.entry = /dev/nvidia-uvm dev/nvidia-uvm none bind,create=file

# Important, give the container access to the drivers!
lxc.mount.entry = /usr/lib/nvidia-384/ usr/lib/nvidia-384/ none bind,create=dir

And finally:

    lxc-start -n gbox
    lxc-attach -n gbox
    passwd ubuntu
    usermod -aG sudo ubuntu
    su ubuntu
    export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/lib/nvidia-384"   # Add to ~/.bashrc if you want
    ./some_gl_app   # Should now hopefully find the libs and run!

I haven’t tested this extensively, but so far it seems to work. I’d like to hear from Stéphane if LXD does something similar under the hood, or if mounting the directory with the Nvidia libraries is not necessarily needed. Hope this helps someone stumbling over this in the future!

1 Like

This is nice! You can also get audio to work if you do the same with PulseAudio.

Something that I did not test, is to see whether Wayland will work here.