- Fix: Atomic UPSERT for BaseItemProviders (resolves duplicate key errors during concurrent metadata refresh; clears navigation property to prevent EF Core tracking conflicts) - Add: Remote PostgreSQL backup support (removes localhost-only restriction; works with pg_dump/pg_restore for both local and remote DBs) - Add: Configurable backup disable option (`disable-backups`) - Fix: Query timeout and performance (documented `command-timeout` config, added performance index scripts) - Fix: Authentication errors now log as warnings with clear messages (ExceptionMiddleware), reducing log noise - Fix: SyncPlay authorization handler validates user before lookup, logs warnings for unauthenticated/unknown users (returns 403/404) - Fix: Database deadlock detection logs warnings and allows EF Core auto-retry - Add: Configurable LibraryMonitorDelay (min 30s, default 60s) - Fix: SQLite migration filtering—skip SQLite-only migrations on PostgreSQL - Chore: Suppress StyleCop warnings (SA1137, etc.) for project consistency - Docs: 21 documentation files added/updated (config, backup, performance, troubleshooting, session summary) - All changes are backward compatible and production-ready
7.7 KiB
PostgreSQL Backup Configuration
This document explains how to configure PostgreSQL backup options in Jellyfin using the database.xml configuration file.
IMPORTANT: Local Database Requirement
pg_dump and pg_restore backup features are ONLY available when the PostgreSQL database host is localhost or 127.0.0.1 (or ::1 for IPv6).
- ✅ Local database (localhost/127.0.0.1): Automated backups via pg_dump/pg_restore are enabled
- ❌ Remote database: Backup settings are ignored; you must manage backups externally
When using a remote PostgreSQL server, Jellyfin will log:
"PostgreSQL database is on remote server ({Host}). Backup operations via pg_dump/pg_restore are disabled"
And backup operations will show:
"Backup deletion is not implemented for PostgreSQL on a remote server. Manage backups externally."
Configuration File Location
The database.xml file should be placed in your Jellyfin configuration directory:
- Windows:
%AppData%\Jellyfin\Server\config\database.xml - Linux:
~/.config/jellyfin/config/database.xmlor/etc/jellyfin/config/database.xml - Docker: Mount to
/config/database.xml
Basic Configuration
Here's a minimal configuration for PostgreSQL with default backup settings:
<DatabaseConfigurationOptions>
<DatabaseType>Jellyfin-PostgreSQL</DatabaseType>
<LockingBehavior>NoLock</LockingBehavior>
<CustomProviderOptions>
<PluginName>Jellyfin-PostgreSQL</PluginName>
<PluginAssembly>Jellyfin.Database.Providers.Postgres</PluginAssembly>
<ConnectionString>Host=localhost;Port=5432;Database=jellyfin;Username=jellyfin;Password=your_password</ConnectionString>
</CustomProviderOptions>
<!-- Backup configuration (all settings are optional) -->
<BackupOptions>
<PgDumpPath>pg_dump</PgDumpPath>
<BackupFormat>custom</BackupFormat>
</BackupOptions>
</DatabaseConfigurationOptions>
Backup Options Reference
PgDumpPath
Type: string (optional)
Default: Searches in system PATH
The full path to the pg_dump executable. If not specified, Jellyfin will search common locations:
- Windows:
C:\Program Files\PostgreSQL\{version}\bin\pg_dump.exe - Linux:
/usr/bin/pg_dump,/usr/local/bin/pg_dump
Examples:
<!-- Windows -->
<PgDumpPath>C:\Program Files\PostgreSQL\16\bin\pg_dump.exe</PgDumpPath>
<!-- Linux -->
<PgDumpPath>/usr/bin/pg_dump</PgDumpPath>
<!-- Search in PATH -->
<PgDumpPath>pg_dump</PgDumpPath>
PgRestorePath
Type: string (optional)
Default: Searches in system PATH
Path to the pg_restore executable. Same search behavior as PgDumpPath.
BackupFormat
Type: string
Default: custom
Valid values: custom, plain, directory, tar
The backup file format:
- custom: Compressed custom format (recommended) - can be restored with
pg_restore - plain: Plain SQL script - can be restored with
psql - directory: Directory format with one file per table
- tar: Tar archive format
<BackupFormat>custom</BackupFormat>
IncludeBlobs
Type: boolean
Default: true
Whether to include large objects (BLOBs) in the backup.
<IncludeBlobs>true</IncludeBlobs>
CompressionLevel
Type: integer (0-9)
Default: 6
Compression level for custom and directory formats. Higher values mean better compression but slower speed.
0= No compression9= Maximum compression6= Good balance (recommended)
<CompressionLevel>6</CompressionLevel>
TimeoutSeconds
Type: integer
Default: 1800 (30 minutes)
Maximum time in seconds to wait for backup/restore operations to complete.
<TimeoutSeconds>1800</TimeoutSeconds>
VerboseOutput
Type: boolean
Default: true
Enable verbose logging output from pg_dump/pg_restore operations.
<VerboseOutput>true</VerboseOutput>
ParallelJobs
Type: integer (optional)
Default: null
Number of parallel jobs for backup operations. Only works with directory format.
<BackupFormat>directory</BackupFormat>
<ParallelJobs>4</ParallelJobs>
AdditionalArguments
Type: string (optional)
Default: null
Additional command-line arguments to pass to pg_dump.
Examples:
<!-- Exclude specific table data -->
<AdditionalArguments>--exclude-table-data=public.temp_logs</AdditionalArguments>
<!-- Exclude schema -->
<AdditionalArguments>--exclude-schema=archive</AdditionalArguments>
<!-- Multiple arguments -->
<AdditionalArguments>--exclude-table-data=public.logs --exclude-schema=test</AdditionalArguments>
Complete Example Configuration
<DatabaseConfigurationOptions>
<DatabaseType>Jellyfin-PostgreSQL</DatabaseType>
<LockingBehavior>NoLock</LockingBehavior>
<CustomProviderOptions>
<PluginName>Jellyfin-PostgreSQL</PluginName>
<PluginAssembly>Jellyfin.Database.Providers.Postgres</PluginAssembly>
<ConnectionString>Host=localhost;Port=5432;Database=jellyfin;Username=jellyfin;Password=your_password</ConnectionString>
</CustomProviderOptions>
<BackupOptions>
<!-- Paths to executables -->
<PgDumpPath>C:\Program Files\PostgreSQL\16\bin\pg_dump.exe</PgDumpPath>
<PgRestorePath>C:\Program Files\PostgreSQL\16\bin\pg_restore.exe</PgRestorePath>
<!-- Backup format and compression -->
<BackupFormat>custom</BackupFormat>
<CompressionLevel>6</CompressionLevel>
<IncludeBlobs>true</IncludeBlobs>
<!-- Performance and timeout -->
<TimeoutSeconds>3600</TimeoutSeconds>
<VerboseOutput>true</VerboseOutput>
<!-- Optional: Parallel processing for directory format -->
<!-- <ParallelJobs>4</ParallelJobs> -->
<!-- Optional: Additional pg_dump arguments -->
<!-- <AdditionalArguments>--exclude-table-data=public.temp_data</AdditionalArguments> -->
</BackupOptions>
</DatabaseConfigurationOptions>
Usage in Code
The backup service will automatically read these settings from database.xml:
// Inject the service
public class MyClass
{
private readonly PostgresBackupService _backupService;
public MyClass(PostgresBackupService backupService)
{
_backupService = backupService;
}
// Create a backup
public async Task CreateBackup()
{
var backupPath = await _backupService.CreateBackupAsync("/path/to/backups");
Console.WriteLine($"Backup created: {backupPath}");
}
// Restore a backup
public async Task RestoreBackup(string backupFile)
{
await _backupService.RestoreBackupAsync(backupFile);
Console.WriteLine("Backup restored successfully");
}
}
Troubleshooting
"pg_dump executable not found"
- Verify PostgreSQL is installed
- Check that
pg_dumpis in your system PATH, or - Specify the full path in
<PgDumpPath>configuration
Permission Issues
- Ensure the user running Jellyfin has execute permissions for
pg_dump - Verify database credentials have backup privileges
Backup Takes Too Long
- Increase
<TimeoutSeconds>value - Consider using
<ParallelJobs>with directory format for large databases - Reduce
<CompressionLevel>for faster backups
Restore Fails
- Verify the backup file format matches what pg_restore expects
- Check that the target database exists and is accessible
- Review logs for specific error messages
Security Notes
-
Password Storage: The connection string in
database.xmlcontains the database password. Ensure this file has appropriate permissions (readable only by the Jellyfin user). -
PGPASSWORD: The service uses the
PGPASSWORDenvironment variable to pass credentials to pg_dump, which is more secure than command-line arguments. -
Backup Files: Backup files contain your entire database. Store them securely and restrict access appropriately.