[Guide] Jellyfin + remote network shares + HW transcoding with Intel's QSV + unprivileged LXC

Thanks for the guide, it was very helpful.

I managed to get iGPU passthrough working on a Jellyfin LXC with my `AMD Ryzen 9 7940HS w/ Radeon 780M Graphics` processor. The steps for me were slightly different. It took some hours of problem solving (aka trial and error) for me to get it going, so I am sharing my steps here for the benefit of anyone in the same predicament.

I recommend taking regular snapshots during this process so you can revert to a previous state if anything goes wrong.



1. Set up Debian 12 LXC, GPU passthrough and media bind mounts as above​

Make sure your hardware is supported by your Proxmox host kernel. You can check your kernel with:

Bash:
proxmox-boot-tool kernel list

Version `6.8.4-3-pve` is working for me. I didn't have to install any mad packages or hacks.

For the device mapping I used this guide, which is more complicated but doesn't require you to change device owner on the Proxmox host:

https://www.youtube.com/watch?v=0ZDr5h52OOE&t=702s

My mappings look like this (`/etc/pve/lxc/[123].conf`):

Code:
lxc.cgroup2.devices.allow: c 226:0 rwm
lxc.cgroup2.devices.allow: c 226:128 rwm
lxc.mount.entry: /dev/dri/renderD128 dev/dri/renderD128 none bind,optional,create=file
lxc.idmap: u 0 100000 65536
lxc.idmap: g 0 100000 44
lxc.idmap: g 44 44 1
lxc.idmap: g 106 104 1
lxc.idmap: g 107 100107 65429

Where group 106 is the render group in my container and 104 is the render group on Proxmox. The video group is 44 in both environments.

2. Install Libva package from Github​

The installation steps are described here: https://github.com/intel/libva

It's better to copy commands from an official source than an internet forum, but here they are from my Bash history:

Bash:
apt update -y && apt upgrade -y

apt-get install git cmake pkg-config meson libdrm-dev automake libtool

git clone https://github.com/intel/libva.git
cd libva

./autogen.sh --prefix=/usr --libdir=/usr/lib/x86_64-linux-gnu
make

make install

3. Install Jellyfin​

Same as in the OP. The steps are documented here: https://jellyfin.org/docs/general/installation/linux/

My Bash history:

Bash:
apt install curl
curl https://repo.jellyfin.org/install-debuntu.sh | bash

4. Set group permissions for Jellyfin and Root user in LXC​

That's these commands on your LXC guest:

Bash:
usermod -aG video,render root
usermod -aG video,render jellyfin

And this command on your Proxmox host:

Bash:
usermod -aG render,video root

At this point I would reboot the container, just to be nice to it. It's been through a lot.

5. Verify device passthrough and driver on LXC​

By running the following command inside your container you should now see a list of codecs supported by your hardware:

Bash:
/usr/lib/jellyfin-ffmpeg/vainfo

The next verification step had me confused until I read the documentation. With AMD we are using the Vulkan driver rather than OpenVA: https://jellyfin.org/docs/general/administration/hardware-acceleration/amd

This command will verify that Vulkan driver is working with ffmpeg:

Bash:
/usr/lib/jellyfin-ffmpeg/ffmpeg -v debug -init_hw_device drm=dr:/dev/dri/renderD128 -init_hw_device vulkan@dr

Where /dev/dri/renderD128 is the path to your GPU.

This command will fail, which is fine:

Bash:
/usr/lib/jellyfin-ffmpeg/ffmpeg -v verbose -init_hw_device vaapi=va:/dev/dri/renderD128 -init_hw_device opencl@va

The driver is the last argument in the command (`vulkan@dr` vs `opencl@va`).

6. Jellyfin Transcoder Config​

For the hardware acceleration type choose `Video Acceleration API (VAAPI)`. Don't choose the AMD one because that won't work.

The output of the vainfo command from earlier will tell you which codecs to select:

Bash:
/usr/lib/jellyfin-ffmpeg/vainfo



Good luck!
 
Last edited:
I have just set-up Jellyfin on my N100 machine with Proxmox 8.2 and I found that setting up GPU passthrough is much simpler.

There is no need editing the config or user groups. All thats needed is to go to container's Resources tab in the web UI and add a Device Passthrough.
There, put the /dev/dri/renderD128 and fill in the GID of render group. Jellyfin adds its user account to render group automatically during installation, so it should work out of the box.
1721698978045.png



I had an issue with the passthrough not working initially, but it was due to GPU driver mismatch. I updated both host & container with the latest driver from https://github.com/intel/compute-runtime/releases and then it worked perfectly.

