diff --git a/Jellyfin.Server.Implementations/Extensions/ServiceCollectionExtensions.cs b/Jellyfin.Server.Implementations/Extensions/ServiceCollectionExtensions.cs
index aed695c35..abdd5ec83 100644
--- a/Jellyfin.Server.Implementations/Extensions/ServiceCollectionExtensions.cs
+++ b/Jellyfin.Server.Implementations/Extensions/ServiceCollectionExtensions.cs
@@ -149,6 +149,23 @@ public static class ServiceCollectionExtensions
"No PostgreSQL connection string found. Set the POSTGRES_CONNECTION_STRING environment variable, " +
"or provide it via CustomProviderOptions.Options[\"ConnectionString\"] or CustomProviderOptions.ConnectionString.");
+ // Support postgresql:// / postgres:// URI format (e.g. DATABASE_URL convention).
+ // NpgsqlDataSourceBuilder requires ADO.NET key=value format; convert if needed.
+ if (connectionString.StartsWith("postgresql://", StringComparison.OrdinalIgnoreCase)
+ || connectionString.StartsWith("postgres://", StringComparison.OrdinalIgnoreCase))
+ {
+ var uri = new Uri(connectionString);
+ var userInfoParts = uri.UserInfo.Split(':', 2);
+ connectionString = new NpgsqlConnectionStringBuilder
+ {
+ Host = uri.Host,
+ Port = uri.Port > 0 ? uri.Port : 5432,
+ Database = uri.AbsolutePath.TrimStart('/'),
+ Username = userInfoParts.Length > 0 ? Uri.UnescapeDataString(userInfoParts[0]) : null,
+ Password = userInfoParts.Length > 1 ? Uri.UnescapeDataString(userInfoParts[1]) : null,
+ }.ToString();
+ }
+
var dataSourceBuilder = new NpgsqlDataSourceBuilder(connectionString);
dataSourceBuilder.ConnectionStringBuilder.MinPoolSize = GetPoolOption(options, "MinPoolSize", 2);
diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.PostgreSQL/PostgreSqlDatabaseProvider.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.PostgreSQL/PostgreSqlDatabaseProvider.cs
index 9b0367685..8fac80484 100644
--- a/src/Jellyfin.Database/Jellyfin.Database.Providers.PostgreSQL/PostgreSqlDatabaseProvider.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.PostgreSQL/PostgreSqlDatabaseProvider.cs
@@ -15,8 +15,9 @@ namespace Jellyfin.Database.Providers.PostgreSQL;
[JellyfinDatabaseProviderKey("Jellyfin-PostgreSQL")]
public sealed class PostgreSqlDatabaseProvider : IJellyfinDatabaseProvider
{
- private const string BackupNotSupportedMessage =
- "Automated migration backups are not supported for PostgreSQL. Use the jellyfin-pg-backup CronJob for nightly S3 backups.";
+ // Sentinel returned by MigrationBackupFast to signal that no file backup was
+ // created (PostgreSQL backups are handled externally by jellyfin-pg-backup CronJob).
+ private const string NoAutomatedBackupKey = "postgresql-no-automated-backup";
private readonly NpgsqlDataSource _dataSource;
@@ -69,19 +70,24 @@ public sealed class PostgreSqlDatabaseProvider : IJellyfinDatabaseProvider
///
public Task MigrationBackupFast(CancellationToken cancellationToken)
{
- throw new NotSupportedException(BackupNotSupportedMessage);
+ // PostgreSQL pre-migration backups are handled externally by the
+ // jellyfin-pg-backup CronJob. Return a sentinel so callers know no
+ // file backup was created and the migration can proceed safely.
+ return Task.FromResult(NoAutomatedBackupKey);
}
///
public Task RestoreBackupFast(string key, CancellationToken cancellationToken)
{
- throw new NotSupportedException(BackupNotSupportedMessage);
+ // No automated backup was taken; nothing to restore.
+ return Task.CompletedTask;
}
///
public Task DeleteBackup(string key)
{
- throw new NotSupportedException(BackupNotSupportedMessage);
+ // No automated backup was taken; nothing to delete.
+ return Task.CompletedTask;
}
///