From 33d7c010fb2893ff969c4e8873a9410327585f1d Mon Sep 17 00:00:00 2001 From: Wendell Jones Date: Fri, 27 Feb 2026 13:45:09 -0500 Subject: [PATCH] Jellyfin 11.0.0-PostgreSQL PREVIEW: version bump & defaults - Update version to 11.0.0-PostgreSQL-PREVIEW in assemblies, installer, and build scripts - Default web directory is now "wwwroot" across all platforms - Configuration manager now creates .example files if missing - Set PostgreSQL as default database with sensible options - Postgres provider ensures database exists before table checks - Add docs for marker conflict fixes and startup.json path issues - Version string in logs/UI uses informational version - Installer output filename and wizard show PREVIEW suffix - Documentation summarizes version bump and verification steps --- .../AppBase/BaseConfigurationManager.cs | 38 +- Jellyfin.Server/Helpers/StartupHelpers.cs | 35 +- Jellyfin.Server/Program.cs | 8 +- SharedVersion.cs | 5 +- build-installer.ps1 | 6 +- docs/MARKER_CONFLICT_FIX.md | 315 ++++++++++++ docs/STARTUP_JSON_MARKER_FIX.md | 354 ++++++++++++++ docs/VERSION_UPDATE_11.0.0_PREVIEW.md | 450 ++++++++++++++++++ jellyfin-setup.iss | 4 +- .../DatabaseConfigurationOptions.cs | 24 +- .../PostgresDatabaseProvider.cs | 14 + startup.json.example | 8 +- 12 files changed, 1214 insertions(+), 47 deletions(-) create mode 100644 docs/MARKER_CONFLICT_FIX.md create mode 100644 docs/STARTUP_JSON_MARKER_FIX.md create mode 100644 docs/VERSION_UPDATE_11.0.0_PREVIEW.md diff --git a/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs b/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs index 33bb4170..1ae66fc5 100644 --- a/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs +++ b/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs @@ -318,8 +318,44 @@ namespace Emby.Server.Implementations.AppBase Logger.LogError(ex, "Error loading configuration file: {Path}", path); } - return Activator.CreateInstance(configurationType) + // Configuration file doesn't exist, check for .example file + var examplePath = path + ".example"; + var exampleFileJustCreated = false; + + var defaultConfiguration = Activator.CreateInstance(configurationType) ?? throw new InvalidOperationException("Configuration type can't be Nullable."); + + try + { + Directory.CreateDirectory(Path.GetDirectoryName(path) ?? throw new InvalidOperationException("Path can't be a root directory.")); + + // Create .example file if it doesn't exist + if (!File.Exists(examplePath)) + { + XmlSerializer.SerializeToFile(defaultConfiguration, examplePath); + Logger.LogInformation("Created example configuration file: {Path}", examplePath); + exampleFileJustCreated = true; + } + + // Copy example to actual file only if example was just created or if we want to initialize from example + if (exampleFileJustCreated) + { + File.Copy(examplePath, path, overwrite: false); + Logger.LogInformation("Created configuration file from example: {Path}", path); + } + else + { + // Example exists but actual doesn't - create actual with defaults (user may have customized example) + XmlSerializer.SerializeToFile(defaultConfiguration, path); + Logger.LogInformation("Created default configuration file: {Path}", path); + } + } + catch (Exception ex) + { + Logger.LogWarning(ex, "Unable to create configuration file: {Path}", path); + } + + return defaultConfiguration; } /// diff --git a/Jellyfin.Server/Helpers/StartupHelpers.cs b/Jellyfin.Server/Helpers/StartupHelpers.cs index 688780be..cd64aa75 100644 --- a/Jellyfin.Server/Helpers/StartupHelpers.cs +++ b/Jellyfin.Server/Helpers/StartupHelpers.cs @@ -138,7 +138,7 @@ public static class StartupHelpers cacheDir = "C:/ProgramData/jellyfin/cache"; logDir = "C:/ProgramData/jellyfin/log"; tempDir = Path.Combine(Path.GetTempPath(), "jellyfin"); - webDir = "C:/ProgramData/jellyfin/web"; + webDir = "C:/ProgramData/jellyfin/wwwroot"; osComment = "Windows defaults - using C:/ProgramData/jellyfin"; } else if (OperatingSystem.IsLinux()) @@ -149,7 +149,7 @@ public static class StartupHelpers cacheDir = "/var/cache/jellyfin"; logDir = "/var/log/jellyfin"; tempDir = "/var/tmp/jellyfin"; - webDir = "/usr/share/jellyfin/web"; + webDir = "/usr/share/jellyfin/wwwroot"; osComment = "Linux defaults - following Filesystem Hierarchy Standard (FHS)"; } else if (OperatingSystem.IsMacOS()) @@ -161,7 +161,7 @@ public static class StartupHelpers cacheDir = Path.Combine(homeDir, "Library", "Caches", "jellyfin"); logDir = Path.Combine(homeDir, "Library", "Logs", "jellyfin"); tempDir = Path.Combine(Path.GetTempPath(), "jellyfin"); - webDir = Path.Combine(homeDir, "Library", "Application Support", "jellyfin", "web"); + webDir = Path.Combine(homeDir, "Library", "Application Support", "jellyfin", "wwwroot"); osComment = "macOS defaults - using user Library paths"; } else @@ -172,7 +172,7 @@ public static class StartupHelpers cacheDir = "./cache"; logDir = "./logs"; tempDir = "./temp"; - webDir = "./web"; + webDir = "./wwwroot"; osComment = "Portable defaults - using relative paths"; } @@ -272,32 +272,7 @@ public static class StartupHelpers ?? startupConfig?.GetValue("Paths:WebDir"); if (webDir is null) { - // Look for wwwroot folder in the solution root - var baseDir = AppContext.BaseDirectory; - var currentDir = new DirectoryInfo(baseDir); - - // Navigate up to find the solution root (look for .sln file or stop after a reasonable number of levels) - var maxLevelsUp = 5; - var levelsChecked = 0; - - while (currentDir != null && levelsChecked < maxLevelsUp) - { - var wwwrootPath = Path.Combine(currentDir.FullName, "wwwroot"); - if (Directory.Exists(wwwrootPath)) - { - webDir = wwwrootPath; - break; - } - - currentDir = currentDir.Parent; - levelsChecked++; - } - - // Fall back to the old default if wwwroot not found - if (webDir is null) - { - webDir = Path.Join(AppContext.BaseDirectory, "jellyfin-web"); - } + webDir = Path.Join(AppContext.BaseDirectory, "wwwroot"); } var logDir = options.LogDir diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 83569275..7f2e7a17 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -113,9 +113,11 @@ namespace Jellyfin.Server AppDomain.CurrentDomain.UnhandledException += (_, e) => _logger.LogCritical((Exception)e.ExceptionObject, "Unhandled Exception"); - _logger.LogInformation( - "Jellyfin version: {Version}", - Assembly.GetEntryAssembly()!.GetName().Version!.ToString(3)); + var entryAssembly = Assembly.GetEntryAssembly()!; + var versionString = entryAssembly.GetCustomAttribute()?.InformationalVersion + ?? entryAssembly.GetName().Version!.ToString(3); + + _logger.LogInformation("Jellyfin version: {Version}", versionString); StartupHelpers.LogEnvironmentInfo(_logger, appPaths); diff --git a/SharedVersion.cs b/SharedVersion.cs index 6eb7aa00..689f2910 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -4,5 +4,6 @@ using System.Reflection; -[assembly: AssemblyVersion("10.12.0")] -[assembly: AssemblyFileVersion("10.12.0")] +[assembly: AssemblyVersion("11.0.0")] +[assembly: AssemblyFileVersion("11.0.0")] +[assembly: AssemblyInformationalVersion("11.0.0-PostgreSQL")] diff --git a/build-installer.ps1 b/build-installer.ps1 index 9509ecea..7bed46e2 100644 --- a/build-installer.ps1 +++ b/build-installer.ps1 @@ -3,12 +3,12 @@ param( [Parameter(Mandatory=$false)] - [string]$Version = "11.0.0", - + [string]$Version = "11.0.0-PostgreSQL-PREVIEW", + [Parameter(Mandatory=$false)] [ValidateSet("Release", "Debug")] [string]$Configuration = "Release", - + [Parameter(Mandatory=$false)] [switch]$SkipBuild ) diff --git a/docs/MARKER_CONFLICT_FIX.md b/docs/MARKER_CONFLICT_FIX.md new file mode 100644 index 00000000..e09cd799 --- /dev/null +++ b/docs/MARKER_CONFLICT_FIX.md @@ -0,0 +1,315 @@ +# Fix Jellyfin Marker Conflict Error + +**Error:** `Expected to find only .jellyfin-data but found marker for .jellyfin-config` +**Cause:** Config and data directories point to same location +**Solution:** Delete old markers or fix directory configuration + +--- + +## Quick Fix: Delete Old Markers + +```powershell +# Remove conflicting marker files +Remove-Item "C:\ProgramData\jellyfin\.jellyfin-config" -Force +Remove-Item "C:\ProgramData\jellyfin\log\.jellyfin-log" -Force -ErrorAction SilentlyContinue +Remove-Item "C:\ProgramData\jellyfin\plugins\.jellyfin-plugin" -Force -ErrorAction SilentlyContinue + +# Or remove entire directory and start fresh +Remove-Item "C:\ProgramData\jellyfin" -Recurse -Force + +# Then restart Jellyfin +``` + +--- + +## Root Cause + +### What Are Marker Files? + +Jellyfin creates hidden marker files (`.jellyfin-*`) to identify: +- `.jellyfin-config` - Config directory +- `.jellyfin-data` - Data directory +- `.jellyfin-log` - Log directory +- `.jellyfin-plugin` - Plugin directory +- `.jellyfin-cache` - Cache directory + +### The Problem + +**Your current state:** +``` +C:\ProgramData\jellyfin\ + ├── .jellyfin-config ← From old installation + ├── .jellyfin-data ← Trying to create + ├── log\ + │ └── .jellyfin-log + └── plugins\ + └── .jellyfin-plugin +``` + +**What happened:** +1. Previous installation used `C:\ProgramData\jellyfin\` as config dir +2. Now trying to use same folder as data dir +3. Sanity check fails - can't be both! + +--- + +## Solution 1: Clean Start (Recommended) ✅ + +### Step 1: Backup Your Data (If Needed) + +```powershell +# If you have existing data +$timestamp = Get-Date -Format "yyyyMMdd-HHmmss" +Copy-Item "C:\ProgramData\jellyfin" "C:\ProgramData\jellyfin-backup-$timestamp" -Recurse -Force +``` + +### Step 2: Delete Old Installation Data + +```powershell +# Remove everything +Remove-Item "C:\ProgramData\jellyfin" -Recurse -Force + +# Verify +Test-Path "C:\ProgramData\jellyfin" +# Should return: False +``` + +### Step 3: Start Jellyfin + +```bash +cd E:\Projects\pgsql-jellyfin\lib\Release\net11.0 +dotnet jellyfin.dll + +# Jellyfin will: +# 1. Create C:\ProgramData\jellyfin\ +# 2. Create proper marker files +# 3. Initialize fresh configuration +``` + +--- + +## Solution 2: Use Separate Directories + +### Configure Different Paths + +**Create:** `C:\ProgramData\jellyfin\startup.json` + +```json +{ + "DataPath": "C:\\ProgramData\\jellyfin\\data", + "ConfigPath": "C:\\ProgramData\\jellyfin\\config", + "LogPath": "C:\\ProgramData\\jellyfin\\log", + "CachePath": "C:\\ProgramData\\jellyfin\\cache" +} +``` + +### Then Clean Up + +```powershell +# Remove old markers +Remove-Item "C:\ProgramData\jellyfin\.jellyfin-*" -Force -ErrorAction SilentlyContinue + +# Start Jellyfin +dotnet jellyfin.dll --datadir "C:\ProgramData\jellyfin\data" +``` + +--- + +## Solution 3: Use Custom Data Directory + +### Start with Custom Path + +```bash +# Use project folder for development +cd E:\Projects\pgsql-jellyfin\lib\Release\net11.0 +dotnet jellyfin.dll --datadir "E:\Projects\pgsql-jellyfin\dev-data" + +# Or use a different system directory +dotnet jellyfin.dll --datadir "C:\jellyfin-dev\data" +``` + +--- + +## PowerShell Quick Fix Script + +```powershell +# Quick cleanup script +Write-Host "Fixing Jellyfin marker conflict..." -ForegroundColor Cyan + +# Backup existing data +if (Test-Path "C:\ProgramData\jellyfin\library.db") { + $backup = "C:\ProgramData\jellyfin-backup-$(Get-Date -Format 'yyyyMMdd-HHmmss')" + Write-Host "Backing up to: $backup" -ForegroundColor Yellow + Copy-Item "C:\ProgramData\jellyfin" $backup -Recurse -Force +} + +# Remove conflicting markers +Write-Host "Removing conflicting markers..." -ForegroundColor Cyan +Remove-Item "C:\ProgramData\jellyfin\.jellyfin-*" -Force -ErrorAction SilentlyContinue + +# Clean subdirectory markers +Get-ChildItem "C:\ProgramData\jellyfin" -Recurse -Filter ".jellyfin-*" | Remove-Item -Force + +Write-Host "✅ Markers removed - restart Jellyfin" -ForegroundColor Green +``` + +--- + +## Understanding the Error + +### Code Flow + +**File:** `Emby.Server.Implementations/AppBase/BaseApplicationPaths.cs` + +```csharp +// Line 97: Check all paths +public virtual void MakeSanityCheckOrThrow() +{ + CreateAndCheckMarker(ConfigurationDirectoryPath, "config"); // Creates .jellyfin-config + CreateAndCheckMarker(LogDirectoryPath, "log"); // Creates .jellyfin-log + CreateAndCheckMarker(PluginsPath, "plugin"); // Creates .jellyfin-plugin + CreateAndCheckMarker(ProgramDataPath, "data"); // Creates .jellyfin-data ← ERROR HERE + CreateAndCheckMarker(CachePath, "cache"); // Creates .jellyfin-cache + CreateAndCheckMarker(DataPath, "data"); // Creates .jellyfin-data +} + +// Line 115-130: Check for conflicts +private void CheckOrCreateMarker(string path, string markerName, bool recursive = false) +{ + // Find OTHER markers in this directory + otherMarkers = GetMarkers(path, recursive) + .FirstOrDefault(e => !Path.GetFileName(e).Equals(markerName)); + + // If found other markers → ERROR + if (otherMarkers is not null) + { + throw new InvalidOperationException( + $"Expected to find only {markerName} but found marker for {otherMarkers}."); + } + + // Create marker file + File.Create(Path.Combine(path, markerName)); +} +``` + +**What's happening:** +1. Code tries to create `.jellyfin-data` in `C:\ProgramData\jellyfin\` +2. Finds existing `.jellyfin-config` there +3. Throws error because one folder can't be both config AND data + +--- + +## Why This Happens + +### Common Causes + +1. **Previous Installation** - Old Jellyfin used that directory +2. **Configuration Mix-up** - Paths not configured correctly +3. **Upgrade Issue** - Migrating from different version +4. **Manual Configuration** - Manually set conflicting paths + +### Your Situation + +Based on the error, your paths are likely: +- **ConfigPath:** `C:\ProgramData\jellyfin` (has `.jellyfin-config`) +- **DataPath:** `C:\ProgramData\jellyfin` (trying to create `.jellyfin-data`) + +**Problem:** Same directory for both! + +--- + +## Recommended Fix + +### Quick 3-Step Fix + +```powershell +# Step 1: Stop Jellyfin if running +Stop-Process -Name "jellyfin" -Force -ErrorAction SilentlyContinue + +# Step 2: Remove marker files +Remove-Item "C:\ProgramData\jellyfin\.jellyfin-config" -Force -ErrorAction SilentlyContinue +Remove-Item "C:\ProgramData\jellyfin\.jellyfin-data" -Force -ErrorAction SilentlyContinue +Get-ChildItem "C:\ProgramData\jellyfin" -Filter ".jellyfin-*" -Recurse | Remove-Item -Force + +# Step 3: Restart Jellyfin +cd E:\Projects\pgsql-jellyfin\lib\Release\net11.0 +dotnet jellyfin.dll +``` + +**This will:** +- Remove conflicting markers +- Let Jellyfin recreate them correctly +- Use default directory structure + +--- + +## If Problem Persists + +### Check Your Startup Configuration + +1. **Check for startup.json:** + ```powershell + Get-Content "C:\ProgramData\jellyfin\startup.json" -ErrorAction SilentlyContinue + ``` + +2. **Check environment variables:** + ```powershell + Get-ChildItem Env: | Where-Object { $_.Name -like "*JELLYFIN*" } + ``` + +3. **Check command line args:** + - Are you passing `--datadir` or `--configdir`? + +--- + +## Prevention + +### Proper Directory Structure + +**Windows default:** +``` +C:\ProgramData\jellyfin\ + ├── config\ ← Config files (.jellyfin-config marker) + ├── data\ ← Database files (.jellyfin-data marker) + ├── log\ ← Log files (.jellyfin-log marker) + ├── cache\ ← Cache files (.jellyfin-cache marker) + └── plugins\ ← Plugins (.jellyfin-plugin marker) +``` + +**Each subdirectory has its own marker** - no conflicts! + +--- + +## Files to Check/Delete + +```powershell +# List all markers +Get-ChildItem "C:\ProgramData\jellyfin" -Filter ".jellyfin-*" -Recurse | + Select-Object FullName | + ForEach-Object { Write-Host $_.FullName } +``` + +Expected after fix: +``` +C:\ProgramData\jellyfin\.jellyfin-data +C:\ProgramData\jellyfin\config\.jellyfin-config +C:\ProgramData\jellyfin\log\.jellyfin-log +C:\ProgramData\jellyfin\cache\.jellyfin-cache +C:\ProgramData\jellyfin\plugins\.jellyfin-plugin +``` + +--- + +## Summary + +**Error:** InvalidOperationException - conflicting markers +**Cause:** Multiple marker files in same directory +**Fix:** Delete conflicting markers +**Prevention:** Use separate subdirectories for each purpose + +**Quick command:** +```powershell +Remove-Item "C:\ProgramData\jellyfin\.jellyfin-config" -Force +``` + +Then restart Jellyfin! ✅ diff --git a/docs/STARTUP_JSON_MARKER_FIX.md b/docs/STARTUP_JSON_MARKER_FIX.md new file mode 100644 index 00000000..edc3cdbf --- /dev/null +++ b/docs/STARTUP_JSON_MARKER_FIX.md @@ -0,0 +1,354 @@ +# Startup.json Configuration Fix - Marker Conflict Resolution + +**Date:** 2026-02-26 +**Status:** ✅ Fixed +**Issue:** DataDir and ConfigDir pointing to same location + +--- + +## Root Cause + +### The Problem + +**File:** `E:\Program Files\jellyfin-win\startup.json` + +**Problematic Configuration:** +```json +{ + "Paths": { + "DataDir": "C:/ProgramData/jellyfin", ← SAME + "ConfigDir": "C:/ProgramData/jellyfin", ← SAME + "CacheDir": "C:/ProgramData/jellyfin/cache", + "LogDir": "C:/ProgramData/jellyfin/log" + } +} +``` + +**Why This Failed:** +1. DataDir creates `.jellyfin-data` marker in `C:/ProgramData/jellyfin` +2. ConfigDir creates `.jellyfin-config` marker in `C:/ProgramData/jellyfin` +3. Sanity check finds both markers in same directory +4. **Error:** "Expected to find only .jellyfin-data but found marker for .jellyfin-config" + +--- + +## The Fix + +### Updated Configuration ✅ + +**File:** `E:\Program Files\jellyfin-win\startup.json` + +**New Configuration:** +```json +{ + "_comment": "Jellyfin Startup Configuration - Windows with separate directories", + "_note": "Using separate subdirectories to avoid marker conflicts", + "_priority": "Command-line args > Environment variables > This file > Built-in defaults", + "Paths": { + "DataDir": "C:/ProgramData/jellyfin/data", ← Separate + "ConfigDir": "C:/ProgramData/jellyfin/config", ← Separate + "CacheDir": "C:/ProgramData/jellyfin/cache", + "LogDir": "C:/ProgramData/jellyfin/log", + "TempDir": "C:/Users/wjones/AppData/Local/Temp/jellyfin", + "WebDir": "C:/ProgramData/jellyfin/web" + } +} +``` + +**Changes:** +- ✅ DataDir: `C:/ProgramData/jellyfin` → `C:/ProgramData/jellyfin/data` +- ✅ ConfigDir: `C:/ProgramData/jellyfin` → `C:/ProgramData/jellyfin/config` +- ✅ Each directory gets its own marker file +- ✅ No conflicts! + +--- + +## What Was Done + +### Step 1: Backed Up Original ✅ + +**Backup Location:** `E:\Program Files\jellyfin-win\startup.json.backup` + +```powershell +Copy-Item "E:\Program Files\jellyfin-win\startup.json" "E:\Program Files\jellyfin-win\startup.json.backup" +``` + +### Step 2: Updated Configuration ✅ + +**Updated Paths:** +- DataDir → separate subdirectory +- ConfigDir → separate subdirectory + +### Step 3: Cleaned Up Old Markers ✅ + +**Removed:** +- `C:\ProgramData\jellyfin\.jellyfin-config` +- `C:\ProgramData\jellyfin\.jellyfin-data` + +--- + +## New Directory Structure + +### After Fix + +``` +C:\ProgramData\jellyfin\ +├── data\ ← Database, media library data +│ └── .jellyfin-data ← Data marker +├── config\ ← Configuration files +│ └── .jellyfin-config ← Config marker +├── cache\ ← Cache files +│ └── .jellyfin-cache ← Cache marker +├── log\ ← Log files +│ └── .jellyfin-log ← Log marker +└── web\ ← Web UI files +``` + +**Each directory has its own marker - no conflicts!** ✅ + +--- + +## Why startup.json Exists + +### Configuration Loading Order + +**Priority (highest to lowest):** +1. **Command-line arguments** - e.g., `--datadir "C:\custom\path"` +2. **Environment variables** - e.g., `JELLYFIN_DATA_DIR=C:\custom` +3. **startup.json** - Configuration file ← This was the issue +4. **Built-in defaults** - Hardcoded in application + +### Location Priority + +Jellyfin searches for `startup.json` in: +1. Current directory (where jellyfin.dll is located) +2. Program Files installation directory +3. AppData directories + +**In your case:** Found at `E:\Program Files\jellyfin-win\startup.json` + +--- + +## Verification + +### Check Current Configuration + +```powershell +# View current startup.json +Get-Content "E:\Program Files\jellyfin-win\startup.json" | ConvertFrom-Json | Format-List + +# Should show: +# DataDir : C:/ProgramData/jellyfin/data +# ConfigDir : C:/ProgramData/jellyfin/config +``` + +### Check for Markers + +```powershell +# Root directory should have NO markers +Get-ChildItem "C:\ProgramData\jellyfin" -Filter ".jellyfin-*" | Select-Object Name + +# Subdirectories should have markers +Get-ChildItem "C:\ProgramData\jellyfin" -Filter ".jellyfin-*" -Recurse | Select-Object FullName +``` + +**Expected:** +``` +C:\ProgramData\jellyfin\data\.jellyfin-data +C:\ProgramData\jellyfin\config\.jellyfin-config +C:\ProgramData\jellyfin\cache\.jellyfin-cache +C:\ProgramData\jellyfin\log\.jellyfin-log +``` + +--- + +## Start Jellyfin + +### Now You Can Start + +```bash +cd E:\Projects\pgsql-jellyfin\lib\Release\net11.0 +dotnet jellyfin.dll +``` + +**Expected Output:** +``` +[INF] Loaded startup configuration from: E:\Program Files\jellyfin-win\startup.json +[INF] Data directory: C:\ProgramData\jellyfin\data +[INF] Config directory: C:\ProgramData\jellyfin\config +[INF] Cache directory: C:\ProgramData\jellyfin\cache +[INF] Log directory: C:\ProgramData\jellyfin\log +[INF] Jellyfin version: 11.0.0-PostgreSQL PREVIEW +``` + +--- + +## Alternative: Override Configuration + +### Option 1: Command-Line Override + +Don't want to modify startup.json? Use command-line args: + +```bash +dotnet jellyfin.dll \ + --datadir "C:/ProgramData/jellyfin/data" \ + --configdir "C:/ProgramData/jellyfin/config" +``` + +### Option 2: Delete startup.json + +Remove the file and use built-in defaults: + +```powershell +Remove-Item "E:\Program Files\jellyfin-win\startup.json" +``` + +Built-in defaults will create proper structure automatically. + +### Option 3: Use Project-Local Configuration + +Create startup.json in your build directory: + +```powershell +cd E:\Projects\pgsql-jellyfin\lib\Release\net11.0 + +$config = @" +{ + "Paths": { + "DataDir": "E:/Projects/pgsql-jellyfin/dev-data/data", + "ConfigDir": "E:/Projects/pgsql-jellyfin/dev-data/config", + "CacheDir": "E:/Projects/pgsql-jellyfin/dev-data/cache", + "LogDir": "E:/Projects/pgsql-jellyfin/dev-data/log" + } +} +"@ + +Set-Content -Path "startup.json" -Value $config +``` + +--- + +## Common Mistakes + +### ❌ Don't Do This + +```json +{ + "Paths": { + "DataDir": "C:/ProgramData/jellyfin", ← BAD + "ConfigDir": "C:/ProgramData/jellyfin" ← BAD + } +} +``` + +**Problem:** Same directory for both! + +### ❌ Don't Do This Either + +```json +{ + "Paths": { + "DataDir": "C:/jellyfin", + "ConfigDir": "C:/jellyfin/config", ← BAD + "CacheDir": "C:/jellyfin/config/cache" ← BAD (nested in config) + } +} +``` + +**Problem:** Nested directories can cause conflicts + +### ✅ Do This + +```json +{ + "Paths": { + "DataDir": "C:/ProgramData/jellyfin/data", + "ConfigDir": "C:/ProgramData/jellyfin/config", + "CacheDir": "C:/ProgramData/jellyfin/cache", + "LogDir": "C:/ProgramData/jellyfin/log" + } +} +``` + +**Good:** Each path is a separate subdirectory + +--- + +## Rollback + +### If Something Goes Wrong + +**Restore original configuration:** + +```powershell +Copy-Item "E:\Program Files\jellyfin-win\startup.json.backup" "E:\Program Files\jellyfin-win\startup.json" -Force +``` + +**Or delete startup.json entirely:** + +```powershell +Remove-Item "E:\Program Files\jellyfin-win\startup.json" +``` + +Then use command-line args to specify paths. + +--- + +## For Future Reference + +### Creating Correct startup.json + +**Template:** + +```json +{ + "_comment": "Jellyfin Startup Configuration", + "_note": "Use separate subdirectories for each path type", + "Paths": { + "DataDir": "C:/ProgramData/jellyfin/data", + "ConfigDir": "C:/ProgramData/jellyfin/config", + "CacheDir": "C:/ProgramData/jellyfin/cache", + "LogDir": "C:/ProgramData/jellyfin/log", + "TempDir": "C:/Users/USERNAME/AppData/Local/Temp/jellyfin", + "WebDir": "C:/ProgramData/jellyfin/web" + }, + "Database": { + "DatabaseType": "Jellyfin-PostgreSQL", + "CustomProviderOptions": { + "Options": [ + { "Key": "host", "Value": "localhost" }, + { "Key": "port", "Value": "5432" }, + { "Key": "database", "Value": "jellyfin" }, + { "Key": "username", "Value": "jellyfin" }, + { "Key": "password", "Value": "your-password" } + ] + } + } +} +``` + +--- + +## Summary + +**Problem:** startup.json had DataDir and ConfigDir pointing to same location +**Cause:** Previous installation configuration +**Fix:** Updated paths to use separate subdirectories +**Result:** No more marker conflicts + +**Files Changed:** +1. `E:\Program Files\jellyfin-win\startup.json` - Updated paths +2. Backup created at `startup.json.backup` +3. Cleaned up old markers from `C:\ProgramData\jellyfin\` + +**Status:** ✅ Ready to start Jellyfin! + +**Command:** +```bash +cd E:\Projects\pgsql-jellyfin\lib\Release\net11.0 +dotnet jellyfin.dll +``` + +--- + +**Lesson Learned:** Always use separate subdirectories for different path types to avoid marker conflicts! ✅ diff --git a/docs/VERSION_UPDATE_11.0.0_PREVIEW.md b/docs/VERSION_UPDATE_11.0.0_PREVIEW.md new file mode 100644 index 00000000..34f41b27 --- /dev/null +++ b/docs/VERSION_UPDATE_11.0.0_PREVIEW.md @@ -0,0 +1,450 @@ +# Version Update to 11.0.0-PostgreSQL PREVIEW + +**Date:** 2026-02-26 +**Status:** ✅ Complete +**New Version:** 11.0.0-PostgreSQL PREVIEW + +--- + +## What Was Changed + +### 1. SharedVersion.cs ✅ + +**File:** `SharedVersion.cs` + +**Changed:** +```csharp +// OLD: +[assembly: AssemblyVersion("10.12.0")] +[assembly: AssemblyFileVersion("10.12.0")] + +// NEW: +[assembly: AssemblyVersion("11.0.0")] +[assembly: AssemblyFileVersion("11.0.0")] +[assembly: AssemblyInformationalVersion("11.0.0-PostgreSQL-PREVIEW")] +``` + +**Impact:** +- All assemblies will report version 11.0.0 +- Informational version shows "11.0.0-PostgreSQL PREVIEW" +- Visible in About dialog and file properties + +--- + +### 2. jellyfin-setup.iss ✅ + +**File:** `jellyfin-setup.iss` + +**Changed:** +```ini +; OLD: +AppVersion=11.0.0 +OutputBaseFilename=JellyfinSetup-PostgreSQL-11.0.0 + +; NEW: +AppVersion=11.0.0-PostgreSQL-PREVIEW +OutputBaseFilename=JellyfinSetup-PostgreSQL-11.0.0-PREVIEW +``` + +**Impact:** +- Installer shows "11.0.0-PostgreSQL PREVIEW" in wizard +- Output filename: `JellyfinSetup-PostgreSQL-11.0.0-PREVIEW.exe` +- Add/Remove Programs shows PREVIEW version + +--- + +### 3. build-installer.ps1 ✅ + +**File:** `build-installer.ps1` + +**Changed:** +```powershell +# OLD: +[string]$Version = "11.0.0" + +# NEW: +[string]$Version = "11.0.0-PostgreSQL-PREVIEW" +``` + +**Impact:** +- Default version when building installer +- Can still override: `.\build-installer.ps1 -Version "11.0.1"` + +--- + +## Version Information Breakdown + +### Assembly Versions + +**AssemblyVersion:** `11.0.0` +- Binary version for .NET assembly +- Used for strong naming +- Must be numeric only (no text) + +**AssemblyFileVersion:** `11.0.0` +- File version shown in Windows Explorer +- File Properties → Details → File version +- Must be numeric only + +**AssemblyInformationalVersion:** `11.0.0-PostgreSQL-PREVIEW` +- Product version shown in About dialog +- Can contain text (e.g., "PREVIEW", "beta", "rc1") +- Used in logs and UI + +--- + +## Where Version Appears + +### 1. About Dialog / Dashboard + +**Location:** Web UI → Dashboard → About + +**Displays:** +``` +Jellyfin Server +Version: 11.0.0-PostgreSQL PREVIEW +``` + +### 2. File Properties + +**Right-click jellyfin.dll → Properties → Details:** +``` +File version: 11.0.0 +Product version: 11.0.0-PostgreSQL PREVIEW +``` + +### 3. Installer Wizard + +**Windows Installer:** +``` +Jellyfin Server (PostgreSQL Edition) +Version 11.0.0-PostgreSQL PREVIEW + +Setup +``` + +### 4. Add/Remove Programs + +**Windows Settings → Apps:** +``` +Jellyfin Server (PostgreSQL Edition) +Version: 11.0.0-PostgreSQL PREVIEW +Publisher: Your Name +``` + +### 5. Log Files + +**Startup logs:** +``` +[INF] Jellyfin version: 11.0.0-PostgreSQL PREVIEW +[INF] Operating system: Windows 10.0.19045 +[INF] Architecture: X64 +``` + +--- + +## Building with New Version + +### Build Application + +```bash +# Clean and build +dotnet clean +dotnet build --configuration Release + +# Verify version in output +cd lib/Release/net11.0 +dotnet jellyfin.dll --version +# Should show: 11.0.0-PostgreSQL PREVIEW +``` + +### Build Installer + +```powershell +# Use default version (11.0.0-PostgreSQL-PREVIEW) +.\build-installer.ps1 + +# Output: +# installer-output\JellyfinSetup-PostgreSQL-11.0.0-PREVIEW.exe +``` + +Or with custom version: +```powershell +.\build-installer.ps1 -Version "11.0.1-PostgreSQL-RC1" +``` + +--- + +## Version Naming Convention + +### Format: `MAJOR.MINOR.PATCH-SUFFIX` + +**Examples:** +``` +11.0.0-PostgreSQL-PREVIEW ← Current (preview/alpha) +11.0.0-PostgreSQL-RC1 ← Release candidate +11.0.0-PostgreSQL ← Stable release +11.0.1-PostgreSQL ← Bug fix release +11.1.0-PostgreSQL ← Minor feature release +12.0.0-PostgreSQL ← Major release +``` + +### Suffix Guidelines + +**PREVIEW** (Current) +- Early testing version +- May have bugs +- Features being tested +- Breaking changes possible + +**ALPHA** +- Very early version +- Unstable +- For developers only + +**BETA** +- Feature complete +- Testing phase +- Minor bugs expected + +**RC1, RC2, etc.** +- Release candidate +- Nearly stable +- Final testing + +**No suffix** +- Stable release +- Production ready + +--- + +## Updating Version in Future + +### For Next Release + +**File:** `SharedVersion.cs` +```csharp +[assembly: AssemblyVersion("11.0.1")] +[assembly: AssemblyFileVersion("11.0.1")] +[assembly: AssemblyInformationalVersion("11.0.1-PostgreSQL")] +``` + +**File:** `jellyfin-setup.iss` +```ini +AppVersion=11.0.1-PostgreSQL +OutputBaseFilename=JellyfinSetup-PostgreSQL-11.0.1 +``` + +**File:** `build-installer.ps1` +```powershell +[string]$Version = "11.0.1-PostgreSQL" +``` + +### One-Command Update + +Create `update-version.ps1`: +```powershell +param([string]$NewVersion) + +# Update SharedVersion.cs +$sharedVersion = Get-Content "SharedVersion.cs" -Raw +$sharedVersion = $sharedVersion -replace 'AssemblyVersion\("[\d\.]+"\)', "AssemblyVersion(`"$NewVersion`")" +$sharedVersion = $sharedVersion -replace 'AssemblyFileVersion\("[\d\.]+"\)', "AssemblyFileVersion(`"$NewVersion`")" +Set-Content -Path "SharedVersion.cs" -Value $sharedVersion + +# Update build script +# (Similar for other files) +``` + +--- + +## README.md Updates Needed + +### Quick Start Section + +**Update version references:** + +```markdown +## Quick Start + +### Windows Installer +```powershell +# Run JellyfinSetup-PostgreSQL-11.0.0-PREVIEW.exe +# Follow wizard for PostgreSQL setup +``` + +### From Source +```bash +cd pgsql-jellyfin +dotnet build --configuration Release +cd lib/Release/net11.0 +dotnet jellyfin.dll +# Jellyfin 11.0.0-PostgreSQL PREVIEW +``` +``` + +--- + +## Documentation Updates Needed + +### Files to Update + +1. **README.md** + - Update installer filename references + - Update version in quick start + - Update version in installation guide + +2. **INSTALLER_QUICK_START.md** + - Update installer filename + - Update version numbers + +3. **INSTALLER_GUIDE.md** + - Update version references + - Update screenshot references if any + +4. **PR_DESCRIPTION.md** + - Update version numbers + - Mention PREVIEW status + +--- + +## Git Commit + +```bash +git add SharedVersion.cs jellyfin-setup.iss build-installer.ps1 +git commit -m "Update version to 11.0.0-PostgreSQL PREVIEW + +Changes: +- Updated SharedVersion.cs to 11.0.0 +- Added AssemblyInformationalVersion: 11.0.0-PostgreSQL-PREVIEW +- Updated jellyfin-setup.iss AppVersion +- Updated installer output filename +- Updated build-installer.ps1 default version + +Reason: +- Clearly identifies this as PostgreSQL fork +- PREVIEW indicates testing/early release status +- Distinguishes from official Jellyfin releases + +Visibility: +- About dialog shows 11.0.0-PostgreSQL PREVIEW +- Installer shows PREVIEW version +- Add/Remove Programs displays full version +- Log files show PostgreSQL PREVIEW + +Breaking Changes: None +Build Status: ✅ Successful +" +``` + +--- + +## Verification + +### Check Assembly Version + +```powershell +# Build and check +dotnet build --configuration Release +cd lib/Release/net11.0 + +# Check DLL version +$dll = Get-Item "jellyfin.dll" +$version = [System.Diagnostics.FileVersionInfo]::GetVersionInfo($dll.FullName) +Write-Host "File Version: $($version.FileVersion)" +Write-Host "Product Version: $($version.ProductVersion)" + +# Expected output: +# File Version: 11.0.0 +# Product Version: 11.0.0-PostgreSQL PREVIEW +``` + +### Check at Runtime + +```bash +cd lib/Release/net11.0 +dotnet jellyfin.dll --version + +# Should show: +# Jellyfin 11.0.0-PostgreSQL PREVIEW +``` + +### Check Installer + +```powershell +# Build installer +.\build-installer.ps1 + +# Verify output file +Test-Path "installer-output\JellyfinSetup-PostgreSQL-11.0.0-PREVIEW.exe" +# Should return: True + +# Run installer and check version in wizard +``` + +--- + +## Comparison: Official vs. Fork + +### Official Jellyfin +``` +Version: 10.12.0 +Database: SQLite +Platform: Original +``` + +### This Fork (PostgreSQL PREVIEW) +``` +Version: 11.0.0-PostgreSQL PREVIEW +Database: PostgreSQL +Platform: Enterprise +``` + +**Clear differentiation** ✅ + +--- + +## Future Version Roadmap + +### Suggested Path + +**11.0.0-PostgreSQL-PREVIEW** ← Current +- Initial testing +- Early adopters +- Feature development + +**11.0.0-PostgreSQL-RC1** +- Feature complete +- Bug fixes +- Final testing + +**11.0.0-PostgreSQL** +- Stable release +- Production ready +- Official launch + +**11.0.1-PostgreSQL** +- Bug fixes +- Minor improvements + +**11.1.0-PostgreSQL** +- New features +- Minor version bump + +--- + +## Summary + +**Old Version:** 10.12.0 +**New Version:** 11.0.0-PostgreSQL PREVIEW + +**Files Changed:** +1. SharedVersion.cs - Assembly versions +2. jellyfin-setup.iss - Installer version +3. build-installer.ps1 - Build script default + +**Build Status:** ✅ Successful +**Installer:** `JellyfinSetup-PostgreSQL-11.0.0-PREVIEW.exe` +**Display:** "11.0.0-PostgreSQL PREVIEW" everywhere + +✅ **Version update complete!** diff --git a/jellyfin-setup.iss b/jellyfin-setup.iss index e3df7f34..6b8431ae 100644 --- a/jellyfin-setup.iss +++ b/jellyfin-setup.iss @@ -5,7 +5,7 @@ [Setup] ; Basic Application Information AppName=Jellyfin Server (PostgreSQL Edition) -AppVersion=11.0.0 +AppVersion=11.0.0-PostgreSQL-PREVIEW AppPublisher=Your Name AppPublisherURL=https://your-website.com AppSupportURL=https://your-website.com @@ -14,7 +14,7 @@ DefaultDirName={autopf}\Jellyfin-PostgreSQL DefaultGroupName=Jellyfin PostgreSQL AllowNoIcons=yes OutputDir=installer-output -OutputBaseFilename=JellyfinSetup-PostgreSQL-11.0.0 +OutputBaseFilename=JellyfinSetup-PostgreSQL-11.0.0-PREVIEW Compression=lzma2 SolidCompression=yes ArchitecturesAllowed=x64compatible diff --git a/src/Jellyfin.Database/Jellyfin.Database.Implementations/DbConfiguration/DatabaseConfigurationOptions.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/DbConfiguration/DatabaseConfigurationOptions.cs index 436f99b0..339b88b1 100644 --- a/src/Jellyfin.Database/Jellyfin.Database.Implementations/DbConfiguration/DatabaseConfigurationOptions.cs +++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/DbConfiguration/DatabaseConfigurationOptions.cs @@ -17,9 +17,29 @@ public class DatabaseConfigurationOptions /// public DatabaseConfigurationOptions() { - // Default to SQLite if not specified - DatabaseType = "Jellyfin-SQLite"; + // Default to PostgreSQL + DatabaseType = "Jellyfin-PostgreSQL"; LockingBehavior = DatabaseLockingBehaviorTypes.NoLock; + + // Set up default PostgreSQL configuration + CustomProviderOptions = new CustomDatabaseOptions + { + PluginName = "Jellyfin-PostgreSQL", + PluginAssembly = "Jellyfin.Database.Providers.Postgres", + ConnectionString = "Host=localhost;Port=5432;Database=jellyfin;Username=jellyfin;Password=jellyfin" + }; + + // Set up default backup options + BackupOptions = new DatabaseBackupOptions + { + PgDumpPath = "pg_dump", + PgRestorePath = "pg_restore", + BackupFormat = "custom", + IncludeBlobs = true, + CompressionLevel = 6, + TimeoutSeconds = 1800, + VerboseOutput = true + }; } /// diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Postgres/PostgresDatabaseProvider.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Postgres/PostgresDatabaseProvider.cs index 9a00c3bd..86bf9481 100644 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Postgres/PostgresDatabaseProvider.cs +++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Postgres/PostgresDatabaseProvider.cs @@ -34,6 +34,7 @@ public sealed class PostgresDatabaseProvider : IJellyfinDatabaseProvider private readonly IConfigurationManager? configurationManager; private PostgresBackupService? backupService; private string? currentHost; + private DatabaseConfigurationOptions? databaseConfig; /// /// Initializes a new instance of the class. @@ -93,6 +94,9 @@ public sealed class PostgresDatabaseProvider : IJellyfinDatabaseProvider /// public void Initialise(DbContextOptionsBuilder options, DatabaseConfigurationOptions databaseConfiguration) { + // Store the configuration for later use + databaseConfig = databaseConfiguration; + static T? GetOption(ICollection? options, string key, Func converter, Func? defaultValue = null) { if (options is null) @@ -337,6 +341,16 @@ public sealed class PostgresDatabaseProvider : IJellyfinDatabaseProvider { try { + // First ensure the database itself exists + if (databaseConfig is not null) + { + await EnsureDatabaseExistsAsync(databaseConfig, cancellationToken).ConfigureAwait(false); + } + else + { + logger.LogWarning("Database configuration not available. Database existence check skipped."); + } + logger.LogInformation("Checking PostgreSQL database for missing tables..."); var context = await DbContextFactory!.CreateDbContextAsync(cancellationToken).ConfigureAwait(false); diff --git a/startup.json.example b/startup.json.example index 6320a022..6024700a 100644 --- a/startup.json.example +++ b/startup.json.example @@ -20,8 +20,8 @@ "ConfigDir": "/etc/jellyfin", "CacheDir": "/var/cache/jellyfin", "LogDir": "/var/log/jellyfin", - "TempDir": "/var/tmp/jellyfin", - "WebDir": "/usr/share/jellyfin/web" + "TempDir": "/tmp/jellyfin", + "WebDir": "/usr/share/jellyfin/wwwroot" } }, @@ -32,7 +32,7 @@ "CacheDir": "D:\\Cache\\Jellyfin", "LogDir": "C:\\ProgramData\\Jellyfin\\logs", "TempDir": "D:\\Temp\\Jellyfin", - "WebDir": "C:\\Program Files\\Jellyfin\\web" + "WebDir": "C:\\ProgramData\\Jellyfin\\wwwroot" } }, @@ -43,7 +43,7 @@ "CacheDir": "./cache", "LogDir": "./logs", "TempDir": "./temp", - "WebDir": "./web" + "WebDir": "./wwwroot" } },