So basically all thats needed:
1) Setup passthrough as mentioned above
2) Mount NFS share (using mount point so container can stay unprivileged)
2) Install jellyfin
3) Potentially update the GPU drivers, if running
Code:
/usr/lib/jellyfin-ffmpeg/ffmpeg -v verbose -init_hw_device vaapi=va:/dev/dri/renderD128 -init_hw_device qsv=hw
gives errors in red about init failing.
 
EDIT: Issue found

adding 100000 does not mean change group id in container of render ^^

Hi,

I followed the instructions, but hardware transcoding keep failing. my current config/test output looks like this:

Hardware: intel i9-9900K
Proxmox: 8.2.4

lxc config
Code:
arch: amd64
cores: 4
features: nesting=1
hostname: jellyfin
memory: 4096
mp0: /mnt/video/,mp=/mnt/video
mp1: /mnt/music/,mp=/mnt/music
net0: name=eth0,bridge=vmbr0,firewall=1,gw=10.10.10.1,hwaddr=BC:24:11:5A:34:7E,ip=10.10.10.110/24,type=veth
onboot: 1
ostype: debian
rootfs: local-lvm:vm-110-disk-0,size=40G
swap: 512
unprivileged: 1
lxc.cgroup2.devices.allow: c 226:128 rwm
lxc.mount.entry: /dev/dri/renderD128 dev/dri/renderD128 none bind,optional,create=file
lxc.hook.pre-start: sh -c "chown 100000:100106 /dev/dri/renderD128"


/dev/dri on node
Code:
drwxr-xr-x 2 root   root         80 Aug 27 21:05 by-path
crw-rw---- 1 root   video  226,   0 Aug 27 21:05 card0
crw-rw---- 1 100000 100106 226, 128 Aug 27 21:05 renderD128

/etc/group on lxc
Code:
video:x:44:jellyfin
render:x:100106:jellyfin
jellyfin:x:112:


/usr/lib/jellyfin-ffmpeg/vainfo --display drm --device /dev/dri/renderD128
Code:
Trying display: drm
libva info: VA-API version 1.22.0
libva info: Trying to open /usr/lib/jellyfin-ffmpeg/lib/dri/iHD_drv_video.so
libva info: Found init function __vaDriverInit_1_22
libva info: va_openDriver() returns 0
vainfo: VA-API version: 1.22 (libva 2.22.0)
vainfo: Driver version: Intel iHD driver for Intel(R) Gen Graphics - 24.2.5 (12561f6)
vainfo: Supported profile and entrypoints
      VAProfileNone                   :    VAEntrypointVideoProc
      VAProfileNone                   :    VAEntrypointStats
      VAProfileMPEG2Simple            :    VAEntrypointVLD
      VAProfileMPEG2Simple            :    VAEntrypointEncSlice
      VAProfileMPEG2Main              :    VAEntrypointVLD
      VAProfileMPEG2Main              :    VAEntrypointEncSlice
      VAProfileH264Main               :    VAEntrypointVLD
      VAProfileH264Main               :    VAEntrypointEncSlice
      VAProfileH264Main               :    VAEntrypointFEI
      VAProfileH264Main               :    VAEntrypointEncSliceLP
      VAProfileH264High               :    VAEntrypointVLD
      VAProfileH264High               :    VAEntrypointEncSlice
      VAProfileH264High               :    VAEntrypointFEI
      VAProfileH264High               :    VAEntrypointEncSliceLP
      VAProfileVC1Simple              :    VAEntrypointVLD
      VAProfileVC1Main                :    VAEntrypointVLD
      VAProfileVC1Advanced            :    VAEntrypointVLD
      VAProfileJPEGBaseline           :    VAEntrypointVLD
      VAProfileJPEGBaseline           :    VAEntrypointEncPicture
      VAProfileH264ConstrainedBaseline:    VAEntrypointVLD
      VAProfileH264ConstrainedBaseline:    VAEntrypointEncSlice
      VAProfileH264ConstrainedBaseline:    VAEntrypointFEI
      VAProfileH264ConstrainedBaseline:    VAEntrypointEncSliceLP
      VAProfileVP8Version0_3          :    VAEntrypointVLD
      VAProfileVP8Version0_3          :    VAEntrypointEncSlice
      VAProfileHEVCMain               :    VAEntrypointVLD
      VAProfileHEVCMain               :    VAEntrypointEncSlice
      VAProfileHEVCMain               :    VAEntrypointFEI
      VAProfileHEVCMain10             :    VAEntrypointVLD
      VAProfileHEVCMain10             :    VAEntrypointEncSlice
      VAProfileVP9Profile0            :    VAEntrypointVLD
      VAProfileVP9Profile2            :    VAEntrypointVLD


