Freemallard's blog

Run graphical apps in lxd container

1 minute read Published: 2026-10-03

Here's a short tutorial on how to run graphical applications (games, etc) under LXC/LXD

Installation

install lxc and lxd packages on your system. On Gentoo simply:

doas emerge -a app-containers/lxc app-containers/lxd

Nota bene: lxc and lxd aren't the same thing, and lxd uses lxc containers. Probably even more confusing, all lxc-* commands (lxc-attach, lxc-start, lxc-copy, etc...) are pure lxc commands whereas: lxc [command]..., are lxd commands.

List of all explicitly installed packages

Here is the list of all packages installed on my arch container. Not all are required but are installed by default. I intended to use this as a gaming container, hence all the wine stuff.

arch-install-scripts
base
dhcpcd
diffutils
dpkg
ex-vi-compat
fd
groff
inetutils
less
logrotate
man-db
man-pages
mesa-utils
nano
netctl
openssh
pipewire
pipewire-alsa
protontricks
spirv-headers
spirv-tools
sudo
sysfsutils
texinfo
volk
vulkan-extra-layers
vulkan-extra-tools
vulkan-headers
vulkan-html-docs
vulkan-icd-loader
vulkan-profiles
vulkan-tools
vulkan-utility-libraries
vulkan-validation-layers
wget
which
wine
winetricks

Configuration

Below is the configuration of the lxd container I use to run GUI apps. Assuming you run wayland, xwayland and Pipewire+Alsa, you'll need a wayland socket, a xwayland (optional but highly recommended), and the pipewire socket The interesting part

Container configuration

# Template used to create this container: /usr/share/lxc/templates/lxc-download
# Parameters passed to the template: -d archlinux -r current -a amd64
# Template script checksum (SHA-1): 218ccdcaa38e3f62e3a17f53b119f34e1e57ea67
# For additional config options, please look at lxc.container.conf(5)

# Uncomment the following line to support nesting containers:
#lxc.include = /usr/share/lxc/config/nesting.conf
# (Be aware this has security implications)


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

# Container specific configuration
lxc.rootfs.path = dir:/var/lib/lxc/lxc-games-arch/rootfs
lxc.uts.name = lxc-games-arch

# Network configuration

lxc.net.0.type = veth
lxc.net.0.flags = up
lxc.net.0.link = br0

Waylandsocket:
     bind: container
     connect: unix:/run/user/1000/wayland-0
     gid: "1000"
     listen: unix:/mnt/wayland1/wayland-0
     mode: "0644"
     security.gid: "1000"
     security.uid: "1000"
     type: proxy
     uid: "1000"

XWaylandsocket:
     bind: container
     connect: unix:/tmp/.X11-unix/X1
     gid: "1000"
     listen: unix:/mnt/wayland1/X1
     mode: "0644"
     security.gid: "1000"
     security.uid: "1000"
     type: proxy
     uid: "1000"

pipewire_socket:
    bind: container
    connect: unix:/run/user/1000/pipewire-0
    gid: "1000"
    listen: unix:/mnt/.container_pipewire_socket
    mode: "0644"
    security.gid: "1000"
    security.uid: "1000"
    type: proxy
    uid: "1000"

Systemd unit file

To mount sockets automatically on container startup I wrote a simple bash script and a Sytemd unit file: /etc/systemd/system/mount-socket.service

[Unit]
Description=Mounting Wayland XWayland and pipewire sockets

[Service]
Type=oneshot
ExecStart=/home/lxc/mount_socket.sh

[Install]
WantedBy=multi-user.target

/home/lxc/mount_socket.sh

#!/bin/sh

mkdir -p /run/user/1000
ln -s /mnt/wayland1/wayland-0 /run/user/1000/wayland-0
ln -s /mnt/.container_pipewire_socket /run/user/1000/pipewire-0

mkdir -p /tmp/.X11-unix/
ln -s /mnt/wayland1/X1 /tmp/.X11-unix/X1