Files
pgsql-jellyfin/README-POSTGRESQL.md
T

12 KiB

Jellyfin with PostgreSQL Support

This is a fork of Jellyfin that adds PostgreSQL database support for .NET 11 preview.

Features

  • PostgreSQL database provider implementation
  • Automatic database initialization from SQL scripts
  • Remote database support with connection string configuration
  • Database backup/restore via pg_dump/pg_restore
  • Migration system disabled in favor of SQL scripts
  • Support for both local and remote PostgreSQL servers

Requirements

FFmpeg Requirements

jellyfin-ffmpeg is highly preferred and recommended for use with Jellyfin Media Server. While standard FFmpeg can be used, the custom jellyfin-ffmpeg fork includes specifically targeted fixes, optimizations, and enhanced hardware acceleration support for media streaming that may not be available or prioritized in the upstream version.

Why jellyfin-ffmpeg is Preferred:

  • Improved Hardware Acceleration: Better support for hardware acceleration (NVENC, QuickSync, VA-API) across a wider range of GPUs, reducing the risk of partial acceleration
  • Reduced Playback Issues: Specifically built to handle HDR/Dolby Vision content, HLS/fMP4/MPEG-TS streaming, and complex transcoding scenarios better than standard FFmpeg
  • Optimized Performance: Often includes more efficient software decoders (like dav1d for AV1)
  • Pre-configured: Automatically included with official Docker images, deb packages, and Windows installers

Link: jellyfin-ffmpeg repository

Installation:

Debian/Ubuntu (using Jellyfin repository):

# Add Jellyfin repository (if not already added)
sudo apt-get install -y software-properties-common
sudo add-apt-repository universe

# Install jellyfin-ffmpeg
sudo apt-get update
sudo apt-get install -y jellyfin-ffmpeg6

Manual Download: Download from jellyfin-ffmpeg releases and configure the path in Jellyfin settings.

If using a custom or unofficial installation where jellyfin-ffmpeg is not available, standard FFmpeg might work but could lead to issues with specific transcoding tasks:

# Debian/Ubuntu
sudo apt-get install -y ffmpeg

# RHEL/Fedora
sudo dnf install -y ffmpeg

# Arch Linux
sudo pacman -S ffmpeg

Note: You may need to manually set the FFmpeg path in Jellyfin's dashboard under Dashboard → Playback → FFmpeg path.

System Dependencies (Linux)

Jellyfin requires certain system libraries to be installed:

Debian/Ubuntu-based systems:

sudo apt-get update
sudo apt-get install -y \
    libfontconfig1 \
    libfreetype6 \
    libssl3 \
    libicu-dev

Note: See the FFmpeg Requirements section above for installing jellyfin-ffmpeg.

RHEL/CentOS/Fedora-based systems:

sudo dnf install -y \
    fontconfig \
    freetype \
    openssl \
    libicu

Note: See the FFmpeg Requirements section above for installing FFmpeg.

Arch Linux:

sudo pacman -S fontconfig freetype2 openssl icu

Note: See the FFmpeg Requirements section above for installing FFmpeg.

Note: The libfontconfig1 library is required for SkiaSharp (image processing). Without it, Jellyfin will fail to start with:

libfontconfig.so.1: cannot open shared object file: No such file or directory

PostgreSQL Requirements

  • PostgreSQL 12 or higher (tested with PostgreSQL 18.3)
  • psql client tools (for automatic schema initialization)
  • Network access to PostgreSQL server (if using remote database)

Install PostgreSQL client tools:

Debian/Ubuntu:

sudo apt-get install -y postgresql-client

RHEL/CentOS/Fedora:

sudo dnf install -y postgresql

Verify psql is available:

psql --version

Database Configuration

Create or edit config/database.xml in your Jellyfin data directory:

