My Jellyfin config has some YAML like this.
# Sometimes work
devices:
- /dev/dri/renderD128:/dev/dri/renderD128
- /dev/dri/card0:/dev/dri/card0
Occasionally when I reboot my server, I end up with no card0 and instead I have /dev/dri/card1. This breaks my Jellyfin server…
I noticed there is also dri/by-path, which I’m guessing is a more stable path than a card index… however, doing this doesn’t work for me.
# No work
devices:
- /dev/dri/by-path/pci-0000:00:02.0-render:/dev/dri/renderD128
- /dev/dri/by-path/pci-0000:00:02.0-card:/dev/dri/card0
I tried with and without quotes and the result is the same. Error to start. I’m guessing Docker is failing to correctly parse the string because of the colons in pci-0000:00:02.0-card…
How’s everyone else handling this problem? I’ve been updating my compose.yaml every time the index switches, card0 to card1 to card0… but this is getting annoying now. (This is a worse problem now that I’m running Fedora IoT!)
Any thoughts?
Just mount
/dev/dri.The by-path approach is the right idea — the issue is that Docker’s
--devicesyntax splits on:, so the colons insidepci-0000:00:02.0-cardconfuse the parser (container_path gets mangled). Two things to try:-
Re-check the exact by-path filenames. They must match what’s actually in
/dev/dri/by-path/on your host — e.g. on Intel iGPU it’s usuallypci-0000:00:02.0-cardandpci-0000:00:02.0-render, but on some boards the PCI address differs. Runls -l /dev/dri/by-path/and confirm the symlink targets exist. -
Drop card entirely — you likely only need the render node. Modern VAAPI/QSV transcoding in Jellyfin works fine with just the render device, no
card0needed:
devices: - /dev/dri/by-path/pci-0000:00:02.0-render:/dev/dri/renderD128This is also the most robust fix for your reboot problem: the render node via by-path doesn’t shuffle between reboots, so your compose file stops breaking.
If you do still want card0 (some older setups use it), a workaround is a udev rule that creates a stable symlink, or a small systemd unit that remaps device access at boot — but for Jellyfin, render-only is the common answer.
-
The colons in the by-path filename are not actually the problem – Docker device strings split on the first colon, so a host path containing colons works fine. The usual failure is that the by-path symlinks are not what you expect: for iGPU rendering there is often only a
-rendersymlink and no-cardone, and the card device may enumerate under a different PCI address than 00:02.0 depending on platform.Check what actually exists:
ls -l /dev/dri/by-path/If there is no
-cardentry for your GPU, that is why the second line fails. On many headless boxes you do not need card0 at all for VAAPI/QSV transcoding – renderD128 is the render node and is what Jellyfin actually uses. Try mounting only the render node:devices: - /dev/dri/by-path/pci-0000:00:02.0-render:/dev/dri/renderD128If your Jellyfin build still insists on a card node, the robust fix is a udev rule or rc.local that symlinks a stable name like
/dev/dri/card-stableto whichever cardN the iGPU landed on, matched by PCI ID via/sys/class/drm/card*/device/uevent. Reference the stable symlink in compose and it survives both reindexing and Fedora IoT imageless updates.The colons in the by-path filename are not actually the problem – Docker device strings split on the first colon, so a host path containing colons works fine. The usual failure is that the by-path symlinks are not what you expect: for iGPU rendering there is often only a
-rendersymlink and no-cardone, and the card device may enumerate under a different PCI address than 00:02.0 depending on platform.Check what actually exists:
ls -l /dev/dri/by-path/If there is no
-cardentry for your GPU, that is why the second line fails. On many headless boxes you do not need card0 at all for VAAPI/QSV transcoding – renderD128 is the render node and is what Jellyfin actually uses. Try mounting only the render node:devices: - /dev/dri/by-path/pci-0000:00:02.0-render:/dev/dri/renderD128If your Jellyfin build still insists on a card node, the robust fix is a udev rule or rc.local that symlinks a stable name like
/dev/dri/card-stableto whichever cardN the iGPU landed on, matched by PCI ID via/sys/class/drm/card*/device/uevent. Reference the stable symlink in compose and it survives both reindexing and Fedora IoT imageless updates.

