Skip to content

Repository files navigation

Logo del plugin PostgreSQL

🌐  Español  ·  English


🐘 PostgreSQL Database Provider

Plugin para Jellyfin que reemplaza SQLite por PostgreSQL como motor de base de datos, sin modificar el núcleo de Jellyfin. Migración bidireccional, búsqueda casi instantánea, health check automático, mantenimiento programado e integración opcional con JellyTrend.


Last Commit CI Build Jellyfin Release Downloads Discord License

v3 / Jellyfin 12.1: requiere .NET 10 y PostgreSQL 16+. Consulta la guía de actualización y pruebas antes de sustituir el proveedor.

¿Vienes de Jellyfin 10.11.x con PostgreSQL? Sigue el manual de migración 10.11.x → 12.x: necesitas el plugin 2.0.1 para exportar PostgreSQL a SQLite antes de actualizar el servidor y el plugin 3.0.0 para importar de vuelta a PostgreSQL.


📚 Documentación

Documento Contenido
Migración 10.11.x → 12.x · EN Manual paso a paso, con diagrama y plan de contingencia
Novedades de 3.0.0 · EN Qué cambia en 3.0.0 frente a 2.0.1
Adaptación a Jellyfin 12.1 Notas técnicas y cómo ejecutar la suite de pruebas
Verificación automatizada Resumen ejecutivo generado desde la suite real
Integración para desarrolladores · EN Contrato público, esquemas privados, migraciones y mantenimiento administrado

✨ Características

  • 🐘 PostgreSQL como backend nativo — EF Core + Npgsql, sin tocar el core de Jellyfin.
  • 🔍 Búsqueda casi instantánea (< 15 ms típico) con índice GIN trigram (pg_trgm); fallback automático a ILIKE.
  • 🔄 Migración bidireccional — SQLite → PostgreSQL y PostgreSQL → SQLite sin herramientas externas.
  • 🩺 Health Check automático al arrancar: diagnostica bloat, índices inválidos, secuencias desfasadas y queries lentas.
  • 🛡️ Prevención de errores — interceptores EF Core para upserts, logging de errores DB y normalización de DateTime.Kind.
  • 🔧 Optimización automática — índices GIN CONCURRENTLY, tuning de autovacuum en tablas críticas.
  • 💾 Backups programados con pg_dump, compresión ZIP opcional y restore desde la UI.
  • 🔐 Host de esquemas privados — contrato reutilizable para que otros plugins persistan únicamente sus propios datos, sin credenciales ni acceso al esquema public de Jellyfin.
  • 📊 Estadísticas de BD — tamaño, conexiones activas y análisis tabla por tabla desde la UI.
  • 🧪 Consola SQL de solo lectura — lanza consultas de diagnóstico desde el panel con 10 plantillas e historial; rechaza cualquier sentencia que modifique datos.
  • 🔁 Rollback a SQLite en un clic desde la configuración.

🧩 Integraciones de plugins

PG Provider puede servir como almacén PostgreSQL privado para otros plugins, sin darles acceso a credenciales ni al esquema public de Jellyfin. Desde Integraciones, el administrador consulta las integraciones registradas, sus tablas y señales de mantenimiento, y decide qué esquemas participan en las tareas programadas.

Pestaña Integraciones

Consulta la guía de integración para desarrolladores para usar el contrato público, diseñar migraciones y conocer sus límites de seguridad.


⚙️ Compatibilidad

Componente Versión
Jellyfin 12.1.x — para Jellyfin 10.11.x usa el plugin 2.0.1
PostgreSQL 16 + (recomendado 17)
.NET 10.0

ℹ️ El plugin implementa IJellyfinDatabaseProvider, el mismo contrato que usa el proveedor SQLite incluido en Jellyfin 12.1. No requiere modificar el núcleo de Jellyfin.


🚀 Instalación

Opción A — repositorio de plugins (recomendada)

  1. En Jellyfin entra en Panel → Avanzado → Repositorios de complementos.

  2. Pulsa Añadir repositorio y usa esta URL:

    https://raw.githubusercontent.com/BORNIOS/Jellyfin-Database-Providers-Postgres/main/manifest.json
    
  3. Guarda, ve al Catálogo, busca PostgreSQL Database Provider e Instala.

  4. Acepta el reinicio cuando te lo pida.