/usr/lib/jellyfin-ffmpeg/ffmpeg -v verbose -init_hw_device vaapi=va:/dev/dri/renderD128 -init_hw_device opencl@va
Code:
ffmpeg version 6.0.1-Jellyfin Copyright (c) 2000-2023 the FFmpeg developers
  built with gcc 12 (Debian 12.2.0-14)
  configuration: --prefix=/usr/lib/jellyfin-ffmpeg --target-os=linux --extra-version=Jellyfin --disable-doc --disable-ffplay --disable-ptx-compression --disable-static --disable-libxcb --disable-sdl2 --disable-xlib --enable-lto --enable-gpl --enable-version3 --enable-shared --enable-gmp --enable-gnutls --enable-chromaprint --enable-opencl --enable-libdrm --enable-libxml2 --enable-libass --enable-libfreetype --enable-libfribidi --enable-libfontconfig --enable-libbluray --enable-libmp3lame --enable-libopus --enable-libtheora --enable-libvorbis --enable-libopenmpt --enable-libdav1d --enable-libsvtav1 --enable-libwebp --enable-libvpx --enable-libx264 --enable-libx265 --enable-libzvbi --enable-libzimg --enable-libfdk-aac --arch=amd64 --enable-libshaderc --enable-libplacebo --enable-vulkan --enable-vaapi --enable-amf --enable-libvpl --enable-ffnvcodec --enable-cuda --enable-cuda-llvm --enable-cuvid --enable-nvdec --enable-nvenc
  libavutil      58.  2.100 / 58.  2.100
  libavcodec     60.  3.100 / 60.  3.100
  libavformat    60.  3.100 / 60.  3.100
  libavdevice    60.  1.100 / 60.  1.100
  libavfilter     9.  3.100 /  9.  3.100
  libswscale      7.  1.100 /  7.  1.100
  libswresample   4. 10.100 /  4. 10.100
  libpostproc    57.  1.100 / 57.  1.100
[AVHWDeviceContext @ 0x594411c29480] libva: VA-API version 1.22.0
[AVHWDeviceContext @ 0x594411c29480] libva: Trying to open /usr/lib/jellyfin-ffmpeg/lib/dri/iHD_drv_video.so
[AVHWDeviceContext @ 0x594411c29480] libva: Found init function __vaDriverInit_1_22
[AVHWDeviceContext @ 0x594411c29480] libva: va_openDriver() returns 0
[AVHWDeviceContext @ 0x594411c29480] Initialised VAAPI connection: version 1.22
[AVHWDeviceContext @ 0x594411c29480] VAAPI driver: Intel iHD driver for Intel(R) Gen Graphics - 24.2.5 (12561f6).
[AVHWDeviceContext @ 0x594411c29480] Driver not found in known nonstandard list, using standard behaviour.
[AVHWDeviceContext @ 0x594411c4eec0] 0.0: Intel(R) OpenCL HD Graphics / Intel(R) UHD Graphics 630 [0x3e98]
[AVHWDeviceContext @ 0x594411c4eec0] Intel QSV to OpenCL mapping function found (clCreateFromVA_APIMediaSurfaceINTEL).
[AVHWDeviceContext @ 0x594411c4eec0] Intel QSV in OpenCL acquire function found (clEnqueueAcquireVA_APIMediaSurfacesINTEL).
[AVHWDeviceContext @ 0x594411c4eec0] Intel QSV in OpenCL release function found (clEnqueueReleaseVA_APIMediaSurfacesINTEL).
Hyper fast Audio and Video encoder
usage: ffmpeg [options] [[infile options] -i infile]... {[outfile options] outfile}...

Transcoding settings
1724791024347.png


protocol of failed transcoding:

