From aa79f9dbe59b516e67d4c7b142ccbfcc7f1754fa Mon Sep 17 00:00:00 2001 From: Gulum Date: Sat, 6 Jun 2026 07:12:20 +0200 Subject: [PATCH] =?UTF-8?q?Revert=20OPS-1=20Windows-plan=20commits=20(dada?= =?UTF-8?q?3af,=206a37f9e):=20superseded=20by=20TrueNAS=20deployment=20tar?= =?UTF-8?q?get;=20re-landed=20on=20main=20against=20GIT-3=20=E2=80=94=20co?= =?UTF-8?q?ntent=20preserved=20on=20Dwight's=20branch-to-be?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../appsettings.Production.json | 12 -- deploy/README.md | 178 ------------------ deploy/scripts/Backup-GerbilManager.ps1 | 126 ------------- deploy/scripts/Register-AutoStart.ps1 | 63 ------- deploy/scripts/Register-BackupTask.ps1 | 69 ------- deploy/scripts/Restore-GerbilManager.ps1 | 152 --------------- deploy/scripts/Start-GerbilManager.ps1 | 72 ------- deploy/scripts/Stop-GerbilManager.ps1 | 49 ----- 8 files changed, 721 deletions(-) delete mode 100644 GerbilManagerWebAPI/appsettings.Production.json delete mode 100644 deploy/README.md delete mode 100644 deploy/scripts/Backup-GerbilManager.ps1 delete mode 100644 deploy/scripts/Register-AutoStart.ps1 delete mode 100644 deploy/scripts/Register-BackupTask.ps1 delete mode 100644 deploy/scripts/Restore-GerbilManager.ps1 delete mode 100644 deploy/scripts/Start-GerbilManager.ps1 delete mode 100644 deploy/scripts/Stop-GerbilManager.ps1 diff --git a/GerbilManagerWebAPI/appsettings.Production.json b/GerbilManagerWebAPI/appsettings.Production.json deleted file mode 100644 index b811af8..0000000 --- a/GerbilManagerWebAPI/appsettings.Production.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Warning", - "Microsoft.AspNetCore": "Warning", - "Microsoft.EntityFrameworkCore": "Warning" - } - }, - "Photos": { - "RootPath": "C:\\gerbil-data\\photos" - } -} diff --git a/deploy/README.md b/deploy/README.md deleted file mode 100644 index 104f22e..0000000 --- a/deploy/README.md +++ /dev/null @@ -1,178 +0,0 @@ -# GerbilManager — Betriebsanleitung (Ops Guide) - -_Für Julian und seine Frau. Alles Wichtige auf einer Seite._ - ---- - -## Schnellstart - -### Erstmalige Einrichtung (einmalig, als Administrator) - -```powershell -# 1. Autostart bei Windows-Anmeldung registrieren -powershell -ExecutionPolicy Bypass -File deploy\scripts\Register-AutoStart.ps1 - -# 2. Taeliches Backup um 03:00 Uhr registrieren -powershell -ExecutionPolicy Bypass -File deploy\scripts\Register-BackupTask.ps1 -``` - -Danach startet GerbilManager automatisch nach jedem Neustart. Fertig. - ---- - -### App manuell starten / stoppen - -```powershell -# Starten (minimiertes Fenster) -powershell -ExecutionPolicy Bypass -File deploy\scripts\Start-GerbilManager.ps1 - -# Stoppen -powershell -ExecutionPolicy Bypass -File deploy\scripts\Stop-GerbilManager.ps1 -``` - -### App im Browser öffnen - -| Gerät | URL | -|---|---| -| Laptop (lokal) | http://localhost:5173 | -| Handy / anderes Gerät im WLAN | http://192.168.2.124:5173 | - -> Die IP-Adresse (192.168.2.124) ist die aktuelle DHCP-Adresse des Laptops. -> Für eine stabile Adresse → Abschnitt "Feste IP-Adresse" weiter unten. - ---- - -## Datensicherung (Backup) - -Backups werden automatisch täglich um 03:00 Uhr nach `C:\gerbil-data\backups\` gesichert. -Jedes Backup enthält: -- `gerbilmanager_.sql` — kompletter Datenbankdump -- `photos_.zip` — alle Tierfotos - -Die letzten **7 Tage** werden aufbewahrt; ältere Backups werden automatisch gelöscht. - -### Backup manuell ausführen - -```powershell -powershell -ExecutionPolicy Bypass -File deploy\scripts\Backup-GerbilManager.ps1 -``` - -### Backup-Protokoll einsehen - -``` -C:\gerbil-data\backups\backup.log -``` - ---- - -## Wiederherstellung aus Backup - -> **Achtung:** Alle aktuellen Daten werden überschrieben! - -```powershell -# Neuestes Backup wiederherstellen (fragt vorher nach Bestätigung) -powershell -ExecutionPolicy Bypass -File deploy\scripts\Restore-GerbilManager.ps1 - -# Bestimmtes Backup wiederherstellen -powershell -ExecutionPolicy Bypass -File deploy\scripts\Restore-GerbilManager.ps1 ` - -BackupDir "C:\gerbil-data\backups\2026-06-05_03-00" -``` - ---- - -## Feste IP-Adresse (empfohlen) - -Damit das Handy immer dieselbe URL verwendet, sollte dem Laptop eine feste -IP-Adresse im Heimnetzwerk zugewiesen werden. - -### Option A: DHCP-Reservierung im Router (empfohlen) - -1. Router-Oberfläche öffnen (meist `http://192.168.2.1` oder `http://fritz.box`) -2. **Heimnetz → Netzwerk → IP-Adressen** (bei FRITZ!Box) -3. Den Eintrag für diesen Laptop suchen (Name: `GULUM-...` oder ähnlich) -4. **"Immer dieselbe IPv4-Adresse zuweisen"** aktivieren -5. Speichern. Ab sofort hat der Laptop immer 192.168.2.124. - -### Option B: Statische IP direkt am Laptop setzen - -```powershell -# Netzwerkadaptername ermitteln -Get-NetAdapter - -# Feste IP setzen (Beispiel fuer WLAN-Adapter "Wi-Fi") -New-NetIPAddress -InterfaceAlias "Wi-Fi" -IPAddress 192.168.2.124 -PrefixLength 24 -DefaultGateway 192.168.2.1 -Set-DnsClientServerAddress -InterfaceAlias "Wi-Fi" -ServerAddresses 192.168.2.1 -``` - ---- - -## Firewall-Regel (für Handy-Zugriff) - -Damit das Handy auf die App zugreifen kann, muss eine Firewall-Ausnahme eingerichtet sein. -Das WLAN "Katzastrophe 4" ist als **Public** eingestuft, daher ist der Befehl nötig: - -```powershell -# Als Administrator ausführen: -New-NetFirewallRule ` - -DisplayName "GerbilManager (Frontend + API)" ` - -Direction Inbound ` - -Action Allow ` - -Protocol TCP ` - -LocalPort 5173,5179 ` - -Profile Any -``` - -> **Einmalig nötig.** Prüfen ob die Regel bereits existiert: -> `Get-NetFirewallRule -DisplayName "GerbilManager*"` - ---- - -## Datenspeicherorte - -| Was | Pfad | -|---|---| -| Tierfotos | `C:\gerbil-data\photos\` | -| Datenbank | Docker-Volume (automatisch, Aspire-verwaltet) | -| Backups | `C:\gerbil-data\backups\` | -| App-Quellcode | `C:\Users\gulum\dev\GerbilManager\` | - ---- - -## Voraussetzungen (für Betrieb) - -| Software | Mindestversion | Status prüfen | -|---|---|---| -| Docker Desktop | Aktuell, läuft | `docker ps` | -| .NET SDK | 10.0+ | `dotnet --version` | -| Node.js | 18+ | `node --version` | - -Docker Desktop muss beim Windows-Start automatisch starten. -Einstellung: Docker Desktop → Settings → **Start Docker Desktop when you sign in**. - ---- - -## Problemlösung - -| Problem | Lösung | -|---|---| -| Seite lädt nicht | Prüfen ob Docker läuft: `docker ps`. Dann `Start-GerbilManager.ps1` | -| Handy erreicht App nicht | Firewall-Regel prüfen (oben). Beide Geräte im selben WLAN? | -| Daten verschwunden | Wiederherstellung: `Restore-GerbilManager.ps1` | -| Datenbank-Fehler beim Start | `docker ps` → Postgres-Container läuft? Sonst neu starten | -| Port belegt (Fehler 5179/5173) | `netstat -ano \| findstr ":5179"` → Prozess beenden | - ---- - -## Backup testen (einmalig empfohlen) - -```powershell -# 1. Backup erstellen -powershell -ExecutionPolicy Bypass -File deploy\scripts\Backup-GerbilManager.ps1 - -# 2. Prüfen ob Backup vorhanden -Get-ChildItem "C:\gerbil-data\backups\" -Directory | Select-Object -Last 3 - -# 3. Inhalt des neuesten Backups prüfen -$latest = (Get-ChildItem "C:\gerbil-data\backups\" -Directory | Sort-Object LastWriteTime -Desc | Select-Object -First 1).FullName -Get-ChildItem $latest -``` diff --git a/deploy/scripts/Backup-GerbilManager.ps1 b/deploy/scripts/Backup-GerbilManager.ps1 deleted file mode 100644 index b2ea173..0000000 --- a/deploy/scripts/Backup-GerbilManager.ps1 +++ /dev/null @@ -1,126 +0,0 @@ -<# -.SYNOPSIS - Sichert die GerbilManager-Datenbank (pg_dump) und den Fotoordner. - -.DESCRIPTION - 1. Findet den laufenden Aspire-Postgres-Docker-Container. - 2. Fuehrt pg_dump aus und speichert das SQL-Dump in C:\gerbil-data\backups\. - 3. Kopiert den Fotoordner als ZIP ins Backup-Verzeichnis. - 4. Rotiert alte Backups: behaelt die letzten $KeepDays Tage. - -.PARAMETER BackupRoot - Pfad zum Backup-Verzeichnis. Standard: C:\gerbil-data\backups - -.PARAMETER PhotosRoot - Pfad zum Fotoordner. Standard: C:\gerbil-data\photos - -.PARAMETER KeepDays - Anzahl der Tage, die Backups aufbewahrt werden. Standard: 7 - -.EXAMPLE - .\Backup-GerbilManager.ps1 - .\Backup-GerbilManager.ps1 -KeepDays 14 -BackupRoot D:\Sicherungen -#> -param( - [string]$BackupRoot = "C:\gerbil-data\backups", - [string]$PhotosRoot = "C:\gerbil-data\photos", - [int]$KeepDays = 7 -) - -Set-StrictMode -Version Latest -$ErrorActionPreference = "Stop" - -$timestamp = Get-Date -Format "yyyy-MM-dd_HH-mm" -$backupDir = Join-Path $BackupRoot $timestamp -$logFile = Join-Path $BackupRoot "backup.log" -$dbDumpFile = Join-Path $backupDir "gerbilmanager_$timestamp.sql" -$photoZip = Join-Path $backupDir "photos_$timestamp.zip" - -function Log([string]$msg) { - $line = "[$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')] $msg" - Write-Host $line - Add-Content -Path $logFile -Value $line -Encoding UTF8 -} - -# --- Voraussetzungen pruefen --- -if (-not (Get-Command "docker" -ErrorAction SilentlyContinue)) { - Log "FEHLER: Docker nicht gefunden. Backup abgebrochen." - exit 1 -} - -# --- Backup-Verzeichnis anlegen --- -New-Item -ItemType Directory -Force -Path $backupDir | Out-Null -Log "Backup-Verzeichnis: $backupDir" - -# --- Postgres-Container finden --- -Log "Suche Postgres-Container..." -$containers = docker ps --format "{{.Names}}" 2>&1 -$pgContainer = $containers -split "`n" | Where-Object { $_ -match "postgres" } | Select-Object -First 1 - -if (-not $pgContainer) { - Log "FEHLER: Kein laufender Postgres-Container gefunden. Ist GerbilManager gestartet?" - exit 1 -} -$pgContainer = $pgContainer.Trim() -Log "Gefundener Container: $pgContainer" - -# Aspire setzt scram-sha-256 Auth - Passwort aus Container-Env lesen -$pgPassword = (docker inspect $pgContainer --format "{{range .Config.Env}}{{println .}}{{end}}" 2>&1) -split "`n" | - Where-Object { $_ -match "^POSTGRES_PASSWORD=" } | - ForEach-Object { $_ -replace "^POSTGRES_PASSWORD=", "" } | - Select-Object -First 1 -if (-not $pgPassword) { - Log "FEHLER: POSTGRES_PASSWORD nicht im Container gefunden." - exit 1 -} - -# --- Datenbank-Dump --- -Log "Starte pg_dump fuer Datenbank 'gerbilmanager'..." -try { - docker exec -e "PGPASSWORD=$pgPassword" $pgContainer ` - pg_dump --clean --if-exists --format=plain --username=postgres gerbilmanager ` - | Out-File -FilePath $dbDumpFile -Encoding UTF8 - - $dumpSize = [math]::Round((Get-Item $dbDumpFile).Length / 1KB, 1) - Log "Datenbank-Dump erstellt: $dbDumpFile ($dumpSize KB)" -} catch { - Log "FEHLER beim Datenbank-Dump: $_" - exit 1 -} - -# Dump-Validierung: muss mindestens 'CREATE TABLE' enthalten -$dumpContent = Get-Content $dbDumpFile -Raw -ErrorAction SilentlyContinue -if ($dumpContent -notlike "*CREATE TABLE*" -and $dumpContent -notlike "*PostgreSQL*") { - Log "WARNUNG: Dump-Datei sieht ungueltig aus - pruefen Sie $dbDumpFile manuell." -} - -# --- Fotos sichern --- -if (Test-Path $PhotosRoot) { - $photoCount = (Get-ChildItem $PhotosRoot -File -ErrorAction SilentlyContinue).Count - if ($photoCount -gt 0) { - Log "Komprimiere $photoCount Fotos nach $photoZip..." - try { - Compress-Archive -Path "$PhotosRoot\*" -DestinationPath $photoZip -Force - $zipSize = [math]::Round((Get-Item $photoZip).Length / 1MB, 1) - Log "Foto-Archiv erstellt: $photoZip ($zipSize MB)" - } catch { - Log "WARNUNG: Foto-Backup fehlgeschlagen: $_" - } - } else { - Log "Kein Fotoordner oder keine Fotos vorhanden - Foto-Backup uebersprungen." - } -} else { - Log "Fotoordner nicht gefunden ($PhotosRoot) - Foto-Backup uebersprungen." -} - -# --- Rotation: alte Backups loeschen --- -Log "Rotiere Backups (behalte letzte $KeepDays Tage)..." -$cutoff = (Get-Date).AddDays(-$KeepDays) -$oldBackups = Get-ChildItem -Path $BackupRoot -Directory | - Where-Object { $_.LastWriteTime -lt $cutoff } -foreach ($old in $oldBackups) { - Log "Loesche altes Backup: $($old.FullName)" - Remove-Item $old.FullName -Recurse -Force -} -$remaining = @(Get-ChildItem -Path $BackupRoot -Directory).Count -Log "Backup abgeschlossen. Vorhandene Backups: $remaining" diff --git a/deploy/scripts/Register-AutoStart.ps1 b/deploy/scripts/Register-AutoStart.ps1 deleted file mode 100644 index ed564c8..0000000 --- a/deploy/scripts/Register-AutoStart.ps1 +++ /dev/null @@ -1,63 +0,0 @@ -<# -.SYNOPSIS - Registriert GerbilManager als Windows-Autostart (geplante Aufgabe bei Benutzeranmeldung). - -.DESCRIPTION - Erstellt eine geplante Aufgabe, die Start-GerbilManager.ps1 automatisch startet, - wenn sich der aktuelle Benutzer anmeldet. Erfordert Administratorrechte. - -.NOTES - Erfordert: PowerShell als Administrator ausfuehren - Aufgabenname: GerbilManager AutoStart -#> -#Requires -RunAsAdministrator -Set-StrictMode -Version Latest -$ErrorActionPreference = "Stop" - -$taskName = "GerbilManager AutoStart" -$scriptPath = Join-Path $PSScriptRoot "Start-GerbilManager.ps1" -$projectRoot = Resolve-Path (Join-Path $PSScriptRoot "..\..") - -if (-not (Test-Path $scriptPath)) { - Write-Error "Startskript nicht gefunden: $scriptPath" - exit 1 -} - -Write-Host "Registriere geplante Aufgabe '$taskName'..." - -$action = New-ScheduledTaskAction ` - -Execute "powershell.exe" ` - -Argument "-NonInteractive -WindowStyle Hidden -ExecutionPolicy Bypass -File `"$scriptPath`"" ` - -WorkingDirectory $projectRoot - -$trigger = New-ScheduledTaskTrigger -AtLogOn -User $env:USERNAME - -$settings = New-ScheduledTaskSettingsSet ` - -ExecutionTimeLimit (New-TimeSpan -Hours 0) ` - -RestartCount 3 ` - -RestartInterval (New-TimeSpan -Minutes 2) ` - -StartWhenAvailable ` - -MultipleInstances IgnoreNew - -$principal = New-ScheduledTaskPrincipal ` - -UserId $env:USERNAME ` - -LogonType Interactive ` - -RunLevel Highest - -# Vorhandene Aufgabe entfernen, falls noetig -Unregister-ScheduledTask -TaskName $taskName -Confirm:$false -ErrorAction SilentlyContinue - -Register-ScheduledTask ` - -TaskName $taskName ` - -Action $action ` - -Trigger $trigger ` - -Settings $settings ` - -Principal $principal ` - -Description "Startet GerbilManager (Rennmaus-Verwaltung) automatisch bei der Benutzeranmeldung." ` - -Force | Out-Null - -Write-Host "Aufgabe registriert: '$taskName'" -Write-Host "GerbilManager startet ab sofort automatisch beim Anmelden." -Write-Host "" -Write-Host "Aufgabe pruefen : Get-ScheduledTask -TaskName '$taskName'" -Write-Host "Aufgabe entfernen: Unregister-ScheduledTask -TaskName '$taskName' -Confirm:`$false" diff --git a/deploy/scripts/Register-BackupTask.ps1 b/deploy/scripts/Register-BackupTask.ps1 deleted file mode 100644 index a450841..0000000 --- a/deploy/scripts/Register-BackupTask.ps1 +++ /dev/null @@ -1,69 +0,0 @@ -<# -.SYNOPSIS - Registriert den GerbilManager-Backup als taegliche geplante Aufgabe (03:00 Uhr). - -.DESCRIPTION - Erstellt eine geplante Aufgabe, die Backup-GerbilManager.ps1 taeglich um 03:00 Uhr - ausfuehrt. Backups werden 7 Tage lang aufbewahrt. - -.PARAMETER BackupTime - Uhrzeit fuer das taeliche Backup. Standard: 03:00 - -.NOTES - Erfordert: PowerShell als Administrator ausfuehren - Aufgabenname: GerbilManager Backup -#> -#Requires -RunAsAdministrator -param( - [string]$BackupTime = "03:00" -) -Set-StrictMode -Version Latest -$ErrorActionPreference = "Stop" - -$taskName = "GerbilManager Backup" -$scriptPath = Join-Path $PSScriptRoot "Backup-GerbilManager.ps1" -$logPath = "C:\gerbil-data\backups\backup.log" - -if (-not (Test-Path $scriptPath)) { - Write-Error "Backup-Skript nicht gefunden: $scriptPath" - exit 1 -} - -# Backup-Verzeichnis vorab anlegen -New-Item -ItemType Directory -Force -Path "C:\gerbil-data\backups" | Out-Null - -Write-Host "Registriere Backup-Aufgabe '$taskName' (taeglich $BackupTime)..." - -$action = New-ScheduledTaskAction ` - -Execute "powershell.exe" ` - -Argument "-NonInteractive -WindowStyle Hidden -ExecutionPolicy Bypass -File `"$scriptPath`" >> `"$logPath`" 2>&1" - -$trigger = New-ScheduledTaskTrigger -Daily -At $BackupTime - -$settings = New-ScheduledTaskSettingsSet ` - -ExecutionTimeLimit (New-TimeSpan -Hours 1) ` - -StartWhenAvailable ` - -WakeToRun ` - -MultipleInstances IgnoreNew - -$principal = New-ScheduledTaskPrincipal ` - -UserId $env:USERNAME ` - -LogonType Interactive ` - -RunLevel Highest - -Unregister-ScheduledTask -TaskName $taskName -Confirm:$false -ErrorAction SilentlyContinue - -Register-ScheduledTask ` - -TaskName $taskName ` - -Action $action ` - -Trigger $trigger ` - -Settings $settings ` - -Principal $principal ` - -Description "Taegiches Backup der GerbilManager-Datenbank und Fotos um $BackupTime Uhr." ` - -Force | Out-Null - -Write-Host "Backup-Aufgabe registriert: '$taskName'" -Write-Host "Backups werden taeglich um $BackupTime Uhr nach C:\gerbil-data\backups\ gesichert." -Write-Host "Protokoll: $logPath" -Write-Host "" -Write-Host "Backup jetzt testen: & `"$scriptPath`"" diff --git a/deploy/scripts/Restore-GerbilManager.ps1 b/deploy/scripts/Restore-GerbilManager.ps1 deleted file mode 100644 index 9e96bbb..0000000 --- a/deploy/scripts/Restore-GerbilManager.ps1 +++ /dev/null @@ -1,152 +0,0 @@ -<# -.SYNOPSIS - Stellt GerbilManager aus einem Backup wieder her. - -.DESCRIPTION - WARNUNG: Ueberschreibt alle aktuellen Datenbankdaten und Fotos! - - 1. Stoppt GerbilManager (falls laufend). - 2. Stellt die Datenbank aus dem pg_dump-SQL-File wieder her. - 3. Entpackt das Foto-Archiv. - 4. Startet GerbilManager neu. - -.PARAMETER BackupDir - Pfad zum Backup-Unterverzeichnis (z.B. C:\gerbil-data\backups\2026-06-06_03-00). - Wenn nicht angegeben, wird das neueste verfuegbare Backup verwendet. - -.PARAMETER PhotosRoot - Pfad zum Fotoordner. Standard: C:\gerbil-data\photos - -.PARAMETER NoRestart - GerbilManager nach der Wiederherstellung NICHT neu starten. - -.EXAMPLE - # Neuestes Backup wiederherstellen - .\Restore-GerbilManager.ps1 - - # Bestimmtes Backup wiederherstellen - .\Restore-GerbilManager.ps1 -BackupDir "C:\gerbil-data\backups\2026-06-05_03-00" -#> -param( - [string]$BackupDir = "", - [string]$PhotosRoot = "C:\gerbil-data\photos", - [switch]$NoRestart -) - -Set-StrictMode -Version Latest -$ErrorActionPreference = "Stop" - -$backupRoot = "C:\gerbil-data\backups" - -function Log([string]$msg) { - Write-Host "[$(Get-Date -Format 'HH:mm:ss')] $msg" -} - -# --- Backup-Verzeichnis bestimmen --- -if ($BackupDir -eq "") { - $latest = Get-ChildItem -Path $backupRoot -Directory | - Sort-Object LastWriteTime -Descending | - Select-Object -First 1 - if (-not $latest) { - Log "FEHLER: Kein Backup gefunden in $backupRoot" - exit 1 - } - $BackupDir = $latest.FullName -} - -if (-not (Test-Path $BackupDir)) { - Log "FEHLER: Backup-Verzeichnis nicht gefunden: $BackupDir" - exit 1 -} - -# --- Dateien im Backup suchen --- -$sqlFile = Get-ChildItem -Path $BackupDir -Filter "*.sql" | Select-Object -First 1 -$zipFile = Get-ChildItem -Path $BackupDir -Filter "*.zip" | Select-Object -First 1 - -if (-not $sqlFile) { - Log "FEHLER: Kein SQL-Dump (.sql) in $BackupDir gefunden." - exit 1 -} - -Log "Wiederherstellung aus: $BackupDir" -Log " Datenbank: $($sqlFile.Name)" -if ($zipFile) { Log " Fotos : $($zipFile.Name)" } - -# --- Bestaetigung --- -Write-Host "" -Write-Host "WARNUNG: Alle aktuellen Datenbankdaten und Fotos werden UNWIDERRUFLICH ueberschrieben!" -ForegroundColor Red -$confirm = Read-Host "Fortfahren? (ja/nein)" -if ($confirm -ne "ja") { - Log "Abgebrochen." - exit 0 -} - -# --- GerbilManager stoppen (falls laufend) --- -$stopScript = Join-Path $PSScriptRoot "Stop-GerbilManager.ps1" -if (Test-Path $stopScript) { - Log "Stoppe GerbilManager..." - & $stopScript - Start-Sleep -Seconds 3 -} - -# --- Postgres-Container finden --- -Log "Suche Postgres-Container..." -$containers = docker ps --format "{{.Names}}" 2>&1 -$pgContainer = $containers -split "`n" | Where-Object { $_ -match "postgres" } | Select-Object -First 1 -if (-not $pgContainer) { - # Container koennte gestoppt sein - starten wir ihn kurz - Log "Postgres-Container laeuft nicht. Starte ihn zunaechst..." - Log "Bitte starten Sie GerbilManager kurz einmal (Start-GerbilManager.ps1) und versuchen Sie es erneut." - exit 1 -} -$pgContainer = $pgContainer.Trim() -Log "Container: $pgContainer" - -# Aspire setzt scram-sha-256 Auth - Passwort aus Container-Env lesen -$pgPassword = (docker inspect $pgContainer --format "{{range .Config.Env}}{{println .}}{{end}}" 2>&1) -split "`n" | - Where-Object { $_ -match "^POSTGRES_PASSWORD=" } | - ForEach-Object { $_ -replace "^POSTGRES_PASSWORD=", "" } | - Select-Object -First 1 -if (-not $pgPassword) { - Log "FEHLER: POSTGRES_PASSWORD nicht im Container gefunden." - exit 1 -} - -# --- Datenbankwiederherstellung --- -Log "Stelle Datenbank wieder her aus $($sqlFile.Name)..." - -# Verbindungen trennen -docker exec -e "PGPASSWORD=$pgPassword" $pgContainer psql -U postgres -c ` - "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = 'gerbilmanager' AND pid <> pg_backend_pid();" | Out-Null - -# SQL-Dump einspielen (--clean im Dump macht DROP TABLE IF EXISTS vor CREATE) -Get-Content $sqlFile.FullName -Raw | docker exec -i -e "PGPASSWORD=$pgPassword" $pgContainer psql -U postgres gerbilmanager -if ($LASTEXITCODE -ne 0) { - Log "FEHLER: Datenbankwiederherstellung fehlgeschlagen (exit $LASTEXITCODE)." - exit 1 -} -Log "Datenbankwiederherstellung erfolgreich." - -# --- Fotos wiederherstellen --- -if ($zipFile) { - Log "Stelle Fotos wieder her..." - if (Test-Path $PhotosRoot) { - Remove-Item "$PhotosRoot\*" -Recurse -Force -ErrorAction SilentlyContinue - } else { - New-Item -ItemType Directory -Force -Path $PhotosRoot | Out-Null - } - Expand-Archive -Path $zipFile.FullName -DestinationPath $PhotosRoot -Force - $count = (Get-ChildItem $PhotosRoot -File).Count - Log "Fotos wiederhergestellt: $count Dateien." -} - -# --- GerbilManager neu starten --- -if (-not $NoRestart) { - $startScript = Join-Path $PSScriptRoot "Start-GerbilManager.ps1" - if (Test-Path $startScript) { - Log "Starte GerbilManager neu..." - & $startScript - } -} - -Log "Wiederherstellung abgeschlossen." diff --git a/deploy/scripts/Start-GerbilManager.ps1 b/deploy/scripts/Start-GerbilManager.ps1 deleted file mode 100644 index 6389694..0000000 --- a/deploy/scripts/Start-GerbilManager.ps1 +++ /dev/null @@ -1,72 +0,0 @@ -<# -.SYNOPSIS - Startet GerbilManager im Produktionsmodus (API + Datenbank + Frontend). - -.DESCRIPTION - Setzt die Produktionsumgebung, legt Datenverzeichnisse an und startet den - Aspire AppHost im Hintergrund. Der Prozess laeuft als minimiertes Fenster. - Der Pfad zum AppHost wird relativ zu diesem Skript aufgeloest. - -.NOTES - Erfordert: .NET SDK 10+, Docker Desktop (running), Node.js 18+ - Startet auf: http://:5173 (Frontend), http://:5179 (API) -#> -param( - [switch]$Wait # Blockiert bis Ctrl+C wenn gesetzt (fuer manuelle Starts) -) - -Set-StrictMode -Version Latest -$ErrorActionPreference = "Stop" - -$projectRoot = Resolve-Path (Join-Path $PSScriptRoot "..\..") - -# --- Datenverzeichnisse sicherstellen --- -$dataRoot = "C:\gerbil-data" -$photosDir = "$dataRoot\photos" -$backupsDir = "$dataRoot\backups" - -foreach ($dir in @($photosDir, $backupsDir)) { - if (-not (Test-Path $dir)) { - New-Item -ItemType Directory -Force -Path $dir | Out-Null - Write-Host "Verzeichnis angelegt: $dir" - } -} - -# --- Produktionsumgebung setzen --- -$env:ASPNETCORE_ENVIRONMENT = "Production" -$env:DOTNET_ENVIRONMENT = "Production" - -# Aspire Dashboard-Browser nicht automatisch oeffnen -$env:DOTNET_LAUNCH_BROWSER = "false" -# Kein Aspire Dashboard im Produktionsbetrieb (Dashboard-Port auf 0 → kein Start) -# Entfernen Sie die naechste Zeile, wenn Sie das Dashboard behalten moechten. -$env:ASPIRE_ALLOW_UNSECURED_TRANSPORT = "true" - -# --- AppHost starten --- -$appHostProject = Join-Path $projectRoot "GerbilManager.AppHost" - -Write-Host "Starte GerbilManager..." -Write-Host " Projekt : $appHostProject" -Write-Host " Umgebung: $($env:ASPNETCORE_ENVIRONMENT)" -Write-Host " Fotos : $photosDir" -Write-Host "" - -if ($Wait) { - # Interaktiver Modus: blockiert bis Ctrl+C - dotnet run --project $appHostProject --no-launch-profile -} else { - # Hintergrundmodus: startet minimiertes Fenster - $pidFile = Join-Path $PSScriptRoot "..\gerbilmanager.pid" - $proc = Start-Process "cmd.exe" ` - -ArgumentList "/c", "dotnet run --project `"$appHostProject`" --no-launch-profile" ` - -WorkingDirectory $projectRoot ` - -WindowStyle Minimized ` - -PassThru - $proc.Id | Out-File -FilePath $pidFile -Encoding UTF8 -Force - Write-Host "GerbilManager gestartet (PID $($proc.Id))." - Write-Host "Frontend : http://localhost:5173" - Write-Host "API : http://localhost:5179" - Write-Host "PID-Datei: $pidFile" - Write-Host "" - Write-Host "Zum Beenden: deploy\scripts\Stop-GerbilManager.ps1" -} diff --git a/deploy/scripts/Stop-GerbilManager.ps1 b/deploy/scripts/Stop-GerbilManager.ps1 deleted file mode 100644 index d3ce2e7..0000000 --- a/deploy/scripts/Stop-GerbilManager.ps1 +++ /dev/null @@ -1,49 +0,0 @@ -<# -.SYNOPSIS - Stoppt alle laufenden GerbilManager-Prozesse (AppHost + Kindprozesse). - -.NOTES - Beendet dotnet-AppHost-Prozesse und wartet darauf, dass Docker-Container - von Aspire selbst heruntergefahren werden. -#> -Set-StrictMode -Version Latest -$ErrorActionPreference = "SilentlyContinue" - -$pidFile = Join-Path $PSScriptRoot "..\gerbilmanager.pid" - -# Ueber gespeicherte PID stoppen (wenn vorhanden) -if (Test-Path $pidFile) { - $savedPid = Get-Content $pidFile -Raw | ForEach-Object { $_.Trim() } - $proc = Get-Process -Id $savedPid -ErrorAction SilentlyContinue - if ($proc) { - Write-Host "Beende Prozess PID $savedPid ($($proc.Name))..." - Stop-Process -Id $savedPid -Force - Remove-Item $pidFile -Force - } -} - -# Alle dotnet-Prozesse stoppen, die den AppHost als Elternprozess haben -$appHostProcs = Get-Process -Name "dotnet" -ErrorAction SilentlyContinue | - Where-Object { $_.MainModule.FileName -like "*dotnet*" } -foreach ($p in $appHostProcs) { - $cmdLine = (Get-CimInstance Win32_Process -Filter "ProcessId = $($p.Id)").CommandLine - if ($cmdLine -like "*GerbilManager.AppHost*") { - Write-Host "Beende dotnet-AppHost (PID $($p.Id))..." - Stop-Process -Id $p.Id -Force - } -} - -# Vite-Dev-Server stoppen (node-Prozess auf Port 5173) -$nodePids = (netstat -ano | Select-String ":5173").ToString() -split "\s+" | - Where-Object { $_ -match "^\d+$" } | Select-Object -Unique -foreach ($nPid in $nodePids) { - $np = Get-Process -Id $nPid -ErrorAction SilentlyContinue - if ($np -and $np.Name -in @("node", "npm")) { - Write-Host "Beende Vite-Dev-Server (PID $nPid)..." - Stop-Process -Id $nPid -Force - } -} - -Write-Host "GerbilManager wurde gestoppt." -Write-Host "Hinweis: Der Postgres-Docker-Container laeuft weiterhin (Aspire managed ihn)." -Write-Host " Zum Stoppen: docker stop $(docker ps --filter 'name=postgres' --format '{{.Names}}' 2>$null)"