<?xml version="1.0" encoding="utf-8"?>
<DatabaseConfigurationOptions>
  <DatabaseType>Jellyfin-PostgreSQL</DatabaseType>
  <LockingBehavior>NoLock</LockingBehavior>
  
  <CustomProviderOptions>
    <PluginName>Jellyfin-PostgreSQL</PluginName>
    <PluginAssembly>Jellyfin.Database.Providers.Postgres</PluginAssembly>
    
    <!-- Connection string with all parameters -->
    <ConnectionString>Host=192.168.1.100;Port=5432;Database=jellyfin;Username=jellyfin;Password=your_password_here</ConnectionString>
  </CustomProviderOptions>
  
  <!-- Optional: Backup configuration (works for both local and remote databases) -->
  <BackupOptions>
    <PgDumpPath>pg_dump</PgDumpPath>
    <PgRestorePath>pg_restore</PgRestorePath>
    <BackupFormat>custom</BackupFormat>
    <IncludeBlobs>true</IncludeBlobs>
    <CompressionLevel>6</CompressionLevel>
    <TimeoutSeconds>1800</TimeoutSeconds>
    <VerboseOutput>true</VerboseOutput>
  </BackupOptions>
</DatabaseConfigurationOptions>

Option 2: Using Individual Options

<?xml version="1.0" encoding="utf-8"?>
<DatabaseConfigurationOptions>
  <DatabaseType>Jellyfin-PostgreSQL</DatabaseType>
  
  <CustomProviderOptions>
    <PluginName>Jellyfin-PostgreSQL</PluginName>
    <PluginAssembly>Jellyfin.Database.Providers.Postgres</PluginAssembly>
    
    <Options>
      <CustomDatabaseOption>
        <Key>Host</Key>
        <Value>192.168.1.100</Value>
      </CustomDatabaseOption>
      
      <CustomDatabaseOption>
        <Key>Port</Key>
        <Value>5432</Value>
      </CustomDatabaseOption>
      
      <CustomDatabaseOption>
        <Key>Database</Key>
        <Value>jellyfin</Value>
      </CustomDatabaseOption>
      
      <CustomDatabaseOption>
        <Key>Username</Key>
        <Value>jellyfin</Value>
      </CustomDatabaseOption>
      
      <CustomDatabaseOption>
        <Key>Password</Key>
        <Value>your_password_here</Value>
      </CustomDatabaseOption>
    </Options>
  </CustomProviderOptions>
</DatabaseConfigurationOptions>

Option 3: Hybrid (ConnectionString + Overrides)

Individual options take precedence over ConnectionString:

<CustomProviderOptions>
  <!-- Base connection -->
  <ConnectionString>Host=192.168.1.100;Port=5432;Database=jellyfin;Username=jellyfin</ConnectionString>
  
  <!-- Override just the password -->
  <Options>
    <CustomDatabaseOption>
      <Key>Password</Key>
      <Value>production_password</Value>
    </CustomDatabaseOption>
  </Options>
</CustomProviderOptions>

Database Initialization

Automatic Initialization

When Jellyfin starts with an empty database:

  1. Database Check: Checks if the database exists (creates if missing)
  2. Table Check: Checks if users.Users table exists
  3. Auto-Initialize: If tables don't exist, automatically runs sql/schema_init/create_database_schema.sql via psql
  4. Schema Verification: Verifies all required schemas and tables are present

Requirements for automatic initialization:

  • psql command must be in system PATH
  • Database must exist (created automatically or manually)
  • SQL script must be deployed: sql/schema_init/create_database_schema.sql

Manual Initialization

If psql is not available or automatic initialization fails:

# Create database first
createdb -U postgres jellyfin

# Run schema creation script
psql -U postgres -d jellyfin -f /path/to/jellyfin/sql/schema_init/create_database_schema.sql

Startup Logs

Successful Startup (Empty Database):