Code:
{"Protocol":0,"Id":"7b119d6bcc364019545ee6d9212d9751","Path":"/mnt/video/Filme/Movie123.mkv","EncoderPath":null,"EncoderProtocol":null,"Type":0,"Container":"mkv","Size":11498973701,"Name":"Movie123","IsRemote":false,"ETag":"924b52b5063b156933ff97c3cf2bfed0","RunTimeTicks":83975560000,"ReadAtNativeFramerate":false,"IgnoreDts":false,"IgnoreIndex":false,"GenPtsInput":false,"SupportsTranscoding":true,"SupportsDirectStream":true,"SupportsDirectPlay":true,"IsInfiniteStream":false,"RequiresOpening":false,"OpenToken":null,"RequiresClosing":false,"LiveStreamId":null,"BufferMs":null,"RequiresLooping":false,"SupportsProbing":true,"VideoType":0,"IsoType":null,"Video3DFormat":null,"MediaStreams":[{"Codec":"hevc","CodecTag":null,"Language":null,"ColorRange":null,"ColorSpace":null,"ColorTransfer":null,"ColorPrimaries":null,"DvVersionMajor":null,"DvVersionMinor":null,"DvProfile":null,"DvLevel":null,"RpuPresentFlag":null,"ElPresentFlag":null,"BlPresentFlag":null,"DvBlSignalCompatibilityId":null,"Comment":null,"TimeBase":"1/1000","CodecTimeBase":null,"Title":null,"VideoRange":1,"VideoRangeType":1,"VideoDoViTitle":null,"AudioSpatialFormat":0,"LocalizedUndefined":null,"LocalizedDefault":null,"LocalizedForced":null,"LocalizedExternal":null,"LocalizedHearingImpaired":null,"DisplayTitle":"1080p HEVC SDR","NalLengthSize":null,"IsInterlaced":false,"IsAVC":false,"ChannelLayout":null,"BitRate":10954590,"BitDepth":10,"RefFrames":1,"PacketLength":null,"Channels":null,"SampleRate":null,"IsDefault":true,"IsForced":false,"IsHearingImpaired":false,"Height":804,"Width":1920,"AverageFrameRate":23.976025,"RealFrameRate":23.976025,"Profile":"Main 10","Type":1,"AspectRatio":"2.40:1","Index":0,"Score":null,"IsExternal":false,"DeliveryMethod":null,"DeliveryUrl":null,"IsExternalUrl":null,"IsTextSubtitleStream":false,"SupportsExternalStream":false,"Path":null,"PixelFormat":"yuv420p10le","Level":186,"IsAnamorphic":false},{"Codec":"aac","CodecTag":null,"Language":"ger","ColorRange":null,"ColorSpace":null,"ColorTransfer":null,"ColorPrimaries":null,"DvVersionMajor":null,"DvVersionMinor":null,"DvProfile":null,"DvLevel":null,"RpuPresentFlag":null,"ElPresentFlag":null,"BlPresentFlag":null,"DvBlSignalCompatibilityId":null,"Comment":null,"TimeBase":"1/1000","CodecTimeBase":null,"Title":"Stereo","VideoRange":0,"VideoRangeType":0,"VideoDoViTitle":null,"AudioSpatialFormat":0,"LocalizedUndefined":null,"LocalizedDefault":"Standard","LocalizedForced":null,"LocalizedExternal":"Extern","LocalizedHearingImpaired":null,"DisplayTitle":"Stereo - Ger - AAC - Standard","NalLengthSize":null,"IsInterlaced":false,"IsAVC":false,"ChannelLayout":"stereo","BitRate":192000,"BitDepth":null,"RefFrames":null,"PacketLength":null,"Channels":2,"SampleRate":48000,"IsDefault":true,"IsForced":false,"IsHearingImpaired":false,"Height":null,"Width":null,"AverageFrameRate":null,"RealFrameRate":null,"Profile":"LC","Type":0,"AspectRatio":null,"Index":1,"Score":null,"IsExternal":false,"DeliveryMethod":null,"DeliveryUrl":null,"IsExternalUrl":null,"IsTextSubtitleStream":false,"SupportsExternalStream":false,"Path":null,"PixelFormat":null,"Level":0,"IsAnamorphic":null},{"Codec":"aac","CodecTag":null,"Language":"ger","ColorRange":null,"ColorSpace":null,"ColorTransfer":null,"ColorPrimaries":null,"DvVersionMajor":null,"DvVersionMinor":null,"DvProfile":null,"DvLevel":null,"RpuPresentFlag":null,"ElPresentFlag":null,"BlPresentFlag":null,"DvBlSignalCompatibilityId":null,"Comment":null,"TimeBase":"1/1000","CodecTimeBase":null,"Title":"Stereo","VideoRange":0,"VideoRangeType":0,"VideoDoViTitle":null,"AudioSpatialFormat":0,"LocalizedUndefined":null,"LocalizedDefault":"Standard","LocalizedForced":null,"LocalizedExternal":"Extern","LocalizedHearingImpaired":null,"DisplayTitle":"Stereo - Ger - AAC","NalLengthSize":null,"IsInterlaced":false,"IsAVC":false,"ChannelLayout":"stereo","BitRate":192000,"BitDepth":null,"RefFrames":null,"PacketLength":null,"Channels":2,"SampleRate":48000,"IsDefault":false,"IsForced":false,"IsHearingImpaired":false,"Height":null,"Width":null,"AverageFrameRate":null,"RealFrameRate":null,"Profile":"LC","Type":0,"AspectRatio":null,"Index":2,"Score":null,"IsExternal":false,"DeliveryMethod":null,"DeliveryUrl":null,"IsExternalUrl":null,"IsTextSubtitleStream":false,"SupportsExternalStream":false,"Path":null,"PixelFormat":null,"Level":0,"IsAnamorphic":null},{"Codec":"aac","CodecTag":null,"Language":"eng","ColorRange":null,"ColorSpace":null,"ColorTransfer":null,"ColorPrimaries":null,"DvVersionMajor":null,"DvVersionMinor":null,"DvProfile":null,"DvLevel":null,"RpuPresentFlag":null,"ElPresentFlag":null,"BlPresentFlag":null,"DvBlSignalCompatibilityId":null,"Comment":null,"TimeBase":"1/1000","CodecTimeBase":null,"Title":"Stereo","VideoRange":0,"VideoRangeType":0,"VideoDoViTitle":null,"AudioSpatialFormat":0,"LocalizedUndefined":null,"LocalizedDefault":"Standard","LocalizedForced":null,"LocalizedExternal":"Extern","LocalizedHearingImpaired":null,"DisplayTitle":"Stereo - English - AAC","NalLengthSize":null,"IsInterlaced":false,"IsAVC":false,"ChannelLayout":"stereo","BitRate":192000,"BitDepth":null,"RefFrames":null,"PacketLength":null,"Channels":2,"SampleRate":48000,"IsDefault":false,"IsForced":false,"IsHearingImpaired":false,"Height":null,"Width":null,"AverageFrameRate":null,"RealFrameRate":null,"Profile":"LC","Type":0,"AspectRatio":null,"Index":3,"Score":null,"IsExternal":false,"DeliveryMethod":null,"DeliveryUrl":null,"IsExternalUrl":null,"IsTextSubtitleStream":false,"SupportsExternalStream":false,"Path":null,"PixelFormat":null,"Level":0,"IsAnamorphic":null},{"Codec":"aac","CodecTag":null,"Language":"eng","ColorRange":null,"ColorSpace":null,"ColorTransfer":null,"ColorPrimaries":null,"DvVersionMajor":null,"DvVersionMinor":null,"DvProfile":null,"DvLevel":null,"RpuPresentFlag":null,"ElPresentFlag":null,"BlPresentFlag":null,"DvBlSignalCompatibilityId":null,"Comment":null,"TimeBase":"1/1000","CodecTimeBase":null,"Title":"Stereo","VideoRange":0,"VideoRangeType":0,"VideoDoViTitle":null,"AudioSpatialFormat":0,"LocalizedUndefined":null,"LocalizedDefault":"Standard","LocalizedForced":null,"LocalizedExternal":"Extern","LocalizedHearingImpaired":null,"DisplayTitle":"Stereo - English - AAC","NalLengthSize":null,"IsInterlaced":false,"IsAVC":false,"ChannelLayout":"stereo","BitRate":192000,"BitDepth":null,"RefFrames":null,"PacketLength":null,"Channels":2,"SampleRate":48000,"IsDefault":false,"IsForced":false,"IsHearingImpaired":false,"Height":null,"Width":null,"AverageFrameRate":null,"RealFrameRate":null,"Profile":"LC","Type":0,"AspectRatio":null,"Index":4,"Score":null,"IsExternal":false,"DeliveryMethod":null,"DeliveryUrl":null,"IsExternalUrl":null,"IsTextSubtitleStream":false,"SupportsExternalStream":false,"Path":null,"PixelFormat":null,"Level":0,"IsAnamorphic":null}],"MediaAttachments":[],"Formats":[],"Bitrate":11722590,"Timestamp":null,"RequiredHttpHeaders":{},"TranscodingUrl":null,"TranscodingSubProtocol":0,"TranscodingContainer":null,"AnalyzeDurationMs":null,"DefaultAudioStreamIndex":null,"DefaultSubtitleStreamIndex":null}

