- All DLLs now output to lib\[Configuration]\[TargetFramework]\ at repo root (see Directory.Build.props) - .gitignore updated to exclude /lib/ - On first run, startup.json is auto-generated with OS-appropriate default paths (Windows, Linux, macOS, or portable) - Removes null/example config; generated config is immediately usable and clearly documented - Extensive new documentation: build output, startup.json logic, visual guides, and code proofs - Publish profile now deletes existing files for clean deploys - No breaking changes: existing startup.json files are preserved - Improves first-run UX, deployment, and cross-platform consistency
8.6 KiB
PostgreSQL Backup - Local-Only Implementation Summary
Overview
The PostgreSQL backup functionality using pg_dump and pg_restore has been updated to ONLY work with local databases (localhost or 127.0.0.1). For remote PostgreSQL servers, users must manage backups externally.
Changes Made
1. PostgresDatabaseProvider.cs
Added Fields:
private readonly IConfigurationManager? configurationManager;
private PostgresBackupService? backupService;
private string? currentHost;
Updated Constructor:
- Added optional
IConfigurationManagerparameter - Allows backup service initialization when configuration is available
New Method: IsLocalHost()
private static bool IsLocalHost(string? host)
{
return host.Equals("localhost", StringComparison.OrdinalIgnoreCase) ||
host.Equals("127.0.0.1", StringComparison.Ordinal) ||
host.Equals("::1", StringComparison.Ordinal); // IPv6 localhost
}
Updated Initialise() Method:
- Captures the database host from connection string
- Initializes
PostgresBackupServiceonly if host is local - Logs appropriate messages based on whether database is local or remote
// Store the host for backup operations
currentHost = connectionBuilder.Host;
// Initialize backup service if host is local and configuration manager is available
if (IsLocalHost(currentHost) && configurationManager is not null)
{
backupService = new PostgresBackupService(backupLogger, configurationManager);
logger.LogInformation("PostgreSQL backup service initialized for local database");
}
else if (!IsLocalHost(currentHost))
{
logger.LogInformation("PostgreSQL database is on remote server ({Host}). Backup operations via pg_dump/pg_restore are disabled", currentHost);
}
Updated Backup Methods:
MigrationBackupFast():
- Local database: Uses
PostgresBackupService.CreateBackupAsync() - Remote database: Returns timestamp key, logs warning
RestoreBackupFast():
- Local database: Uses
PostgresBackupService.RestoreBackupAsync() - Remote database: Logs warning only
DeleteBackup():
- Local database: Deletes backup file from disk
- Remote database: Logs warning
2. Updated Log Messages
All messages now specify "on a remote server" for clarity:
| Old Message | New Message |
|---|---|
| "Backup deletion is not implemented for PostgreSQL. Manage backups externally." | "Backup deletion is not implemented for PostgreSQL on a remote server. Manage backups externally." |
| "Fast backup is not implemented for PostgreSQL. Use pg_dump for proper backups." | "Fast backup is not implemented for PostgreSQL on a remote server. Use pg_dump manually for proper backups." |
| "Fast restore is not implemented for PostgreSQL. Use pg_restore for proper restoration." | "Fast restore is not implemented for PostgreSQL on a remote server. Use pg_restore manually for proper restoration." |
3. Updated Configuration Documentation
database.xml.example:
<!--
IMPORTANT: pg_dump/pg_restore backup features are ONLY available when the
PostgreSQL database host is localhost or 127.0.0.1. For remote databases,
you must manage backups externally using pg_dump/pg_restore commands manually.
-->
BACKUP_CONFIGURATION.md:
- Added prominent warning about local-only requirement
- Clarified behavior for remote databases
- Updated examples and troubleshooting sections
Behavior Matrix
| Database Host | Backup Service Initialized? | Backup Operations | Log Message |
|---|---|---|---|
localhost |
✅ Yes | Fully functional via pg_dump/pg_restore | "PostgreSQL backup service initialized for local database" |
127.0.0.1 |
✅ Yes | Fully functional via pg_dump/pg_restore | "PostgreSQL backup service initialized for local database" |
::1 (IPv6) |
✅ Yes | Fully functional via pg_dump/pg_restore | "PostgreSQL backup service initialized for local database" |
192.168.1.10 (remote) |
❌ No | Disabled, external management required | "PostgreSQL database is on remote server ({Host}). Backup operations via pg_dump/pg_restore are disabled" |
db.example.com (remote) |
❌ No | Disabled, external management required | "PostgreSQL database is on remote server ({Host}). Backup operations via pg_dump/pg_restore are disabled" |
Example Configurations
Local Database (Backups Enabled):
<DatabaseConfigurationOptions>
<DatabaseType>Jellyfin-PostgreSQL</DatabaseType>
<CustomProviderOptions>
<PluginName>Jellyfin-PostgreSQL</PluginName>
<PluginAssembly>Jellyfin.Database.Providers.Postgres</PluginAssembly>
<ConnectionString>Host=localhost;Port=5432;Database=jellyfin;Username=jellyfin;Password=pwd</ConnectionString>
</CustomProviderOptions>
<BackupOptions>
<PgDumpPath>pg_dump</PgDumpPath>
<BackupFormat>custom</BackupFormat>
<CompressionLevel>6</CompressionLevel>
</BackupOptions>
</DatabaseConfigurationOptions>
Result: ✅ Backups work automatically via pg_dump/pg_restore
Remote Database (Backups Disabled):
<DatabaseConfigurationOptions>
<DatabaseType>Jellyfin-PostgreSQL</DatabaseType>
<CustomProviderOptions>
<PluginName>Jellyfin-PostgreSQL</PluginName>
<PluginAssembly>Jellyfin.Database.Providers.Postgres</PluginAssembly>
<ConnectionString>Host=192.168.1.50;Port=5432;Database=jellyfin;Username=jellyfin;Password=pwd</ConnectionString>
</CustomProviderOptions>
<!-- BackupOptions are ignored for remote databases -->
<BackupOptions>
<PgDumpPath>pg_dump</PgDumpPath>
</BackupOptions>
</DatabaseConfigurationOptions>
Result: ❌ Backup operations log warnings; users must manually run:
# Manual backup on remote server
pg_dump -h 192.168.1.50 -p 5432 -U jellyfin -d jellyfin -F c -f backup.dump
# Manual restore on remote server
pg_restore -h 192.168.1.50 -p 5432 -U jellyfin -d jellyfin backup.dump
Security Rationale
This restriction exists because:
- Local Access Required:
pg_dumpandpg_restoremust be executed on the same machine as the PostgreSQL server for reliable filesystem access - Credentials: Running pg_dump against remote servers requires storing remote credentials
- Network Overhead: Large backups over network connections can be slow and unreliable
- Best Practice: Remote PostgreSQL deployments should have their own backup infrastructure (scheduled pg_dump jobs, WAL archiving, replication, etc.)
Migration Path
If you previously had a remote PostgreSQL setup expecting automatic backups:
Before (Not Working):
- Jellyfin connected to remote PostgreSQL
- Expected automatic backups (didn't work)
After (Clear Behavior):
- Jellyfin connects to remote PostgreSQL
- Clear log messages indicate backups are disabled
- Documentation provides manual backup commands
Recommended Setup for Remote Databases:
-
On the PostgreSQL server, set up a cron job:
# /etc/cron.daily/jellyfin-backup.sh pg_dump -U jellyfin -d jellyfin -F c -f /backups/jellyfin_$(date +%Y%m%d).dump -
Use PostgreSQL's native backup features:
- Continuous archiving (WAL archiving)
- Streaming replication
- Point-in-time recovery (PITR)
- pgBackRest or Barman for enterprise backups
-
Cloud-native solutions:
- AWS RDS automated backups
- Azure Database for PostgreSQL automated backups
- Google Cloud SQL automated backups
Testing
To test the local vs. remote behavior:
// Test with localhost
var localConfig = new DatabaseConfigurationOptions
{
CustomProviderOptions = new CustomDatabaseOptions
{
Options = new[]
{
new CustomDatabaseOption { Key = "host", Value = "localhost" }
}
}
};
// Result: Backup service initialized
// Test with remote host
var remoteConfig = new DatabaseConfigurationOptions
{
CustomProviderOptions = new CustomDatabaseOptions
{
Options = new[]
{
new CustomDatabaseOption { Key = "host", Value = "192.168.1.50" }
}
}
};
// Result: Backup service NOT initialized, warning logged
Summary
✅ Local databases (localhost/127.0.0.1): Full automated backup support via pg_dump/pg_restore
❌ Remote databases: Backup operations disabled, clear messaging, external management required
📝 Documentation: Updated to clearly explain the local-only restriction
🔒 Security: Follows best practices for remote database backup management
This implementation provides a clear, safe, and maintainable approach to PostgreSQL backups in Jellyfin.