Revert OPS-1 Windows-plan commits (dada3af, 6a37f9e): superseded by TrueNAS deployment target; re-landed on main against GIT-3 — content preserved on Dwight's branch-to-be

This commit is contained in:
2026-06-06 07:12:20 +02:00
parent 3b3497079b
commit aa79f9dbe5
8 changed files with 0 additions and 721 deletions

View File

@@ -1,12 +0,0 @@
{
"Logging": {
"LogLevel": {
"Default": "Warning",
"Microsoft.AspNetCore": "Warning",
"Microsoft.EntityFrameworkCore": "Warning"
}
},
"Photos": {
"RootPath": "C:\\gerbil-data\\photos"
}
}

View File

@@ -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_<datum>.sql` — kompletter Datenbankdump
- `photos_<datum>.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
```

View File

@@ -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"

View File

@@ -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"

View File

@@ -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`""

View File

@@ -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."

View File

@@ -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://<LAN-IP>:5173 (Frontend), http://<LAN-IP>: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"
}

View File

@@ -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)"