/usr/lib/jellyfin-ffmpeg/ffmpeg -analyzeduration 200M -probesize 1G -init_hw_device vaapi=va:,kernel_driver=i915,driver=iHD -init_hw_device qsv=qs@va -filter_hw_device qs -noautorotate -i file:"/mnt/video/Filme/Movie123.mkv" -map_metadata -1 -map_chapters -1 -threads 0 -map 0:0 -map 0:1 -map -0:s -codec:v:0 h264_qsv -preset veryfast -look_ahead 0 -b:v 18257650 -maxrate 18257650 -bufsize 36515300 -g:v:0 72 -keyint_min:v:0 72 -vf "setparams=color_primaries=bt709:color_trc=bt709:colorspace=bt709,scale=trunc(min(max(iw\,ih*a)\,min(1920\,804*a))/2)*2:trunc(min(max(iw/a\,ih)\,min(1920/a\,804))/2)*2,format=nv12" -codec:a:0 libfdk_aac -ac 2 -ab 192000 -ar 48000 -copyts -avoid_negative_ts disabled -max_muxing_queue_size 2048 -f hls -max_delay 5000000 -hls_time 3 -hls_segment_type fmp4 -hls_fmp4_init_filename "f383ef50628c2fbcea82bade6818a47a-1.mp4" -start_number 0 -hls_segment_filename "/var/cache/jellyfin/transcodes/f383ef50628c2fbcea82bade6818a47a%d.mp4" -hls_playlist_type vod -hls_list_size 0 -y "/var/cache/jellyfin/transcodes/f383ef50628c2fbcea82bade6818a47a.m3u8"


