Skip to content

Instantly share code, notes, and snippets.

@yvesh
Created February 2, 2026 22:30
Show Gist options
  • Select an option

  • Save yvesh/463594f0d3e9174a8032f236a59f8a50 to your computer and use it in GitHub Desktop.

Select an option

Save yvesh/463594f0d3e9174a8032f236a59f8a50 to your computer and use it in GitHub Desktop.
CachyOS LXC Container for sway, hyprland or xorg with DRI, render, Sound, Input etc.
# Full working Arch Linux / CachyOS LXC container for Sway (Hyprland or any other Wayland window manager works too) with full performance
# Audio, libinput etc.. a lot of workarounds for wayland (XDG_RUNTIME_DIR.. etc.)
# Runs stable, you can tweak security further.
# For CachyOs start with the Archlinux LXC Template and "migrate" with the scripts to CachyOS.
# Template used to create this container: /usr/share/lxc/templates/lxc-download
# Parameters passed to the template: --dist archlinux --release current --arch 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
# Distribution configuration
lxc.include = /usr/share/lxc/config/common.conf
lxc.arch = x86_64
# Container specific configuration
lxc.rootfs.path = zfs:zpcachyos/lxc/sway_prod
lxc.uts.name = sway_prod
lxc.cgroup2.cpu.weight = 1000 # CPU prio
# Different Network configuration samples
# lxc.net.0.macvlan.mode = private
# lxc.net.0.link = veth-sway
lxc.net.0.type = veth
lxc.net.0.flags = up
lxc.net.0.name = eth0
lxc.net.0.veth.pair = veth-sway
# lxc.net.0.hwaddr = 10:66:6a:1e:e2:42
# lxc.net.0.type = ipvlan
# lxc.net.0.ipvlan.mode = l2
# lxc.net.0.flags = up
# lxc.net.0.veth.mode = router
# lxc.net.0.link = wlan0
# lxc.net.0.name = eth0
lxc.net.0.ipv4.address = 10.0.43.53/32
lxc.net.0.ipv4.gateway = 10.0.43.1
# lxc.network.type = macvlan
# lxc.network.flags = up
# lxc.network.link = eth0
# lxc.network.hwaddr = 4a:49:43:49:79:bd
# lxc.network.ipv4 = 10.0.42.53/24
# If you want to run an unprivileged container (Security)
# 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
# This is very open, you could also, go down the rabbit hole of configuring them one by one
lxc.cgroup2.devices.allow = a
# The other way (e.g. way more restrictive:
# lxc.cgroup2.devices.deny = a
# lxc.cgroup2.devices.allow = c 1:3 rwm # /dev/null
# lxc.cgroup2.devices.allow = c 1:5 rwm # /dev/zero
# lxc.cgroup2.devices.allow = c 1:7 rwm # /dev/full
# lxc.cgroup2.devices.allow = c 1:8 rwm # /dev/random
# lxc.cgroup2.devices.allow = c 1:9 rwm # /dev/urandom
# lxc.cgroup2.devices.allow = c 5:0 rwm # /dev/tty
# lxc.cgroup2.devices.allow = c 5:1 rwm # /dev/console
# lxc.cgroup2.devices.allow = c 226:* rwm # GPU (Direct Rendering)
# lxc.cgroup2.devices.allow = c 116:* rwm # ALSA (Sound)
# lxc.cgroup2.devices.allow = c 13:* rwm # Input (Maus/Tastatur)
# This is also very open - all caps
# lxc.cap.keep = sys_admin sys_tty_config
lxc.cap.drop =
# This too
lxc.mount.auto = proc:mixed sys:ro cgroup:rw:force
# Disabling apparmor - you might want to enable it again and add a matching profile
lxc.apparmor.profile = unconfined
lxc.mount.entry = /sys/kernel/debug sys/kernel/debug none bind,optional 0 0
lxc.mount.entry = /sys/fs/fuse/connections sys/fs/fuse/connections none bind,optional 0 0
# GPU
lxc.mount.entry = /dev/dri dev/dri none bind,optional,create=dir 0 0
lxc.mount.entry = /dev/input dev/input none bind,optional,create=dir 0 0
lxc.mount.entry = /dev/snd dev/snd none bind,optional,create=dir 0 0
lxc.mount.entry = /dev/shm dev/shm none bind,optional,create=dir 0 0
lxc.mount.entry = /dev/net dev/net none bind,optional,create=dir 0 0
# We can't just add it to run/udev (gets overriden - we need to "bind" it in the container later, like with systemd-tmpfile)
lxc.mount.entry = /run/udev mnt/udev none bind,optional,create=dir 0 0
# Not really needed
lxc.mount.entry = /run/user/1000 run/user/1000 none bind,optional,create=dir 0 0
# TTYs, if you want to use wayland you need tty0.. because of seatd
# Else this whole is way easier and you can just use tty7 with lightdm / sddm
# or any xorg window manager.. Sway was really tough to get running, permissions, seatd, XDG etc.
lxc.mount.entry = /dev/tty0 dev/tty0 none bind,optional,create=file 0 0
lxc.mount.entry = /dev/tty4 dev/tty4 none bind,optional,create=file 0 0
lxc.mount.entry = /dev/tty7 dev/tty7 none bind,optional,create=file 0 0
# lxc.mount.entry = /dev/console dev/console none bind,optional,create=file 0 0
# Just a sample mount.. for example to have shared home profiles accross multiple containers
lxc.mount.entry = /home/user home/user none bind,create=dir 0 0
lxc.tty.max = 0
lxc.console.path = /dev/tty7
# For sway, makes things easier.. but it's not all you need
lxc.environment = XDG_RUNTIME_DIR=/run/user/1000
lxc.environment = XDG_SESSION_TYPE=wayland
lxc.environment = QT_QPA_PLATFORM=wayland
# Some network hook examples
lxc.hook.pre-start = sh -c "sysctl -w net.ipv4.ip_forward=1"
# Some other examples for KVM etc
# lxc.hook.autodev = sh -c 'mknod "$LXC_ROOTFS_MOUNT"/dev/tty7 c 4 7 && mknod "$LX_ROOTFS_MOUNT"/dev/kvm c 10 232'
# If you need NAT for working with WIFI (veth and proxy)
# Just a sample - adjust to your IPs
lxc.hook.start-host = sh -c "sysctl -w net.ipv4.conf.wlan0.proxy_arp=1 && sysctl -w net.ipv4.conf.veth-sway.proxy_arp=1 && sysctl -w net.ipv4.ip_forward=1 && ip a add 42.42.42.1/24 dev veth-sway && iptables -t nat -C POSTROUTING -o wlan0 -j MASQUERADE"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment