Enabling Hardware Acceleration for Jellyfin on Talos Linux (Using Onedr0p Cluster-Template)
In my homelab journey, I've embraced Kubernetes for everything from running Jellyfin media servers to home automation and beyond. Central to my setup is a Kubernetes cluster running on Talos Linux, managed declaratively through Flux CD. I've been using the fantastic onedr0p cluster-template, a GitOps-driven, batteries-included template that leverages Talos.
Recently, I faced a common challenge: enabling hardware acceleration for Jellyfin running on nodes powered by Intel integrated GPUs (iGPU). This feature dramatically reduces CPU usage during media transcoding. After some back-and-forth experimentation and learning, I successfully enabled iGPU acceleration through system extensions provided by Talos's new “System Extensions” functionality.
In this guide, I share everything I learned, broken down into clear steps you can follow to replicate the setup smoothly, even if you're new to Talos or the onedr0p cluster-template.
What You'll Learn in This Guide
- Building a custom Talos installer image via Talos Image Factory
- Integrating Talos system extensions (specifically i915 for Intel iGPUs)
- Declaratively managing Talos nodes with onedr0p's cluster-template
- Configuring Jellyfin for hardware-accelerated transcoding
- Validating and troubleshooting your setup
Prerequisites
- A running Talos Linux cluster
- Nodes equipped with Intel iGPUs (e.g., UHD 630 on Dell OptiPlex Micro)
- Jellyfin deployed in Kubernetes (preferably via Flux)
- Basic familiarity with the onedr0p cluster-template workflow
Step-by-Step Guide
Important Note on Upgrading Talos
This guide also covers the scenario of upgrading Talos Linux from an older version (like 1.9.5) to a newer version (like 1.10.0). All the steps outlined here will seamlessly guide you through the upgrade process alongside enabling hardware acceleration.
Step 1: Building a Custom Talos Installer Image (via Talos Image Factory)
Head over to the official Talos Image Factory to build a tailored installer image:
- Choose the desired new Talos version to upgrade to (e.g., from 1.9.5 to 1.10.0) or use the same version your nodes are currently running if you prefer not to upgrade.
- Under System Extensions, select:
- siderolabs/i915 (GPU driver)
- siderolabs/intel-ucode (optional but recommended microcode update)
- Click Create and copy your generated schematic ID.
The Factory will provide an image URL similar to:
factory.talos.dev/installer/<your-schematic-id>:v1.10.0
Step 2: Integrate the Custom Installer with Onedr0p Cluster-Template
Update your nodes.yaml file with the schematic ID you generated:
nodes:
- name: talos-1
address: <your-ip-address>
controller: true
disk: <your-disk>
mac_addr: <your-mac-address>
schematic_id: <your-schematic-id> # Update with the new Schematic ID received by the Talos Image Factory
- name: talos-2
address: <your-ip-address>
controller: true
disk: <your-disk>
mac_addr: <your-mac-address>
schematic_id: <your-schematic-id> # Update with the new Schematic ID received by the Talos Image Factory
- name: talos-3
address: <your-ip-address>
controller: true
disk: <your-disk>
mac_addr: <your-mac-address>
schematic_id: <your-schematic-id> # Update with the new Schematic ID received by the Talos Image Factory
Commit and push your changes.
Step 3: Regenerate the Cluster Configurations
task configure
task talos:generate-config
Ensure the installer image URL is correctly updated in talos/clusterconfig/talconfig.yaml:
nodes:
- hostname: 'talos-1'
# ...
talosImageURL: factory.talos.dev/installer/4b3cd373a192c8469e859b7a0cfbed3ecc3577c4a2d346a37b0aeff9cd17cdb0 # You should see your new image URL here
- hostname: 'talos-2'
# ...
Step 4: Roll Out the Upgrade (Node-by-Node so nothing explodes)
This step will also perform the actual Talos version upgrade (e.g., from 1.9.5 to 1.10.0), ensuring your nodes run the desired Talos version after completion.
Safely upgrade your nodes one-by-one (starting with controllers if you have multiple):
kubectl drain talos-1 --ignore-daemonsets --delete-emptydir-data # Drain the node from any workloads
task talos:upgrade-node IP=<IP> # Upgrade the node, this will use the new image
talosctl health -n <IP> # Check health, you should see "Healthy" status and an error telling us to uncordon the node
kubectl uncordon talos-1 # Uncordon the node
Repeat for each controller and worker nodes.
Step 5: Verify iGPU Drivers on Talos Nodes
Once the node is upgraded and rebooted, confirm everything loaded correctly:
talosctl -n <IP> get extensions | grep i915 # Should show "running"
talosctl -n <IP> ls /dev/dri # renderD128 should appear
Test VA-API capabilities directly from the Talos node:
talosctl -n <IP> containers exec -- \
vainfo --display drm --device /dev/dri/renderD128
Expect to see H.264 and HEVC capabilities with driver iHD.
Note
If you encounter issues related to the vainfo command, ensure you have the necessary packages installed. You can do this by running the following within the container:
apt-get install vainfo
Step 6: Configure Jellyfin for Hardware Acceleration
In Jellyfin's Web UI:
Admin Dashboard > Playback > Transcoding
Configure as follows:
Option | Recommended Setting |
---|---|
Hardware acceleration | VA API / Intel QSV |
Device | /dev/dri/renderD128 |
Enable hardware decoding | H.264, HEVC (H.265), VP9 |
Enable hardware encoding | ✅ |
HEVC encoding | Optional (depends on clients) |
Allow 10-bit HEVC | ❌ |
VPP Tone-mapping | ❌ |
Transcode temporary path | /cache/transcodes |
Max simultaneous transcodes | 2 |
Step 7: Test Jellyfin HW Acceleration
Play a 4K HEVC file from a device forcing transcoding (e.g., Safari on iOS). In Jellyfin's Dashboard > Activity, you should see:
- VAAPI (hw) or QSV (hw) for both decode and encode.
- CPU usage should be significantly lower (< 15%).
Check live ffmpeg logs if needed:
kubectl logs <jellyfin-pod> -f | grep ffmpeg
Troubleshooting
Common Issues and Solutions
- Missing /dev/dri/renderD128: Ensure the Talos node correctly loaded siderolabs/i915 and rebooted after upgrade.
- vainfo errors inside Jellyfin container: Install VA-API libs:
apt update && apt install -y intel-media-va-driver-non-free
- “Software” instead of “(hw)” in Jellyfin: Double-check Jellyfin settings and codecs selections as outlined.
- Issues upgrading Talos versions (e.g., schema validation errors in talhelper): Ensure your talhelper version is up-to-date and compatible with the new Talos version schema.
Final Thoughts & Lessons Learned
Leveraging Talos system extensions to enable iGPU transcoding was a bit challenging at first, primarily due to understanding the Talos Image Factory and how extensions work declaratively. However, using the onedr0p cluster-template's structured workflow greatly simplified the integration.
Now, with Jellyfin smoothly transcoding using hardware acceleration, CPU usage is dramatically reduced, providing a significantly better streaming experience and cooler-running hardware. This experience not only solved a practical need but also taught me valuable insights about declarative management of system extensions within the Talos ecosystem.
I hope this detailed guide helps you achieve the same results in your homelab or projects!
Happy homelabbing, Philip Rutberg 🚀