Opción B — ZIP manual

  1. Descarga el ZIP del Release.
  2. Descomprímelo en la carpeta de plugins de Jellyfin.
  3. Reinicia Jellyfin.

💡 Ubicaciones habituales de la carpeta de plugins:

  • Linux / Docker: /config/plugins/
  • Windows: %LOCALAPPDATA%\jellyfin\plugins\

🖥️ Interfaz del plugin

El plugin añade una página propia en Panel → Complementos → PostgreSQL Database Provider con seis pestañas, en este orden: Configuración, Migración, Mantenimiento, Health, Consola SQL e 🧩 Integraciones. La barra se adapta a pantallas pequeñas y conserva el nombre de cada sección como ayuda contextual.

⚙️ Configuración — conexión, pool y motor activo

Es el punto de entrada: define a qué PostgreSQL te conectas, con qué parámetros de pool y qué motor usa Jellyfin ahora mismo (SQLite o PostgreSQL).

Tab Configuración

Estado actual — resumen en vivo de lo que el plugin está usando de verdad: motor activo, archivo SQLite detectado, esquema y una línea con Pool: min-max · Timeout · Prepared statements.

Conexión PostgreSQL

Parámetro Descripción Default
Connection string Cadena completa de Npgsql —
Schema Schema PostgreSQL a usar public
PgBin path Ruta a pg_dump / psql / pg_restore auto-detect
Backup directory Carpeta donde se guardan los backups <DataPath>/postgres-backups
Backup compression Comprimir el backup en ZIP true

Opciones avanzadas

Parámetro Descripción Default
Min pool size Conexiones mínimas que mantiene abiertas Npgsql 4
Max pool size Conexiones máximas del pool 100
Max auto-prepare Sentencias preparadas en el servidor (0 = desactivado) 50
Command timeout Tiempo máximo de una query EF Core (segundos) 600

ℹ️ Si tu cadena de conexión ya incluye una de estas claves, ese valor manda y la configuración solo rellena lo que falte. Los cambios de pool requieren reiniciar Jellyfin para aplicarse.

Acciones

Botón Función
Probar conexion Valida la cadena y devuelve la versión del servidor PostgreSQL
Guardar configuracion Persiste conexión, opciones avanzadas y rutas (rechaza max < min)
Activar PostgreSQL y reiniciar Solo aparece cuando Jellyfin usa SQLite; valida la conexión antes de escribir config/database.xml en modo PLUGIN_PROVIDER y reinicia el servidor
Revertir a SQLite y reiniciar Solo aparece cuando PostgreSQL está activo; valida que exista una base SQLite utilizable, elimina config/database.xml y reinicia

Flujo recomendado: 1) Probar conexión → 2) ajustar pool y timeout → 3) Guardar configuración → 4) migrar los datos → 5) Activar PostgreSQL.


🔄 Migración

Dos operaciones disponibles con progreso en vivo:

Tab Migración

SQLite → PostgreSQL

Copia jellyfin.db a PostgreSQL tabla por tabla.

  1. La ruta de jellyfin.db se autodetecta ({DataPath}/jellyfin.db).
  2. Ajusta el batch size (default 1000).
  3. Activa Truncar tablas antes de insertar si repites la migración sobre datos existentes.
  4. Pulsa Iniciar migración y sigue el progreso.
  5. Al llegar al 100 %, activa PostgreSQL desde la pestaña Configuración.

⚠️ La opción --truncate hace TRUNCATE + RESTART IDENTITY + CASCADE en el destino. Úsala en reintentos para evitar duplicados; es destructiva con datos existentes.

PostgreSQL → SQLite

Exporta toda la base directamente a un archivo .db nativo sin herramientas externas.

  • Si el .db no existe → lo crea con el schema derivado de PostgreSQL.
  • Si el .db ya existe → preserva las tablas y reemplaza solo el contenido (DELETE + INSERT).
  • Escritura en transacciones de 10 000 filas con PRAGMA journal_mode=WAL.
  • Cuando Jellyfin 12.1 requiere el archivo heredado library.db, se crea mediante SQLite y se valida con PRAGMA integrity_check; el export falla de forma explícita en vez de dejar un archivo inválido.

Casos de uso: revertir a SQLite, copia portable de seguridad, inspección local.