ffmpeg version 6.0.1-Jellyfin Copyright (c) 2000-2023 the FFmpeg developers
  built with gcc 12 (Debian 12.2.0-14)
  configuration: --prefix=/usr/lib/jellyfin-ffmpeg --target-os=linux --extra-version=Jellyfin --disable-doc --disable-ffplay --disable-ptx-compression --disable-static --disable-libxcb --disable-sdl2 --disable-xlib --enable-lto --enable-gpl --enable-version3 --enable-shared --enable-gmp --enable-gnutls --enable-chromaprint --enable-opencl --enable-libdrm --enable-libxml2 --enable-libass --enable-libfreetype --enable-libfribidi --enable-libfontconfig --enable-libbluray --enable-libmp3lame --enable-libopus --enable-libtheora --enable-libvorbis --enable-libopenmpt --enable-libdav1d --enable-libsvtav1 --enable-libwebp --enable-libvpx --enable-libx264 --enable-libx265 --enable-libzvbi --enable-libzimg --enable-libfdk-aac --arch=amd64 --enable-libshaderc --enable-libplacebo --enable-vulkan --enable-vaapi --enable-amf --enable-libvpl --enable-ffnvcodec --enable-cuda --enable-cuda-llvm --enable-cuvid --enable-nvdec --enable-nvenc
  libavutil      58.  2.100 / 58.  2.100
  libavcodec     60.  3.100 / 60.  3.100
  libavformat    60.  3.100 / 60.  3.100
  libavdevice    60.  1.100 / 60.  1.100
  libavfilter     9.  3.100 /  9.  3.100
  libswscale      7.  1.100 /  7.  1.100
  libswresample   4. 10.100 /  4. 10.100
  libpostproc    57.  1.100 / 57.  1.100
[AVHWDeviceContext @ 0x606ce5953fc0] No VA display found for any default device.
Device creation failed: -22.
Failed to set value 'vaapi=va:,kernel_driver=i915,driver=iHD' for option 'init_hw_device': Invalid argument
Error parsing global options: Invalid argument

I really don't know what could be the reason.
 
Last edited:
Hey Tina,

Glad you got it working. This method does get it going but there is a better and cleaner way of doing it that wont cause your /dev/dri/renderD128 gid and uid on the proxmox host to be change to 100000 and 100106, that way you can easily use the iGPU or dGPU for another lxc without having to jump through hoops later,

I recommend this ONLY IF the uid/gid of video and render on your host id are 44 and 104 and the uid and gid of video and render on the lxc are 44 and 106 that you do this instead to your lxc.conf

lxc.idmap: u 0 100000 65536
lxc.idmap: g 0 100000 44
lxc.idmap: g 44 44 1
lxc.idmap: g 45 100045 61
lxc.idmap: g 106 104 1
lxc.idmap: g 107 100107 65429
lxc.cgroup2.devices.allow: c 226:0 rwm
lxc.cgroup2.devices.allow: c 226:128 rwm
lxc.mount.entry: /dev/dri/card0 dev/dri/card0 none bind,optional,create=file
lxc.mount.entry: /dev/dri/renderD128 dev/dri/renderD128 none bind,optional,create=file


you do not need to add the line
lxc.hook.pre-start: sh -c "chown 100000:100106 /dev/dri/renderD128


make sure you add to /etc/subuid & /etc/subgid on the proxmox host
root:44:1
root:104:1
 
Last edited:
This method does get it going but there is a better and cleaner way of doing it that wont cause your /dev/dri/renderD128 gid and uid on the proxmox host to be change to 100000 and 100106, that way you can easily use the iGPU or dGPU for another lxc without having to jump through hoops later,

I'm not super familiar with LXC UID mappings. If on my proxmox host I get:

# ls -l /dev/dri

crw-rw---- 1 root video 226, 1 Aug 20 23:32 card1
crw-rw---- 1 root render 226, 128 Aug 20 23:32 renderD128

# cat /etc/group

video:x:44
render:x:103


Is the following OK?

# nano /etc/pve/lxc/<lxc_id>.conf

lxc.idmap: u 0 100000 65536
lxc.idmap: g 0 100000 44
lxc.idmap: g 44 44 1
lxc.idmap: g 45 100045 61
lxc.idmap: g 106 103 1
lxc.idmap: g 107 100107 65429
lxc.cgroup2.devices.allow: c 226:1 rwm
lxc.cgroup2.devices.allow: c 226:128 rwm
lxc.mount.entry: /dev/dri/card1 dev/dri/card1 none bind,optional,create=file
lxc.mount.entry: /dev/dri/renderD128 dev/dri/renderD128 none bind,optional,create=file

