Self-Hosting
Jellyfin on N100/N150: Linux Docker Hardware Acceleration
Set up Intel Quick Sync for Jellyfin on native Linux Docker: render-device access, group permissions, driver checks and a forced-transcode verification.
Start here: Prove the Linux host has a usable render device
Use native Linux with Docker Engine. Record the exact N100/N150 host, distro, kernel and Jellyfin version. Run ls -l /dev/dri/ and identify the intended renderD node; multiple GPUs can change its number.
This procedure is not for Docker Desktop on macOS, Windows Docker or WSL QSV.
Problem summary
First prove the render device exists on native Linux. Then pass that device and its numeric group to the official Jellyfin container, verify the driver, and force a real video transcode. This is a worked configuration and diagnostic sequence, not a measured N100/N150 performance promise.
Use native Linux with Docker Engine. Record the exact N100/N150 host, distro, kernel and Jellyfin version. Run ls -l /dev/dri/ and identify the intended renderD node; multiple GPUs can change its number.
ls -l /dev/dri/ stat -c "%g" /dev/dri/renderD128 id -u id -g
At least one intended renderD device exists, and its owner group has read/write access.
This procedure is not for Docker Desktop on macOS, Windows Docker or WSL QSV.
Layer path
Step-by-step runbook
Start here. Do each check in order, compare it to the expected result, and stop when the evidence explains the failure or the safe stop point applies.
Prove the Linux host has a usable render device
Check: Use native Linux with Docker Engine. Record the exact N100/N150 host, distro, kernel and Jellyfin version. Run ls -l /dev/dri/ and identify the intended renderD node; multiple GPUs can change its number.
Expected result: At least one intended renderD device exists, and its owner group has read/write access.
If not: If absent, enable the integrated GPU in BIOS and check the supported host kernel/driver. Docker cannot invent a device absent on the host.
Safe stop: This procedure is not for Docker Desktop on macOS, Windows Docker or WSL QSV.
Map numeric permissions before creating the container
Check: Run stat -c "%g" /dev/dri/renderD128 for the chosen node, plus id -u and id -g for the non-root account owning the config/cache folders. Fill YOUR_RENDER_GID, YOUR_UID and YOUR_GID in the example below.
Expected result: The supplementary group matches the device’s actual numeric group; the chosen account can write config and cache.
If not: The group name may be render, video or input. Do not assume a copied numeric ID such as 122 matches your host, and do not chmod 777 the device.
Validate the explicit Compose deployment
Check: Use the official jellyfin/jellyfin image with a pinned version you have chosen and supported media mount. Replace every placeholder, match renderD128 to your actual node, and run docker compose config before docker compose up -d. The localhost-only example needs an SSH tunnel for remote browser access.
Expected result: Compose validates, the service starts, and /media contains the intended files without write access.
If not: If you intentionally need LAN access, change the host bind to your server’s LAN address and apply a firewall rule. Do not expose the admin interface publicly just to run this test.
Check the driver in the container, then enable QSV
Check: Run the "Container media driver" command below and inspect Intel iHD and supported decode/encode profiles. In Jellyfin Dashboard → Playback → Transcoding choose Intel Quick Sync (QSV), select the render device if offered and only enable supported decode codecs.
Expected result: The driver enumerates the needed codec profiles; the configured device agrees with the mapped node.
If not: Permission denied means user/group/device mapping. A driver initialisation failure may be a kernel/runtime issue. Do not enable every codec or low-power encoding option as a guess.
Force and verify a real video transcode
Check: Play your own SDR test clip, request a lower output resolution, and open playback information plus the ffmpeg transcode log. Look for QSV encoder/decoder selection and watch intel_gpu_top’s Video engine on the Linux host if the tool supports your device.
Expected result: The session really transcodes; the log reports the hardware path and video-engine activity accompanies playback.
If not: Direct Play, audio-only conversion or a checked settings box cannot prove video acceleration. Record the complete ffmpeg error before changing settings.
Add HDR, subtitles and concurrency one at a time
Check: Repeat with your HDR-to-SDR file and real subtitle format. Test tone mapping as a separate processing stage and inspect its log/runtime support. Then add the household’s expected concurrent clients and watch buffer events, encode speed, memory and thermals.
Expected result: The complete workload plays smoothly on this host with measured headroom.
If not: An N100/N150 label is not a fixed stream-count promise. If ordinary SDR works but HDR/subtitles fail, investigate that stage before replacing the entire server.
Safe stop: Keep a known working configuration and do not use privileged mode to hide an unexplained permission issue.
Did this solve your problem?
Your answer helps us improve this page.
No account or personal details. We store the page, answer, optional reason and day with a 90-day retention period. A random reference in this browser prevents repeat votes. Feedback privacy
Decision tree
If: No renderD device exists on the native Linux host
Then: BIOS, host kernel/driver or guest passthrough is the first layer
Action: Prove the host device before editing Docker or Jellyfin settings.
If: The host has a render node, but the container reports permission denied
Then: Device mapping or supplementary numeric group is wrong
Action: Match the actual node and stat-reported group to the non-root service account; avoid privileged mode/chmod 777.
If: vainfo enumerates the needed profiles, but playback still uses software
Then: Device visibility alone does not establish the application codec/encoder path
Action: Choose the supported QSV method/codecs and force a video transcode; inspect its complete ffmpeg log.
If: SDR QSV works, but HDR tone mapping or subtitle burn-in is slow
Then: A separate processing stage or system bottleneck needs isolation
Action: Retest without those features, then add one at a time while recording encode speed and media-engine/CPU load.
Evidence table
| Symptom | Evidence to collect | Likely layer | Next action |
|---|---|---|---|
| No renderD device exists on the native Linux host | Host ls -l /dev/dri output, BIOS state and kernel version | BIOS, host kernel/driver or guest passthrough is the first layer | Prove the host device before editing Docker or Jellyfin settings. |
| The host has a render node, but the container reports permission denied | Host and container device listings plus the container user’s numeric groups | Device mapping or supplementary numeric group is wrong | Match the actual node and stat-reported group to the non-root service account; avoid privileged mode/chmod 777. |
| vainfo enumerates the needed profiles, but playback still uses software | vainfo profiles, selected codecs, playback mode and ffmpeg encoder selection | Device visibility alone does not establish the application codec/encoder path | Choose the supported QSV method/codecs and force a video transcode; inspect its complete ffmpeg log. |
| SDR QSV works, but HDR tone mapping or subtitle burn-in is slow | Comparison of SDR, HDR and subtitle tests under the same host/software versions | A separate processing stage or system bottleneck needs isolation | Retest without those features, then add one at a time while recording encode speed and media-engine/CPU load. |
Commands and settings paths
Host render node and group
ls -l /dev/dri/
stat -c "%g" /dev/dri/renderD128
id -u
id -gWhere: Native Linux host; substitute the actual render node
Expected: Device exists; note its numeric group and the intended service account IDs
Failure means: Missing device is a host issue, not an application checkbox
Safe next step: Resolve BIOS/kernel support before configuring Docker.
Compose example — replace every placeholder
services:
jellyfin:
image: jellyfin/jellyfin:YOUR_TESTED_VERSION
user: "YOUR_UID:YOUR_GID"
group_add:
- "YOUR_RENDER_GID"
devices:
- /dev/dri/renderD128:/dev/dri/renderD128
ports:
- "127.0.0.1:8096:8096"
volumes:
- ./config:/config
- ./cache:/cache
- /path/to/media:/media:roWhere: A new deployment directory; do not overwrite an existing server’s config
Expected: Correct image tag, IDs, mount paths and host-only port binding
Failure means: Placeholder strings and the wrong render node are not a working configuration
Safe next step: Validate with docker compose config; select a supported version instead of leaving YOUR_TESTED_VERSION.
Validate and start
docker compose config
docker compose up -dWhere: Directory containing the reviewed compose file
Expected: Compose validates and services start
Failure means: Invalid mappings, inaccessible folders or an unselected image version
Safe next step: Fix the reported error before proceeding; inspect logs without posting private media paths publicly.
Container media driver
docker compose exec jellyfin /usr/lib/jellyfin-ffmpeg/vainfo --display drm --device /dev/dri/renderD128Where: Same Compose directory; official Jellyfin image
Expected: Intel iHD and the codec profiles required by your source/output
Failure means: Permission or driver initialisation error
Safe next step: Match the render group and node, then consult the version-specific Jellyfin Intel guide.
Transcode evidence
Jellyfin playback information → video transcode; Dashboard → Logs → ffmpeg transcode logWhere: Web UI during lower-resolution SDR playback
Expected: QSV path plus matching GPU media-engine activity
Failure means: Direct Play or software fallback does not validate QSV
Safe next step: Test one SDR file first and retain the exact ffmpeg failure.
Hardware and platform boundary
Change only when
- Change hardware only when an unsupported codec or measured bottleneck is established.
Evidence that matters
- Native Linux kernel/device support, numeric permissions, codec profiles, ffmpeg logs and measured full-workload playback.
Evidence that does not matter
- A headline stream count without a reproducible workload.
Avoid
- Do not copy another host’s group ID, enable all codecs blindly or add privileged mode/chmod 777.
Related problems
Last reviewed
2026-09-27 · Reviewed by HomeTechOps. Source-reviewed 2026-09-27 against Jellyfin’s Intel Linux/Docker guide. The Compose structure and verification sequence are checked; no physical N100/N150 benchmark, universal stream count or hardware-tested badge is claimed.
Sources/assumptions
- Native Linux Docker Engine, official Jellyfin image, supported Intel GPU and host kernel. Placeholders must be replaced; Docker Desktop/Windows/WSL are outside this procedure. Source-reviewed, without a physical N100/N150 test.
Source-backed checks
HomeTechOps turns official docs and conservative safety rules into a shorter runbook. These links are the source trail for the page direction.
Planning a purchase?
We keep a source-backed, price-free comparison so you can buy once and right. No star ratings, every spec cited.
NAS for Plex & Jellyfin: transcoding →Get the deal & firmware alerts
Home Stack Field Notes: NAS deals, firmware changes worth acting on, restore-test reminders, and new decision guides — plus the capacity & backup sizing cheatsheets from our calculators. Unsubscribe anytime.
Subscribe on beehiiv