- Removed unused classes and files related to SQLite database provider, including SqliteDesignTimeJellyfinDbFactory, ModelBuilderExtensions, PragmaConnectionInterceptor, AssemblyInfo, SqliteDatabaseProvider, DateTimeKindValueConverter. - Updated tests to remove dependencies on removed classes and adjusted mocking for configuration sections. - Added Microsoft.EntityFrameworkCore.Sqlite package reference to test project. - Improved string handling in tests for better consistency and clarity. - Refactored logging methods in JellyfinApplicationFactory for better readability and maintainability.
15 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.
Using Standard FFmpeg (Not Recommended):
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)
psqlclient 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
Option 1: Using ConnectionString (Recommended)
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:
- Database Check: Checks if the database exists (creates if missing)
- Table Check: Checks if
users.Userstable exists - Auto-Initialize: If tables don't exist, automatically runs
sql/schema_init/create_database_schema.sqlviapsql - Schema Verification: Verifies all required schemas and tables are present
Requirements for automatic initialization:
- ✅
psqlcommand 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.xmlis in the correct location (/var/lib/jellyfin/config/database.xmlon 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 entriesauthentication- API keys, devices, device optionsdisplaypreferences- User display preferenceslibrary- 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
Troubleshooting Connection Issues
Error: 57P01: terminating connection due to administrator command
Cause: PostgreSQL server forcibly terminated the connection during an operation
Common reasons:
- PostgreSQL server restart or reload
- Connection timeout (statement_timeout, idle_in_transaction_session_timeout)
- Manual connection termination via
pg_terminate_backend() - Network instability or firewall issues
- Resource limits exceeded (max_connections, memory pressure)
Solutions:
1. Configure Automatic Retry (Already Enabled)
Jellyfin now includes automatic retry logic for transient failures:
- Max retries: 3 attempts
- Max delay: 5 seconds between retries
- Retryable errors: Includes
57P01(connection termination)
2. Increase PostgreSQL Timeouts
Edit PostgreSQL configuration (/etc/postgresql/*/main/postgresql.conf):
# Increase statement timeout
statement_timeout = 300000 # 5 minutes (in milliseconds)
# Increase idle transaction timeout
idle_in_transaction_session_timeout = 600000 # 10 minutes
# Enable TCP keepalives (prevent network timeouts)
tcp_keepalives_idle = 60 # seconds
tcp_keepalives_interval = 10 # seconds
tcp_keepalives_count = 6
Reload PostgreSQL:
sudo systemctl reload postgresql
# OR
psql -U postgres -c "SELECT pg_reload_conf();"
3. Optimize Connection String
Add keepalive and timeout parameters to your connection string:
<ConnectionString>Host=192.168.129.253;Port=5432;Database=jellyfin;Username=jellyfin;Password=yourpass;Pooling=True;Minimum Pool Size=0;Maximum Pool Size=50;Connection Idle Lifetime=300;Connection Pruning Interval=10;Timeout=30;Command Timeout=300;Keepalive=60</ConnectionString>
Key parameters:
Timeout=30- Connection establishment timeout (30 seconds)Command Timeout=300- Query execution timeout (5 minutes)Keepalive=60- TCP keepalive interval (60 seconds)Connection Idle Lifetime=300- Close idle connections after 5 minutesConnection Pruning Interval=10- Check for stale connections every 10 seconds
4. Check PostgreSQL Logs
On your PostgreSQL server:
# View recent logs
sudo tail -f /var/log/postgresql/postgresql-*.log
# Or check systemd journal
sudo journalctl -u postgresql -n 100 --no-pager
Look for:
received fast shutdown requestterminating connectiontoo many connectionsout of memory
5. Monitor Active Connections
-- Check current connections
SELECT
datname,
usename,
application_name,
state,
state_change
FROM pg_stat_activity
WHERE datname = 'jellyfin'
ORDER BY state_change DESC;
-- Check connection limits
SELECT
(SELECT setting::int FROM pg_settings WHERE name = 'max_connections') AS max_connections,
(SELECT COUNT(*) FROM pg_stat_activity) AS current_connections,
(SELECT COUNT(*) FROM pg_stat_activity WHERE datname = 'jellyfin') AS jellyfin_connections;
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.