Volunteer-built media solution that puts you in control — stream to any device from your own server, with no strings attached.
| Port | 8096 |
| Registry | ghcr.io/daemonless/jellyfin |
| Source | https://github.com/jellyfin/jellyfin |
| Website | https://jellyfin.org/ |
| Tag | Description | Best For |
|---|---|---|
latest / pkg |
FreeBSD Quarterly. Uses stable, tested packages. | Most users. Matches Linux Docker behavior. |
pkg-latest |
FreeBSD Latest. Rolling package updates. | Newest FreeBSD packages. |
Before deploying, ensure your host environment is ready. See the Quick Start Guide for host setup instructions.
services:
jellyfin:
image: "ghcr.io/daemonless/jellyfin:latest"
container_name: jellyfin
environment:
- PUID=1000 # User ID for the application process
- PGID=1000 # Group ID for the application process
- TZ=UTC # Timezone for the container
- FFMPEG_PATH=/usr/local/bin/jellyfin-ffmpeg # Path to the FFmpeg binary. Options: /usr/local/bin/jellyfin-ffmpeg (default) or /usr/local/bin/ffmpeg
volumes:
- "/path/to/containers/jellyfin:/config"
- "/path/to/containers/jellyfin/cache:/cache" # optional
- "/path/to/tv:/tv" # optional
- "/path/to/movies:/movies" # optional
ports:
- "8096:8096"
annotations:
org.freebsd.jail.allow.mlock: "true"
restart: unless-stopped.env:
# .env
DIRECTOR_PROJECT=jellyfin
PUID=1000
PGID=1000
TZ=UTC
FFMPEG_PATH=/usr/local/bin/jellyfin-ffmpeg
appjail-director.yml:
# appjail-director.yml
options:
- virtualnet: ':<random> default'
- nat:
services:
jellyfin:
name: jellyfin
options:
- container: 'boot args:--pull'
- expose: '8096:8096 proto:tcp' \
oci:
user: root
environment:
- PUID: !ENV '${PUID}'
- PGID: !ENV '${PGID}'
- TZ: !ENV '${TZ}'
- FFMPEG_PATH: !ENV '${FFMPEG_PATH}'
volumes:
- jellyfin: /config
- jellyfin_cache: /cache
- tv: /tv
- movies: /movies
volumes:
jellyfin:
device: '/path/to/containers/jellyfin'
jellyfin_cache:
device: '/path/to/containers/jellyfin/cache'
tv:
device: 'tv'
movies:
device: 'movies'Makejail:
# Makejail
ARG tag=latest
OPTION overwrite=force
OPTION from=ghcr.io/daemonless/jellyfin:${tag}
SET allow.mlock=1
Note: Exposing ports in AppJail means that your service can be reached from remote hosts. If that is not your intention, do not expose the ports and communicate with the service using the IPv4 address assigned by the virtual network.
podman run -d --name jellyfin \
-p 8096:8096 \
--annotation 'org.freebsd.jail.allow.mlock=true' \
-e PUID=1000 \
-e PGID=1000 \
-e TZ=UTC \
-e FFMPEG_PATH=/usr/local/bin/jellyfin-ffmpeg \
-v /path/to/containers/jellyfin:/config \
-v /path/to/containers/jellyfin/cache:/cache # optional \
-v /path/to/tv:/tv # optional \
-v /path/to/movies:/movies # optional \
ghcr.io/daemonless/jellyfin:latestappjail oci run -Pd \
-o overwrite=force \
-o container="args:--pull" \
-o virtualnet=":<random> default" \
-o nat \
-o expose="8096:8096 proto:tcp" \
-e PUID=1000 \
-e PGID=1000 \
-e TZ=UTC \
-e FFMPEG_PATH=/usr/local/bin/jellyfin-ffmpeg \
-o fstab="/path/to/containers/jellyfin /config <pseudofs>" \
-o fstab="/path/to/containers/jellyfin/cache /cache <pseudofs>" \ # optional
-o fstab="/path/to/tv /tv <pseudofs>" \ # optional
-o fstab="/path/to/movies /movies <pseudofs>" \ # optional
ghcr.io/daemonless/jellyfin:latest jellyfinNote: Exposing ports in AppJail means that your service can be reached from remote hosts. If that is not your intention, do not expose the ports and communicate with the service using the IPv4 address assigned by the virtual network.
- name: Deploy jellyfin
containers.podman.podman_container:
name: jellyfin
image: "ghcr.io/daemonless/jellyfin:latest"
state: started
restart_policy: always
env:
PUID: "1000"
PGID: "1000"
TZ: "UTC"
FFMPEG_PATH: "/usr/local/bin/jellyfin-ffmpeg"
ports:
- "8096:8096"
volumes:
- "/path/to/containers/jellyfin:/config"
- "/path/to/containers/jellyfin/cache:/cache" # optional
- "/path/to/tv:/tv" # optional
- "/path/to/movies:/movies" # optional
annotation:
org.freebsd.jail.allow.mlock: "true"Access at: http://localhost:8096
| Variable | Default | Description |
|---|---|---|
PUID |
1000 |
User ID for the application process |
PGID |
1000 |
Group ID for the application process |
TZ |
UTC |
Timezone for the container |
FFMPEG_PATH |
/usr/local/bin/jellyfin-ffmpeg |
Path to the FFmpeg binary. Options: /usr/local/bin/jellyfin-ffmpeg (default) or /usr/local/bin/ffmpeg |
| Path | Description |
|---|---|
/config |
Configuration directory |
/cache |
Cache directory (Optional) |
/tv |
TV Series library (Optional) |
/movies |
Movie library (Optional) |
| Port | Protocol | Description |
|---|---|---|
8096 |
TCP | Web UI |
This image includes both standard ffmpeg and jellyfin-ffmpeg. By default,
it uses jellyfin-ffmpeg (via the FFMPEG_PATH environment variable).
Why use jellyfin-ffmpeg?
While raw encoding performance is similar, jellyfin-ffmpeg includes critical
patches for HDR to SDR tone mapping (specifically the tonemapx filter).
Stock FFmpeg lacks a proper BT.2390 implementation, which results in "washed
out" or blown-out colors when serving HDR10 content to SDR displays.
Port Status
Note that jellyfin-ffmpeg is not currently in the official FreeBSD ports
tree, but it is provided in this image to ensure a high-quality transcoding
experience identical to the official Jellyfin Linux distributions.
Intel iGPU hardware transcoding is supported via VAAPI. The image includes
libva, libva-intel-media-driver, and gmmlib.
Host setup required — the GPU must be enabled and a devfs ruleset must expose the DRI devices into the jail:
-
Install the DRM kernel module and firmware:
pkg install drm-kmod libva-intel-media-driver gmmlib echo 'kld_list="i915kms"' >> /etc/rc.conf kldload i915kms -
Add a devfs ruleset to
/etc/devfs.rules:[devfsrules_jails_gpu=61182] add include $devfsrules_hide_all add include $devfsrules_unhide_basic add include $devfsrules_unhide_login add path 'bpf*' unhide add path 'dri' unhide add path 'dri/*' unhide mode 0666 add path 'drm*' unhide mode 0666 -
Configure the jail to use ruleset
61182and enableallow.mlock(already set in the example compose above). -
In Jellyfin: Dashboard → Playback → Transcoding → set Hardware acceleration to VAAPI, device
/dev/dri/renderD128.
Architectures: amd64
User: bsd (UID/GID via PUID/PGID, defaults to 1000:1000)
Base: FreeBSD 15.1
Need help? Join our Discord community.