The Sway config is here! And we can 3D render stuff!
Make sure the container is off to enable nesting. Enable nesting on the LXC so that you don’t get annoying logind timeouts
pct set 450 --features nesting=1
Step 1: Install sway and components
Since we will use WayVNC to talk to the machine, that will be included, waybar gives us something to click on.
Sway is to give a minimal “desktop” to work with when using UI applications on this LXC.
sudo apt update
sudo apt install -y sway wayland-protocols libgl1-mesa-dri mesa-utils xwayland waybar wayvnc
Why Sway? Initial experiments installing a full desktop environment proved rather complex. While possible, I want to start as small and lean as I can for this particular setup.
Step 2: Grant video,render permissions to iamnotroot
From the previous guide, we set up a user ‘iamnotroot’ just as a user account. We give them permissions on the card and render pipelines.
sudo usermod -aG video,render iamnotroot
Add the correct exports to .bashrc
cat << 'EOF' >> ~/.bashrc
# Set NVIDIA GPU exports for Wayland
export WLR_NO_HARDWARE_CURSORS=1
export LIBVA_DRIVER_NAME=nvidia
export XDG_SESSION_TYPE=wayland
export GBM_BACKEND=nvidia-drm
export __GLX_VENDOR_LIBRARY_NAME=nvidia
EOF
Step 3: Create a super basic waybar and sway config in user space
Pretty straight forward here, by default waybar shows a lot of features that don’t cleanly map to a headless LXC. This is meant to give you a starting place.
Please replace 0.0.0.0 with your actual lan address or tailscale ip.
# Create directory structures
mkdir -p ~/.config/sway ~/.config/waybar
# 1. Sway Configuration
cat << 'EOF' > ~/.config/sway/config
# Headless Sway Configuration for NVIDIA
# Force virtual headless output backend
output * bg #1e1e2e solid_color
# Force a standard virtual resolution for the headless output
output HEADLESS-1 mode 1920x1080@60Hz
# Disable input requirements since it's headless
input * {
xkb_layout us
}
exec waybar
# Please replace 0.0.0.0 with your actual LAN address
exec wayvnc 0.0.0.0 5900
# Set the modifier key to the Super/Windows key
set $mod Mod4
# Start a terminal (foot)
bindsym $mod+Return exec foot
# Kill focused window
bindsym $mod+Shift+q kill
# Reload the configuration file
bindsym $mod+Shift+c reload
EOF
# 2. Waybar Configuration
cat << 'EOF' > ~/.config/waybar/config
[
{
"layer": "top",
"position": "top",
"height": 34,
"modules-left": ["sway/workspaces", "sway/mode"],
"modules-center": ["sway/window"],
"modules-right": ["clock"],
"clock": {
"format": "{:%Y-%m-%d %H:%M}"
}
}
]
EOF
# 3. Waybar Styling (Catppuccin Mocha Palette)
cat << 'EOF' > ~/.config/waybar/style.css
* {
font-family: monospace;
font-size: 13px;
}
window#waybar {
background: rgba(17, 17, 27, 0.85);
color: #cdd6f4;
}
#workspaces button {
padding: 0 5px;
color: #6c7086;
}
#workspaces button.focused {
color: #89b4fa;
background: #313244;
}
#clock {
padding: 0 10px;
color: #89b4fa;
font-weight: bold;
}
EOF
Step 4: Systemd user service
Sway, by default, runs in a user space, and creates user sessions. Since this is headless, and we aren’t using something like SDDM we want the WayVNC to hook straight into the user session. This does mean authentication will be skipped over WayVNC and you should take steps to minimize risk. This guide will not help minimize it, this is more the “proof of concept”
mkdir -p ~/.config/systemd/user/
nano ~/.config/systemd/user/wayland-desktop.service
And configure as such:
[Unit]
Description=Sway Wayland Compositor (Headless NVIDIA)
Documentation=man:sway(5)
After=graphical-session-pre.target
PartOf=graphical-session.target
[Service]
Type=simple
Environment=WLR_BACKENDS=headless
Environment=WLR_LIBINPUT_NO_DEVICES=1
Environment=WLR_NO_HARDWARE_CURSORS=1
Environment=LIBVA_DRIVER_NAME=nvidia
Environment=XDG_SESSION_TYPE=wayland
Environment=GBM_BACKEND=nvidia-drm
Environment=__GLX_VENDOR_LIBRARY_NAME=nvidia
Environment=XDG_CURRENT_DESKTOP=sway
ExecStart=/usr/bin/sway --unsupported-gpu
Restart=on-failure
RestartSec=3s
[Install]
WantedBy=default.target
Now enable and reload the services.
systemctl --user enable --now wayland-desktop.service
Step 5: Validation
Connect to the VNC view port now and validate
WAYLAND_DISPLAY=wayland-1 glxinfo -B
For my GTX 1660 super, glxinfo gave me everything.
name of display: :0
display: :0 screen: 0
direct rendering: Yes
Memory info (GL_NVX_gpu_memory_info):
Dedicated video memory: 6144 MB
Total available memory: 6144 MB
Currently available dedicated video memory: 5734 MB
OpenGL vendor string: NVIDIA Corporation
OpenGL renderer string: NVIDIA GeForce GTX 1660 SUPER/PCIe/SSE2
OpenGL core profile version string: 4.6.0 NVIDIA 620.70.06
OpenGL core profile shading language version string: 4.60 NVIDIA
OpenGL core profile context flags: (none)
OpenGL core profile profile mask: core profile
OpenGL version string: 4.6.0 NVIDIA 620.70.06
OpenGL shading language version string: 4.60 NVIDIA
OpenGL context flags: (none)
OpenGL profile mask: (none)
OpenGL ES profile version string: OpenGL ES 3.2 NVIDIA 620.70.06
OpenGL ES profile shading language version string: OpenGL ES GLSL ES 3.20
And now check with glxgears (on a separate terminal, SSH into the box and run nvidia-smi to check GPU usage)
WAYLAND_DISPLAY=wayland-1 glxgears
With the gears running, on the SSH session, run nvidia-smi to confirm GPU utilization.
In my case it went from 0% to 24% - A WIN!
NEXT TIME: MakeMKV and Handbrake. Can we use them?