How to Configure GPU Passthrough for Linux Containers (LXC) on Proxmox

This post provides a step-by-step guide to passing through a GPU from Proxmox to a Linux Container (LXC), focusing on an unprivileged setup.

Backstory

Since my migration of my Plex and media services didn’t go well. This was due to some self-hosted services not working well with Kubernetes and Samba shares. There was an issue SQLite being server from net share. Didn’t want to put too much effort to setup Longhorn or any other block storage for Kubernetes I’ve decided to go with simpler option Linux Containers.

Requirements

  1. Proxmox >= 8.3.0
  2. Enabled IOMMU on both host and BIOS - you can find more here
  3. Host being able to use GPU

What are Linux Containers

Linux Containers are lightweight option to virtualize operating system on your host. They utilize Linux kernel features like namespaces and cgroups. Think of they as Docker Container but on a little bit higher level.

Keep in mind that they share the host system’s kernel, therefore, consume fewer resources and start faster.

Types of LXC

There are two types of Linux Containers.

Privileged Containers

These containers run as the root user on the host machine. This means that the root user inside the container has the same privileges as the root on the host. While this setup is simpler and might be necessary for some specific applications, it comes with a higher security risk as any breach inside the container could potentially lead to a breach on the host system.

Unprivileged Containers

These containers run with user namespaces that map container users to non-root host users. The root user inside the container is mapped to a non-root user on the host, enhancing security by limiting the potential impact of a breach. Unprivileged containers are recommended for most setups due to their increased security.

Why Share a GPU with LXC?

In my setup, utilizing my Intel GPU for Plex transcoding was crucial to achieving optimal performance. By enabling GPU hardware transcoding, my system could handle four simultaneous 4K transcodings efficiently, with minimal fan noise. Keeping the container unprivileged added another layer of security without sacrificing performance.

Why another tutorial?

I spent two weekends trying to figure it out. I followed official Proxmox’s Wiki, many tutorials like:

  1. Proxmox GPU Passthrough on Unprivileged LXC Containers
  2. Setting up Intel GPU passthrough on Proxmox LXC containers
  3. Even Nvidia GPU Passthrough to LXC Container in Proxmox.
  4. And PCI/GPU Passthrough on Proxmox VE 8 : Installation and configuration

None of them worked for my case. Mostly because I don’t fully understand mapping between host and container UIDs and GUIDs resulting in missing privileges to use GPU by LXCs.

Solution

Finally I’ve realized that there is an option that was never mentioned:

proxmox-add-device-passthrough.png
Option to add device passthrough using Proxmox GUI

Make sure you have device enabled in your host

First we need to make sure that our host operation system has access and uses the GPU. To verify, look at the directory by running:

ls -lah /dev/dri

It should have similar structure as this:

drwxr-xr-x  3 root root        100 Dec  1 12:00 .
drwxr-xr-x 20 root root       4.7K Dec  1 13:49 ..
drwxr-xr-x  2 root root         80 Dec  1 12:00 by-path
crw-rw----  1 root video  226,   0 Dec  1 12:00 card0
crw-rw----  1 root render 226, 128 Dec  1 12:00 renderD128

The most important for us is the last item. renderD128 indicates that our GPU is up and running.

Now we want to share renderD128 device with the LXC. There is one more thing we need to know before final operation.

Know the id of render group

Before we do final operation we have to know the id of a render group. To do so we can exercise:

cat /etc/group | grep render

In result we can see that in my case the render group ID equals 104. Please note your ID down. We will need it later.

Add device Passthrough via Proxmox GUI

Since we have all necessary information now we can execute last operation:

  1. Go to: Host -> Linux Container -> Resources
  2. Add -> Device Passthrough
  3. Enter the device path, in my case /dev/dri/renderD128
  4. Check “Advanced” checkbox
  5. Fill “GID in CT” with your render group ID

Here is my final setup:

proxmox-add-device-passthrough-final.png
Device passthrough dialog window with device path, and guid values filled

Summary

This journey taught me a lot. Starting from handling drivers on the Proxmos (host) side, through my first actual interactions with Linux Containers, sharing permissions between host and LXCs. It was wonderful adventure for two weeks.

I would have never though that the solution would be so simple. No need to map IDs LXC and host. Proxmox does it great!