# nano /etc/subuid

root:44:1
root:103:1

# nano /etc/subgid

root:44:1
root:103:1
 
Last edited:
I've been trying to get this to work but I keep getting an error when trying to start up my Jellyfin container. The error I'm getting is the following:
Code:
run_buffer: 571 Script exited with status 17
lxc_setup: 3948 Failed to run autodev hooks
do_start: 1273 Failed to setup container "101"
sync_wait: 34 An error occurred in another process (expected sequence number 4)
__lxc_start: 2114 Failed to spawn container "101"
TASK ERROR: startup for container '101' failed

After some trial-and-error I've pinpointed the error to this line of code: lxc.mount.entry: /dev/dri/renderD128 dev/dri/renderD128 none bind,optional,create=file. Removing this line from 101.conf enables the container to start normally.

My 101.conf looks like this:
Code:
lxc.idmap: u 0 100000 65536
lxc.idmap: g 0 100000 44
lxc.idmap: g 44 44 1
lxc.idmap: g 104 104 1
lxc.cgroup2.devices.allow: c 226:1 rwm
lxc.cgroup2.devices.allow: c 226:128 rwm
# lxc.mount.entry: /dev/dri/renderD128 dev/dri/renderD128 none bind,optional,create=file

I've also added the root:44:1 and root:104:1 to my host /etc/subuid and /etc/subgid.

Anyone who can help me figure this one out?
 
I'm not super familiar with LXC UID mappings. If on my proxmox host I get:

# ls -l /dev/dri

crw-rw---- 1 root video 226, 1 Aug 20 23:32 card1
crw-rw---- 1 root render 226, 128 Aug 20 23:32 renderD128

# cat /etc/group

video:x:44
render:x:103


Is the following OK?

# nano /etc/pve/lxc/<lxc_id>.conf

lxc.idmap: u 0 100000 65536
lxc.idmap: g 0 100000 44
lxc.idmap: g 44 44 1
lxc.idmap: g 45 100045 61
lxc.idmap: g 106 103 1
lxc.idmap: g 107 100107 65429
lxc.cgroup2.devices.allow: c 226:1 rwm
lxc.cgroup2.devices.allow: c 226:128 rwm
lxc.mount.entry: /dev/dri/card1 dev/dri/card1 none bind,optional,create=file
lxc.mount.entry: /dev/dri/renderD128 dev/dri/renderD128 none bind,optional,create=file

# nano /etc/subuid

root:44:1
root:103:1

# nano /etc/subgid

root:44:1
root:103:1
Hey sorry for the late reply,

This looks like it would be ok. Does everything seem to be working in order?

I think this line
lxc.idmap: g 45 100045 61

you would have to put either 62 or 60 instead of 61 if it wasnt working for you
 
Last edited:
I've been trying to get this to work but I keep getting an error when trying to start up my Jellyfin container. The error I'm getting is the following:
Code:
run_buffer: 571 Script exited with status 17
lxc_setup: 3948 Failed to run autodev hooks
do_start: 1273 Failed to setup container "101"
sync_wait: 34 An error occurred in another process (expected sequence number 4)
__lxc_start: 2114 Failed to spawn container "101"
TASK ERROR: startup for container '101' failed

After some trial-and-error I've pinpointed the error to this line of code: lxc.mount.entry: /dev/dri/renderD128 dev/dri/renderD128 none bind,optional,create=file. Removing this line from 101.conf enables the container to start normally.

My 101.conf looks like this:
Code:
lxc.idmap: u 0 100000 65536
lxc.idmap: g 0 100000 44
lxc.idmap: g 44 44 1
lxc.idmap: g 104 104 1
lxc.cgroup2.devices.allow: c 226:1 rwm
lxc.cgroup2.devices.allow: c 226:128 rwm
# lxc.mount.entry: /dev/dri/renderD128 dev/dri/renderD128 none bind,optional,create=file

I've also added the root:44:1 and root:104:1 to my host /etc/subuid and /etc/subgid.

Anyone who can help me figure this one out?
can you
Code:
ls -l /dev/dri
and tell us what the output is
 
Hey sorry for the late reply,

This looks like it would be ok. Does everything seem to be working in order?

I think this line
lxc.idmap: g 45 100045 61

you would have to put either 62 or 60 instead of 61 if it wasn't working for you

Using this lxc-idmap tool I was able to confirm the correctness of my configuration.
However, I tried and the container starts fine but it seems like it doesn't have full root access to the renderD128 device and the following command:

# vainfo --display drm --device /dev/dri/renderD128

fails.

The only difference I can see between the lxc.hook.pre-start and the lxc.idmap configurations is the following:

Host hook: crw-rw---- 1 100000 100106 226, 128 Sep 14 02:20 renderD128
Container hook: crw-rw---- 1 root render 226, 128 Sep 14 02:20 renderD128