[INF] PostgreSQL connection: Host="192.168.1.100", Port=5432, Database="jellyfin", ...
[INF] Database tables not found (users.Users table missing). Initializing from SQL script...
[INF] Found schema script at: .../sql/schema_init/create_database_schema.sql
[INF] Executing create_database_schema.sql (this may take several minutes)...
[INF] Executing via psql: psql -h 192.168.1.100 -p 5432 -U jellyfin -d jellyfin -f "..."
[INF] ✅ Successfully initialized database from SQL script via psql
[INF] Database is ready. You can now start Jellyfin.
[DBG] Schema 'users' contains 4 tables
[DBG] Schema 'library' contains 45 tables
[DBG] Schema 'activitylog' contains 1 tables
[INF] ✅ Database schema verification complete
[INF] There are 0 migrations for stage CoreInitialisation
[INF] There are 24 migrations for stage AppInitialisation

Successful Startup (Existing Database):

[INF] PostgreSQL connection: Host="192.168.1.100", Port=5432, Database="jellyfin", ...
[INF] Database tables exist (users.Users table found)
[DBG] Schema 'users' contains 4 tables
[DBG] Schema 'library' contains 45 tables
[INF] ✅ Database schema verification complete

Troubleshooting

Error: libfontconfig.so.1: cannot open shared object file

Cause: Missing system dependency

Solution:

# Debian/Ubuntu
sudo apt-get install -y libfontconfig1

# RHEL/Fedora
sudo dnf install -y fontconfig

Error: psql command not found

Cause: PostgreSQL client tools not installed

Solution:

# Debian/Ubuntu
sudo apt-get install -y postgresql-client

# RHEL/Fedora
sudo dnf install -y postgresql

Error: Failed to connect to 127.0.0.1:5432

Cause: Configuration not loading correctly (using default localhost)

Solution:

  • Verify database.xml is in the correct location (/var/lib/jellyfin/config/database.xml on Linux)
  • Check that ConnectionString or individual Options are properly configured
  • Ensure Host is set to your remote server IP/hostname

Error: database "jellyfin" does not exist

Cause: Database wasn't created automatically (rare)

Solution:

# Create database manually
createdb -U postgres -h your-server jellyfin

# Grant privileges
psql -U postgres -h your-server -c "GRANT ALL PRIVILEGES ON DATABASE jellyfin TO jellyfin;"

# Restart Jellyfin (it will create tables automatically)

Architecture

Database Schema

  • activitylog - Activity log entries
  • authentication - API keys, devices, device options
  • displaypreferences - User display preferences
  • library - Media library data (BaseItems, metadata, etc.)
  • users - User accounts, permissions, preferences

Migration System

Entity Framework migrations are DISABLED for .NET 11 preview. Schema changes are managed via SQL scripts:

  • Core migrations: Disabled (no database structure changes via EF)
  • Application migrations: Enabled (configuration and data migrations only)

Why: EF migrations in preview builds can cause schema inconsistencies. SQL scripts provide reliable schema management.


Backup and Restore

Automatic Backups (via pg_dump)

Configured in database.xml:

<BackupOptions>
  <PgDumpPath>pg_dump</PgDumpPath>
  <BackupFormat>custom</BackupFormat>
  <CompressionLevel>6</CompressionLevel>
</BackupOptions>

Works for both local and remote databases!

Manual Backup

# Backup to custom format (compressed)
pg_dump -h your-server -U jellyfin -d jellyfin -Fc -f jellyfin_backup.dump

# Backup to SQL format
pg_dump -h your-server -U jellyfin -d jellyfin -f jellyfin_backup.sql

Manual Restore

# Restore from custom format
pg_restore -h your-server -U jellyfin -d jellyfin jellyfin_backup.dump

# Restore from SQL format
psql -h your-server -U jellyfin -d jellyfin -f jellyfin_backup.sql

Building from Source

# Clone repository
git clone https://github.com/yourusername/jellyfin.git
cd jellyfin

# Checkout the upgrade branch
git checkout upgrade-to-NET11

# Build
dotnet build

# Run
cd Jellyfin.Server
dotnet run

Contributing

This is a development/preview branch. For production use, please use the official Jellyfin releases.

License

GNU General Public License v2.0 (same as Jellyfin)


Credits

Based on Jellyfin with PostgreSQL support and .NET 11 compatibility.