🛠️ Mantenimiento

Operaciones de mantenimiento, backups y estadísticas de la base de datos.

Tab Mantenimiento

Acción Función
VACUUM ANALYZE Mantiene las tablas public de Jellyfin; los esquemas privados solo participan si el administrador los habilita en Integraciones
REINDEX DATABASE Reconstruye índices de public; los esquemas privados requieren habilitación explícita en Integraciones
Aplicar optimizaciones Crea 9 índices GIN CONCURRENTLY y ajusta autovacuum en las tablas críticas
Crear backup ahora Genera un .sql con pg_dump (y .zip si la compresión está activa)
Restablecer backup Restaura desde .sql o .zip, con selector de backups disponibles
Actualizar estadisticas Tamaño total, conexiones activas y métricas tabla por tabla

💡 Aplicar optimizaciones activa también la búsqueda casi instantánea cuando pg_trgm está disponible, y es el paso que crea los índices GIN que usa el endpoint de búsqueda.


🩺 Health — diagnóstico automático

Comprueba la salud de la base 10 segundos después del arranque y permite relanzar el chequeo a mano desde la propia pestaña.

Tab Health

Check Qué comprueba
Conexión Que PostgreSQL responde, y con qué latencia
Extensiones Que pg_trgm y pg_stat_statements están disponibles
Índices inválidos Índices en estado invalid, con reparación en un clic
Bloat de tablas Tablas con más de 20 % de tuplas muertas
Secuencias desfasadas Secuencias fuera de rango respecto a los datos
Estadísticas obsoletas Tablas sin ANALYZE reciente
Queries lentas Top consultas por tiempo acumulado (vía pg_stat_statements)
Presión de buffers Porcentaje de aciertos en caché compartida, bloques leídos de disco, uso temporal y WAL de las consultas lentas

Cada resultado lleva semáforo Info / Warn / Error, y los problemas marcados como reparables se corrigen desde la misma card. El resumen del arranque queda además en el log del plugin:

[HealthCheck] Resumen arranque: 0 error(es), 0 advertencia(s), 65 informativo(s) | Severidad: Ok

🧪 Consola SQL — consultas de solo lectura

Herramienta de diagnóstico para lanzar SELECT contra la base del plugin sin salir del panel ni abrir una sesión psql.

Tab Consola SQL

  • Solo lectura por diseño: rechaza INSERT / UPDATE / DELETE / DDL y también varias sentencias enviadas a la vez.
  • 10 plantillas listas para usar: consultas lentas, tamaño por tabla, índices sin uso, conexiones activas, bloat, bloqueos, y más.
  • Las plantillas filtran por base de datos y excluyen sentencias administrativas, así que no arrastran ruido de otras bases del mismo servidor PostgreSQL.
  • Historial de las últimas consultas conservado en la sesión del navegador, con botón para limpiarlo.

🧩 Integraciones — esquemas privados de otros plugins

Permite revisar únicamente los esquemas registrados mediante el contrato público del proveedor, sin exponer credenciales, public ni datos de otra integración. Elige una integración y después una tabla para consultar una muestra limitada y ordenable de sus datos.

  • La tabla de estado muestra filas estimadas, tamaño, índices, tuplas muertas y cambios.
  • ANALYZE programado está activo inicialmente; VACUUM (ANALYZE) y REINDEX programados solo se ejecutan cuando el administrador los selecciona para ese esquema.
  • El backup completo incluye todos los esquemas privados registrados; las acciones manuales quedan limitadas al esquema o tabla elegidos.

Consulta la guía de integración para desarrolladores para el contrato, el aislamiento y la estrategia de migraciones.


🔍 Búsqueda casi instantánea

Cuando los índices GIN están activos, el plugin expone un endpoint propio que evita EF Core:

  • Latencia típica < 15 ms en bibliotecas medianas y grandes (depende del hardware y del cliente).
  • Búsqueda por nombre, path y tipo de ítem.
  • Fallback automático a ILIKE si los índices GIN aún no existen.
  • Se activa en Mantenimiento → Aplicar optimizaciones.

🔁 Activar / Desactivar PostgreSQL

Activar PostgreSQL

  1. Configura y prueba la conexión en la pestaña Configuración.
  2. Migra los datos (Migración → SQLite → PostgreSQL).
  3. Pulsa Activar PostgreSQL y confirma el reinicio.

