Hace poco menos de una año, instalé Jellyfin en Proxmox LXC usando los Proxmox VE Helper-Scripts.
Además, habilité la Intel HD Graphics 630 en Proxmox para activar la aceleración hardware que permite transcodificar usando Intel QuickSync (QSV)
.
En este post se irá un poco más allá para combinar el rendimiento de los LXC con la flexibilidad de Docker a la hora de ejecutar la última versión de una aplicación.
Aprovechando la plantilla de LXC con Debian 12 para ejecutar Docker en Proxmox que hice hace unos días, crearé un nuevo contenedor Linux para ejecutar la imagen oficial jellyfin/jellyfin
.
Crear contenedor
Para crear el contenedor se siguen las instrucciones de la plantilla para obtener este código que ejecuta en la shell de Proxmox:
# Plantilla
ct_id="700"
# Datos del nuevo contenedor
new_ct_id="318"
lxcname="jellyfin"
ip="192.168.1.89/24"
gw="192.168.1.1"
cores="2"
memory="2048"
swap="512"
disk_size="5"
# Clonar la plantilla
pct clone "$ct_id" "$new_ct_id" --hostname "$lxcname" --full
# Añadir mountpoint para backups rsync
mkdir "/backups/rsync/$lxcname"
chown 100000:101000 "/backups/rsync/$lxcname"
chmod 770 "/backups/rsync/$lxcname"
pct set "$new_ct_id" -mp0 "/backups/rsync/$lxcname,mp=/mnt/rsync"
# (Opcional) Añadir mountpoint para media
# pct set "$new_ct_id" -mp1 "/datos/samba/media,mp=/mnt/samba"
# Añadir dispositivo /dev/dri/renderD128
GID=$(getent group render | cut -d: -f3)
echo "dev0: /dev/dri/renderD128,gid=$GID" >> "/etc/pve/lxc/$new_ct_id.conf"
# Dirección IP y puerta de enlace
pct set "$new_ct_id" -net0 name=eth0,bridge=vmbr0,ip="$ip",gw="$gw"
# Parámetros hardware
pct set "$new_ct_id" -cores "$cores" -memory "$memory" -swap "$swap"
# Tamaño del disco
pct resize "$new_ct_id" rootfs "${disk_size}G"
# Información del contenedor
pct config "$new_ct_id"
# Iniciar contenedor
pct start "$new_ct_id"
Jellyfin usando docker compose
La instalación es bastante sencilla siguiendo el ejemplo de la documentación oficial:
services:
jellyfin:
image: jellyfin/jellyfin:10.10.7
container_name: jellyfin
user: 1000:1000
group_add:
# ID del grupo 'render'
- "104"
network_mode: 'host'
environment:
- TZ=Europe/Madrid
volumes:
- /etc/localtime:/etc/localtime:ro
- ./jellyfin_config:/config
- ./jellyfin_cache:/cache
- ./jellyfin_media:/local_media
devices:
# Dispositivo de renderización
- /dev/dri/renderD128:/dev/dri/renderD128
restart: 'unless-stopped'
Se crean los directorios necesarios:
mkdir ./jellyfin_config
mkdir ./jellyfin_cache
mkdir ./jellyfin_media
Se ejecuta el contenedor Docker:
docker compose up -d
Se accede a http://192.168.1.89:8096/
y se realiza la configuración inicial de Jellyfin:
- Welcome to Jellyfin!
- Preferred display language:
English
- Preferred display language:
- Tell us about yourself
- Username:
admin
- Password:
********
- Username:
- Set up your media libraries
- Saltar este paso, de momento
- Preferred Metadata Language
- Language: Spanish; Castilian
- Country/Region: Spain
- Set up Remote Access
- Allow remote connections to this server: No
- Enable automatic port mapping: No
- You’re Done!
A continuación se descarga el clásico Big Buck Bunny en formato 4K, 3840x2160, 60 fps.
La idea de usar este vídeo es probar, además de la descarga de metadatos y la reproducción desde la propia interfaz web, la transcodificación al solicitar un bitrate más pequeño.
Se descarga el video en el subdirectorio ./jellyfin_media
:
mkdir -p "./jellyfin_media/Big Buck Bunny (2008)" && cd "./jellyfin_media/Big Buck Bunny (2008)"
curl -O "http://distribution.bbb3d.renderfarming.net/video/mp4/bbb_sunflower_2160p_60fps_normal.mp4"
Desde la página principal de la interfaz web (Administration
→ Dashboard
→ Libraries
) se crea una nueva librería con la siguiente configuración:
- Add Media Library
- Content type:
Movies
- Display name:
Local
- Folders:
/local_media
[X]
Enable the library- Preferred download language: Spanish; Castilian
- Country/Region: Spain
- Metadata savers:
Nfo
- Save artwork into media folders
- Content type:
Si todo funciona correctamente, Jellyfin obtendrá los metadatos de la película “Big Buck Bunny” desde los servidores configurados en la librería.
Se puede utilizar el botón ▶ en la parte superior derecha para reproducir la película. Se puede mostrar la información de reproducción usando la opción Settings
→ Playback info
del reproductor de vídeo HTML de Jellyfin.
Aceleración hardware
El servidor Jellyfin puede usar una tarjeta gráfica integrada o discreta (GPU) para realizar la transcodificación de video de manera muy eficiente sin forzar la CPU.
En mi caso, se utilizará Intel Quick Sync Video (QSV) en la tarjeta gráfica Intel HD Graphics 630 que incorpora el Dell OptiPlex 7050 Micro donde ejecuto Proxmox VE 8.4.11.
La imagen oficial de Docker incluye todos los controladores multimedia Intel necesarios para el modo usuario y el entorno de ejecución OpenCL.
Solo hay que pasar el ID del grupo render
del host a Docker y modificar la configuración para que se ajuste a las necesidades de transcodificación que queramos.
getent group render | cut -d: -f3
group_add:
# ID del grupo 'render'
- "104"
También hay que pasar el dispositivo de renderización /dev/dri/renderD128
de la GPU.
Este dispositivo permite acceso restringido únicamente a funciones de cómputo del hardware gráfico, incluyendo:
- Transcodificación de vídeo
- Decodificación por hardware (VAAPI, QSV)
- Procesamiento sin acceso al framebuffer
No es necesario pasar el dispositivo principal /dev/dri/card0
de la GPU ya que permite acceso completo al hardware gráfico, incluyendo:
- Framebuffer (pantalla)
- Salida de vídeo
- Composición gráfica
- Aceleración por hardware
devices:
# Dispositivo de renderización
- /dev/dri/renderD128:/dev/dri/renderD128
Para que Jellyfin use la aceleración hardware, únicamente hay que configurarlo desde:
Administration
→Dashboard
→Playback
→Transcoding
- Hardware acceleration: Intel QuickSync (QSV)
Si se reproduce la misma película y se fuerza la resolución a 420 kbps (360p)
para simular un dispositivo no compatible con el formato original de la película en la librería, se observa como Jellyfin realiza el transcoding al vuelo:
(Opcional) Añadir /mnt/samba
Esto es una configuración opcional para poder compartir media entre diferentes LXC usando un servidor Samba.
En el LXC se añadió el mountpoint mp1
:
mp1: /datos/samba/media,mp=/mnt/samba
En el servidor Proxmox, el directorio /datos/samba/media
tiene las siguientes protecciones:
drwxrwx--- 9 100000 100300 4096 Mar 25 21:40 media
En el LXC el directorio /mnt/samba
tiene las siguientes protecciones (por ser unprivileged):
drwxrwx--- 9 root sambashare 4096 Mar 25 21:40 samba
Se crea el grupo sambashare
con GID 300
y se añade al usuario sin privilegios desde el que ejecuto los Dockers:
sambashare:x:300:manel
Este usuario sin privilegios es miembro de los siguientes grupos por la forma en que se creó la plantilla LXC:
uid=1000(manel) gid=1000(manel) groups=1000(manel),300(sambashare),996(docker)
Historial de cambios
- 2025-08-15: Documento inicial