Difficulty running X applications in unprivileged container

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.

$root@host:
  zfs create tank/lxc/gbox

  # allow user's unprivileged container to be written there
  chown user:user /tank/lxc/gbox    
$user@host:
  # 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:

$user@host
    lxc-start -n gbox
    lxc-attach -n gbox
$root@gbox:
    passwd ubuntu
    usermod -aG sudo ubuntu
    su ubuntu
$ubuntu@gbox:
    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