Files
pgsql-jellyfin/docs/POSTGRES_BACKUP_LOCAL_ONLY_IMPLEMENTATION.md
T
wjones 8f860a8ec3 Centralize build output and generate OS-specific startup.json
- 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
2026-02-26 14:21:26 -05:00

236 lines
8.6 KiB
Markdown

# 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:
```csharp
private readonly IConfigurationManager? configurationManager;
private PostgresBackupService? backupService;
private string? currentHost;
```
#### Updated Constructor:
- Added optional `IConfigurationManager` parameter
- Allows backup service initialization when configuration is available
#### New Method: `IsLocalHost()`
```csharp
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 `PostgresBackupService` **only if host is local**
- Logs appropriate messages based on whether database is local or remote
```csharp
// 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**:
```xml
<!--
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):
```xml
<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):
```xml
<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:
```bash
# 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:
1. **Local Access Required**: `pg_dump` and `pg_restore` must be executed on the same machine as the PostgreSQL server for reliable filesystem access
2. **Credentials**: Running pg_dump against remote servers requires storing remote credentials
3. **Network Overhead**: Large backups over network connections can be slow and unreliable
4. **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:
1. **On the PostgreSQL server**, set up a cron job:
```bash
# /etc/cron.daily/jellyfin-backup.sh
pg_dump -U jellyfin -d jellyfin -F c -f /backups/jellyfin_$(date +%Y%m%d).dump
```
2. **Use PostgreSQL's native backup features**:
- Continuous archiving (WAL archiving)
- Streaming replication
- Point-in-time recovery (PITR)
- pgBackRest or Barman for enterprise backups
3. **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:
```csharp
// 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.