Resultado: database.xml se escribe en modo PLUGIN_PROVIDER apuntando a este plugin.

Volver a SQLite (rollback)

  1. En Configuración pulsa Desactivar / Volver a SQLite.
  2. El plugin elimina database.xml.
  3. Reinicia Jellyfin.

Cuándo hacer rollback: caída de conectividad a PostgreSQL, mantenimiento urgente o migración incompleta.


💾 Backups

Configurar

En Configuración:

  • PgBin path — ruta a pg_dump/psql/pg_restore. Déjalo vacío para usar el PATH del sistema.
  • Backup directory — carpeta destino de los archivos.
  • Backup compression — activa ZIP del .sql.

Manual

En Mantenimiento: Crear backup ahora / Restablecer backup (acepta .sql o .zip).


📅 Tareas programadas

Tarea Default Descripción
PostgreSQL Backup Diario 02:00 Backup con pg_dump
PostgreSQL VACUUM ANALYZE (managed schemas) Domingo 03:00 Mantiene public y solo los esquemas privados autorizados en Integraciones
PostgreSQL REINDEX (managed schemas) Domingo 04:00 Reconstruye índices de public y únicamente los esquemas privados autorizados
Optimize GIN Indexes Domingo 05:00 Mantiene los índices GIN trigram frescos

⚠️ Evita solapar REINDEX, VACUUM y Backup en la misma ventana horaria.


✅ Checklist post-migración

  1. Login correcto con los usuarios existentes.
  2. Progreso de reproducción actualizando correctamente.
  3. Conteos clave validados (UserData, Users, BaseItems).
  4. Sin errores de conexión PostgreSQL en logs de Jellyfin.
  5. Health Check ejecutado sin errores (Warn aceptable, Error requiere acción).
  6. Backup manual probado al menos una vez.
  7. Índices GIN aplicados (Mantenimiento → Aplicar optimizaciones).

❓ FAQ

Instalé el plugin pero no migró datos automáticamente.

Es el comportamiento esperado. Ejecuta la migración desde Migración → SQLite → PostgreSQL y luego activa PostgreSQL desde Configuración.

La migración falla o da resultados raros en reintentos.

Activa Truncar tablas antes de insertar para reiniciar las tablas destino antes de insertar. Es destructivo sobre datos existentes en PostgreSQL, pero garantiza un resultado limpio.

¿Puedo editar database.xml manualmente?

Sí, pero se recomienda usar la UI del plugin para evitar errores de formato.

¿Qué pasa si exporto a SQLite y el .db ya existe?

El plugin preserva la estructura de tablas y reemplaza solo los datos (DELETE + INSERT). El archivo no se elimina ni recrea.

¿Uso Docker; por qué falla un backup o la copia de migración con pg_dump?

pg_dump, psql y pg_restore se ejecutan dentro del contenedor de Jellyfin. Instala un cliente PostgreSQL compatible —se recomienda PostgreSQL 17— en tu imagen derivada de Jellyfin y configura su directorio de binarios en PgBin path. Instalarlo solo en el host Docker no lo hace disponible para el plugin dentro del contenedor.

¿La búsqueda rápida requiere cambios en el cliente Jellyfin?

No. Es un endpoint de servidor. La UI del plugin lo usa internamente cuando PostgreSQL está activo y los índices GIN existen.

¿Por qué los timestamps muestran UTC en lugar de mi zona horaria o una fecha mínima?

Las versiones anteriores usaban el switch global Npgsql.EnableLegacyTimestampBehavior, que forzaba UTC en todas las lecturas. El interceptor actual normaliza parámetros de escritura sin zona horaria sin alterar las lecturas y convierte DateTime.MinValue a un valor UTC seguro para clientes antes de que Npgsql lo represente como -infinity.


🤝 Comunidad

¿Dudas, sugerencias o encontraste un bug? Abre un issue o únete a la comunidad oficial de Jellyfin:

Discord Reddit


Hecho con ❤️ para la comunidad Jellyfin  ·  ⭐ Star en GitHub

About

Production-ready PostgreSQL backend solution for Jellyfin through PLUGIN_PROVIDER.

Resources

Stars

12 stars

Watchers

2 watching

Forks

Releases

Contributors

Languages