Video transcoding in nixos-container (intel)

I’m trying to run immich in a nixos-container but I can’t get the hardware acceleration transcoding to work. I’m using imperative containers to iterate before commiting a declarative config.

That the exact same service configuration works fine when run directly on the host.

  • I explicitely set the group and user ids to match the ids on the host
  • I have tried to chmod the device to 777 both on the host and in the container
  • I have sudo setfacl -m u:993:rw /dev/dri/renderD128 both on the host and the container

hardware acceleration is not working

I create the container like this

sudo nixos-container update immich --config '
  services.immich = {
    enable = true;
    openFirewall = true;
    host = "0.0.0.0";
    accelerationDevices=[ "/dev/dri/renderD128 ];
    environment.LIBVA_DRIVER_NAME = "iHD";
  };
  nixpkgs.config.allowUnfree = true; 
  users.users.immich = {
    extraGroups = [ "video" "render" ];
    uid = 993;
    group = "immich";
  }; 
  users.groups.immich = {
    gid = 991;
  };
  users.groups.video = {
    gid = 26;
  };
  users.groups.render = {
    gid = 303;
  };
  hardware.graphics = {
    enable = true;
    extraPackages = with pkgs; [
      intel-media-driver # For Broadwell (2014) or newer processors. LIBVA_DRIVER_NAME=iHD
      libva-vdpau-driver # Previously vaapiVdpau
      intel-compute-runtime # OpenCL filter support (hardware tonemapping and subtitle burn-in)
      vpl-gpu-rt # QSV on 11th gen or newer
      intel-ocl # OpenCL support
    ];
  };
  networking.firewall.allowedTCPPorts = [ 2283 ];
  environment.systemPackages = with pkgs; [
    clinfo
    libva-utils
    ffmpeg
    vim
  ];
  system.stateVersion = "25.05";
'

then start it

sudo nixos-container start immich

then bind mount the /dev/dri directory to the container

 sudo machinectl bind immich /dev/dri --mkdir 

then i change immich options to use hardware accelleration and forces transcoding for all videos.

in the immich-server logs when I upload a vide or ask to refresh the encoded videos of a video, I get this error :

[root@immich:~]# journalctl -u immich-server.service
Aug 29 13:28:38 immich immich[1177]: [Nest] 1177  - 08/29/2025, 1:28:38 PM     LOG [Microservices:MediaService] Transcoding video ac117f82-6281-4e8b-9d05-36f4143621b9 with VAAPI-accelerated encoding and software >
Aug 29 13:28:38 immich immich[1177]: [Nest] 1177  - 08/29/2025, 1:28:38 PM   ERROR [Microservices:MediaRepository] ffmpeg version 7.1.1-Jellyfin Copyright (c) 2000-2025 the FFmpeg developers
Aug 29 13:28:38 immich immich[1177]:   built with gcc 14.3.0 (GCC)
Aug 29 13:28:38 immich immich[1177]:   configuration: --disable-static --prefix=/nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-jellyfin-ffmpeg-7.1.1-1 --target_os=linux --arch=x86_64 --pkg-config=pkg-config --enable>
Aug 29 13:28:38 immich immich[1177]:   libavutil      59. 39.100 / 59. 39.100
Aug 29 13:28:38 immich immich[1177]:   libavcodec     61. 19.101 / 61. 19.101
Aug 29 13:28:38 immich immich[1177]:   libavformat    61.  7.100 / 61.  7.100
Aug 29 13:28:38 immich immich[1177]:   libavdevice    61.  3.100 / 61.  3.100
Aug 29 13:28:38 immich immich[1177]:   libavfilter    10.  4.100 / 10.  4.100
Aug 29 13:28:38 immich immich[1177]:   libswscale      8.  3.100 /  8.  3.100
Aug 29 13:28:38 immich immich[1177]:   libswresample   5.  3.100 /  5.  3.100
Aug 29 13:28:38 immich immich[1177]:   libpostproc    58.  3.100 / 58.  3.100
Aug 29 13:28:38 immich immich[1177]: [AVHWDeviceContext @ 0x1a9b9500] Failed to open /dev/dri/renderD128 as DRM device node.
Aug 29 13:28:38 immich immich[1177]: [AVHWDeviceContext @ 0x1a9b9500] Cannot open X11 display /dev/dri/renderD128.
Aug 29 13:28:38 immich immich[1177]: [AVHWDeviceContext @ 0x1a9b9500] No VA display found for device /dev/dri/renderD128.
Aug 29 13:28:38 immich immich[1177]: Device creation failed: -22.
Aug 29 13:28:38 immich immich[1177]: Failed to set value 'vaapi=accel:/dev/dri/renderD128' for option 'init_hw_device': Invalid argument
Aug 29 13:28:38 immich immich[1177]: Error parsing global options: Invalid argument
Aug 29 13:28:38 immich immich[1177]:
Aug 29 13:28:38 immich immich[1177]: [Nest] 1177  - 08/29/2025, 1:28:38 PM   ERROR [Microservices:MediaService] Error occurred during transcoding: ffmpeg exited with code 234: Device creation failed: -22.
Aug 29 13:28:38 immich immich[1177]: Failed to set value 'vaapi=accel:/dev/dri/renderD128' for option 'init_hw_device': Invalid argument
Aug 29 13:28:38 immich immich[1177]: Error parsing global options: Invalid argument
Aug 29 13:28:38 immich immich[1177]:
Aug 29 13:28:38 immich immich[1177]: [Nest] 1177  - 08/29/2025, 1:28:38 PM   ERROR [Microservices:MediaService] Retrying with VAAPI acceleration disabled
Aug 29 13:28:41 immich immich[1177]: [Nest] 1177  - 08/29/2025, 1:28:41 PM     LOG [Microservices:MediaService] Successfully encoded ac117f82-6281-4e8b-9d05-36f4143621b9

so the transcoding is not done using hardware acceleration
if I do the exact same thing on the host I get this log instead

[Microservices:MediaService] Transcoding video 24de7ffd-f475-48c0-93c8-79f4ce63d46a with VAAPI-accelerated encoding and decoding

If I root-login in the container, I see

[root@immich:~]# ll /dev/dri
total 0
drwxr-xr-x  2 root root        100 Aug 27 14:04 by-path
crwxrwxrwx  1 root video  226,   1 Aug 27 14:04 card1
crwxrwxrwx+ 1 root render 226, 128 Aug 27 14:04 renderD128
[root@immich:~]# clinfo
Number of platforms                               2
  Platform Name                                   Intel(R) OpenCL Graphics
  Platform Vendor                                 Intel(R) Corporation
  Platform Version                                OpenCL 3.0
  Platform Profile                                FULL_PROFILE
#[...] and a lot more output 
[root@immich:~]# ffmpeg -init_hw_device vaapi=accel:/dev/dri/renderD128
ffmpeg version 7.1.1 Copyright (c) 2000-2025 the FFmpeg developers
  built with gcc 14.3.0 (GCC)
  configuration: --disable-static --prefix=/nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-ffmpeg-7.1.1 --target_os=linux --arch=x86_64 --pkg-config=pkg-config --enable-gpl --enable-version3 --disable-nonfree --disable-static --enable-shared --enable-pic --disable-thumb --disable-small --enable-runtime-cpudetect --disable-gray --enable-swscale-alpha --enable-hardcoded-tables --enable-safe-bitstream-reader --enable-pthreads --disable-w32threads --disable-os2threads --enable-network --enable-pixelutils --datadir=/nix/store/vjjiqyr8cc526i765fm8s2v48b2g428x-ffmpeg-7.1.1-data/share/ffmpeg --enable-ffmpeg --enable-ffplay --enable-ffprobe --bindir=/nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-ffmpeg-7.1.1-bin/bin --enable-avcodec --enable-avdevice --enable-avfilter --enable-avformat --enable-avutil --enable-postproc --enable-swresample --enable-swscale --libdir=/nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-ffmpeg-7.1.1-lib/lib --incdir=/nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-ffmpeg-7.1.1-dev/include --enable-doc --enable-htmlpages --enable-manpages --mandir=/nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-ffmpeg-7.1.1-man/share/man --enable-podpages --enable-txtpages --docdir=/nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-ffmpeg-7.1.1-doc/share/doc/ffmpeg --enable-alsa --enable-amf --enable-libaom --disable-libaribb24 --disable-libaribcaption --enable-libass --disable-avisynth --enable-libbluray --disable-libbs2b --enable-bzlib --disable-libcaca --disable-libcdio --disable-libcelt --disable-chromaprint --disable-libcodec2 --disable-cuda --enable-cuda-llvm --disable-cuda-nvcc --enable-cuvid --enable-libdav1d --disable-libdc1394 --enable-libdrm --disable-libdvdnav --disable-libdvdread --disable-libfdk-aac --enable-ffnvcodec --disable-libflite --enable-fontconfig --enable-libfontconfig --enable-libfreetype --disable-frei0r --enable-libfribidi --disable-libgme --enable-gnutls --disable-libgsm --enable-libharfbuzz --enable-iconv --disable-libilbc --disable-libjack --disable-libjxl --disable-libkvazaar --disable-ladspa --disable-liblc3 --disable-liblcevc-dec --disable-lcms2 --enable-lzma --disable-metal --disable-libmfx --disable-libmodplug --enable-libmp3lame --disable-libmysofa --disable-libnpp --enable-nvdec --enable-nvenc --disable-openal --enable-opencl --disable-libopencore-amrnb --disable-libopencore-amrwb --disable-opengl --disable-libopenh264 --enable-libopenjpeg --enable-libopenmpt --enable-libopus --disable-libplacebo --enable-libpulse --disable-libqrencode --disable-libquirc --disable-librav1e --enable-librist --disable-librtmp --disable-librubberband --disable-libsmbclient --enable-sdl2 --disable-libshaderc --disable-libshine --disable-libsnappy --enable-libsoxr --enable-libspeex --enable-libsrt --enable-libssh --disable-librsvg --enable-libsvtav1 --disable-libtensorflow --enable-libtheora --disable-libtwolame --enable-libv4l2 --enable-v4l2-m2m --enable-vaapi --enable-vdpau --disable-libvpl --enable-libvidstab --disable-libvmaf --disable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-vulkan --disable-libvvenc --enable-libwebp --enable-libx264 --enable-libx265 --disable-libxavs --disable-libxcb --disable-libxcb-shape --disable-libxcb-shm --disable-libxcb-xfixes --disable-libxevd --disable-libxeve --disable-xlib --enable-libxml2 --enable-libxvid --enable-libzimg --enable-zlib --disable-libzmq --enable-libzvbi --disable-debug --enable-optimizations --disable-extra-warnings --disable-stripping
  libavutil      59. 39.100 / 59. 39.100
  libavcodec     61. 19.101 / 61. 19.101
  libavformat    61.  7.100 / 61.  7.100
  libavdevice    61.  3.100 / 61.  3.100
  libavfilter    10.  4.100 / 10.  4.100
  libswscale      8.  3.100 /  8.  3.100
  libswresample   5.  3.100 /  5.  3.100
  libpostproc    58.  3.100 / 58.  3.100
Universal media converter
usage: ffmpeg [options] [[infile options] -i infile]... {[outfile options] outfile}...
[root@immich:~]# sudo -u immich ffmpeg -init_hw_device vaapi=accel:/dev/dri/renderD128
ffmpeg version 7.1.1 Copyright (c) 2000-2025 the FFmpeg developers
  built with gcc 14.3.0 (GCC)
  configuration: --disable-static --prefix=/nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-ffmpeg-7.1.1 --target_os=linux --arch=x86_64 --pkg-config=pkg-config --enable-gpl --enable-version3 --disable-nonfree --disable-static --enable-shared --enable-pic --disable-thumb --disable-small --enable-runtime-cpudetect --disable-gray --enable-swscale-alpha --enable-hardcoded-tables --enable-safe-bitstream-reader --enable-pthreads --disable-w32threads --disable-os2threads --enable-network --enable-pixelutils --datadir=/nix/store/vjjiqyr8cc526i765fm8s2v48b2g428x-ffmpeg-7.1.1-data/share/ffmpeg --enable-ffmpeg --enable-ffplay --enable-ffprobe --bindir=/nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-ffmpeg-7.1.1-bin/bin --enable-avcodec --enable-avdevice --enable-avfilter --enable-avformat --enable-avutil --enable-postproc --enable-swresample --enable-swscale --libdir=/nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-ffmpeg-7.1.1-lib/lib --incdir=/nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-ffmpeg-7.1.1-dev/include --enable-doc --enable-htmlpages --enable-manpages --mandir=/nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-ffmpeg-7.1.1-man/share/man --enable-podpages --enable-txtpages --docdir=/nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-ffmpeg-7.1.1-doc/share/doc/ffmpeg --enable-alsa --enable-amf --enable-libaom --disable-libaribb24 --disable-libaribcaption --enable-libass --disable-avisynth --enable-libbluray --disable-libbs2b --enable-bzlib --disable-libcaca --disable-libcdio --disable-libcelt --disable-chromaprint --disable-libcodec2 --disable-cuda --enable-cuda-llvm --disable-cuda-nvcc --enable-cuvid --enable-libdav1d --disable-libdc1394 --enable-libdrm --disable-libdvdnav --disable-libdvdread --disable-libfdk-aac --enable-ffnvcodec --disable-libflite --enable-fontconfig --enable-libfontconfig --enable-libfreetype --disable-frei0r --enable-libfribidi --disable-libgme --enable-gnutls --disable-libgsm --enable-libharfbuzz --enable-iconv --disable-libilbc --disable-libjack --disable-libjxl --disable-libkvazaar --disable-ladspa --disable-liblc3 --disable-liblcevc-dec --disable-lcms2 --enable-lzma --disable-metal --disable-libmfx --disable-libmodplug --enable-libmp3lame --disable-libmysofa --disable-libnpp --enable-nvdec --enable-nvenc --disable-openal --enable-opencl --disable-libopencore-amrnb --disable-libopencore-amrwb --disable-opengl --disable-libopenh264 --enable-libopenjpeg --enable-libopenmpt --enable-libopus --disable-libplacebo --enable-libpulse --disable-libqrencode --disable-libquirc --disable-librav1e --enable-librist --disable-librtmp --disable-librubberband --disable-libsmbclient --enable-sdl2 --disable-libshaderc --disable-libshine --disable-libsnappy --enable-libsoxr --enable-libspeex --enable-libsrt --enable-libssh --disable-librsvg --enable-libsvtav1 --disable-libtensorflow --enable-libtheora --disable-libtwolame --enable-libv4l2 --enable-v4l2-m2m --enable-vaapi --enable-vdpau --disable-libvpl --enable-libvidstab --disable-libvmaf --disable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-vulkan --disable-libvvenc --enable-libwebp --enable-libx264 --enable-libx265 --disable-libxavs --disable-libxcb --disable-libxcb-shape --disable-libxcb-shm --disable-libxcb-xfixes --disable-libxevd --disable-libxeve --disable-xlib --enable-libxml2 --enable-libxvid --enable-libzimg --enable-zlib --disable-libzmq --enable-libzvbi --disable-debug --enable-optimizations --disable-extra-warnings --disable-stripping
  libavutil      59. 39.100 / 59. 39.100
  libavcodec     61. 19.101 / 61. 19.101
  libavformat    61.  7.100 / 61.  7.100
  libavdevice    61.  3.100 / 61.  3.100
  libavfilter    10.  4.100 / 10.  4.100
  libswscale      8.  3.100 /  8.  3.100
  libswresample   5.  3.100 /  5.  3.100
  libpostproc    58.  3.100 / 58.  3.100
Universal media converter
usage: ffmpeg [options] [[infile options] -i infile]... {[outfile options] outfile}...

I managed to actually manualy transcode a video so I don’t understand why immich fails T_T

What am I missing ?

Bind mount is not enough.
Create the container declaratively with the configuration:

    containers.<name>.allowedDevices = [
      {
        modifier = "rw";
        node = "/dev/dri/renderD128";
      }
    ];

thank you. I indeed got it working with the declarative container

{ config, lib, pkgs, nixos-hardware, lanzaboote, ... }:
{
  users = {
    groups = {
      immich = {
        gid = 991;
      };
    };
    users.immich ={
      extraGroups = [ "video" "render" ];
      uid =991;
      group = "immich";
    };
  };
  containers.immich = {
    privateNetwork = true;
    hostAddress6 = "fc00::1";
    localAddress6 = "fc00::2";
    autoStart = true;
    allowedDevices = [
      {
        node = "/dev/dri";
        modifier = "rw";
      }
      {
        modifier = "rw";
        node = "/dev/dri/renderD128";
      }
      {
        modifier = "rw";
        node = "/dev/dri/card1";
      }
    ];
    bindMounts = {
      "/dev/dri" = {
        hostPath = "/dev/dri/";
        isReadOnly = false;
      };
    };

    config = { pkgs, lib, ... }: {
      services.immich = {
        enable = true;
        openFirewall = true;
        host = "::";
        accelerationDevices=[ "/dev/dri/renderD128" ];
        environment.LIBVA_DRIVER_NAME = "iHD";
      };
      nixpkgs.config.allowUnfree = true;
      users.users.immich = {
        extraGroups = [ "video" "render" ];
        uid = 993;
        group = "immich";
      };
      users.groups.immich = {
        gid = 991;
      };
      users.groups.video = {
        gid = 26;
      };
      users.groups.render = {
        gid = 303;
      };
      hardware.graphics = {
        enable = true;
        extraPackages = with pkgs; [
          intel-media-driver # For Broadwell (2014) or newer processors. LIBVA_DRIVER_NAME=iHD
          libva-vdpau-driver # Previously vaapiVdpau
          intel-compute-runtime # OpenCL filter support (hardware tonemapping and subtitle burn-in)
          vpl-gpu-rt # QSV on 11th gen or newer
          intel-ocl # OpenCL support
        ];
      };
      networking.firewall.allowedTCPPorts = [ 2283 ];
      environment.systemPackages = with pkgs; [
        clinfo
        libva-utils
        ffmpeg
        vim
      ];
      system.stateVersion = "25.05";
      };
    };
}
1 Like