Host idmap: crw-rw---- 1 root render 226, 128 Sep 14 02:20 renderD128
Container idmap: crw-rw---- 1 nobody render 226, 128 Sep 14 02:20 renderD128
 
Using this lxc-idmap tool I was able to confirm the correctness of my configuration.
However, I tried and the container starts fine but it seems like it doesn't have full root access to the renderD128 device and the following command:

# vainfo --display drm --device /dev/dri/renderD128

fails.

The only difference I can see between the lxc.hook.pre-start and the lxc.idmap configurations is the following:

Host hook: crw-rw---- 1 100000 100106 226, 128 Sep 14 02:20 renderD128
Container hook: crw-rw---- 1 root render 226, 128 Sep 14 02:20 renderD128

Host idmap: crw-rw---- 1 root render 226, 128 Sep 14 02:20 renderD128
Container idmap: crw-rw---- 1 nobody render 226, 128 Sep 14 02:20 renderD128
Try running this command in the lxc instead

/usr/lib/jellyfin-ffmpeg/vainfo --display drm --device /dev/dri/renderD128

& This

/usr/lib/jellyfin-ffmpeg/ffmpeg -v verbose -init_hw_device vaapi=va:/dev/dri/renderD128 -init_hw_device opencl@va
 
Last edited:
Try running this command in the lxc instead

/usr/lib/jellyfin-ffmpeg/vainfo --display drm --device /dev/dri/renderD128

& This

/usr/lib/jellyfin-ffmpeg/ffmpeg -v verbose -init_hw_device vaapi=va:/dev/dri/renderD128 -init_hw_device opencl@va

I'm pretty sure the id mapping is correct and yet the LXC starts fine but then I still get the following error:

# /usr/lib/jellyfin-ffmpeg/vainfo --display drm --device /dev/dri/renderD128
Trying display: drm
Failed to open the given device!


I noticed the container renderD128 device has a nobody owner. Is this how it's supposed to be?

crw-rw---- 1 nobody render 226, 128 Sep 14 02:20 renderD128

I must be missing something but I have no idea what. So for now I will continue using the lxc.hook.pre-start method which works. I even found this article showing how to solve its main drawback of not being able to passthrough devices to multiple LXC.
 
Last edited:
I've been trying to get this to work but I keep getting an error when trying to start up my Jellyfin container. The error I'm getting is the following:
Code:
run_buffer: 571 Script exited with status 17
lxc_setup: 3948 Failed to run autodev hooks
do_start: 1273 Failed to setup container "101"
sync_wait: 34 An error occurred in another process (expected sequence number 4)
__lxc_start: 2114 Failed to spawn container "101"
TASK ERROR: startup for container '101' failed

After some trial-and-error I've pinpointed the error to this line of code: lxc.mount.entry: /dev/dri/renderD128 dev/dri/renderD128 none bind,optional,create=file. Removing this line from 101.conf enables the container to start normally.

My 101.conf looks like this:
Code:
lxc.idmap: u 0 100000 65536
lxc.idmap: g 0 100000 44
lxc.idmap: g 44 44 1
lxc.idmap: g 104 104 1
lxc.cgroup2.devices.allow: c 226:1 rwm
lxc.cgroup2.devices.allow: c 226:128 rwm
# lxc.mount.entry: /dev/dri/renderD128 dev/dri/renderD128 none bind,optional,create=file

I've also added the root:44:1 and root:104:1 to my host /etc/subuid and /etc/subgid.

Anyone who can help me figure this one out?
I have the same issue. Were you able to fix this?
 
Last edited:
I have the same issue. Were you able to fix this?
I ended up deleting that container and starting from scratch. I ended up using https://tteck.github.io/Proxmox/#jellyfin-media-server-lxc to set up my jellyfin server, which automatically set up my iGPU passthrough from the host to the unprivileged container. You may have to install some iGPU drivers on your proxmox host before you install this for it to work though; I'd already done so when I installed the container so I don't know if it's required or not.

After installing that LXC container, it was as easy as following the Jellyfin guide for hardware transcoding:
https://jellyfin.org/docs/general/administration/hardware-acceleration/#intel-qsv--va-api

I'm afraid I'm unable to help with restoring your broken container, but if you want to know any of the specific commands I ran to get it working on my new container, I'm sure I could dig those up.
 

About

The Proxmox community has been around for many years and offers help and support for Proxmox VE, Proxmox Backup Server, and Proxmox Mail Gateway.
We think our community is one of the best thanks to people like you!

Get your subscription!

The Proxmox team works very hard to make sure you are running the best software and getting stable updates and security enhancements, as well as quick enterprise support. Tens of thousands of happy customers have a Proxmox subscription. Get yours easily in our online shop.

Buy now!