OPS-1: startup scripts, autostart task, backup task, ops README, production config
- appsettings.Production.json: Photos:RootPath -> C:\gerbil-data\photos so photo files land on a stable host path when ASPNETCORE_ENVIRONMENT=Production - Start-GerbilManager.ps1: creates data dirs, sets Production env, launches AppHost minimised; saves PID for Stop script - Stop-GerbilManager.ps1: kills AppHost + Vite node processes by PID / port - Register-AutoStart.ps1: Windows Scheduled Task on user logon (RunLevel Highest) - Register-BackupTask.ps1: daily 03:00 Scheduled Task for Backup script - deploy/README.md: Julian ops guide — start/stop commands, phone URL, DHCP reservation, firewall rule (Public-profile Wi-Fi), backup/restore procedures, prerequisites checklist, troubleshooting table (German) Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
63
deploy/scripts/Register-AutoStart.ps1
Normal file
63
deploy/scripts/Register-AutoStart.ps1
Normal file
@@ -0,0 +1,63 @@
|
||||
<#
|
||||
.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"
|
||||
69
deploy/scripts/Register-BackupTask.ps1
Normal file
69
deploy/scripts/Register-BackupTask.ps1
Normal file
@@ -0,0 +1,69 @@
|
||||
<#
|
||||
.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`""
|
||||
72
deploy/scripts/Start-GerbilManager.ps1
Normal file
72
deploy/scripts/Start-GerbilManager.ps1
Normal file
@@ -0,0 +1,72 @@
|
||||
<#
|
||||
.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"
|
||||
}
|
||||
49
deploy/scripts/Stop-GerbilManager.ps1
Normal file
49
deploy/scripts/Stop-GerbilManager.ps1
Normal file
@@ -0,0 +1,49 @@
|
||||
<#
|
||||
.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)"
|
||||
Reference in New Issue
Block a user