Includes homelab deploy tooling, image position/zoom manifest persistence, and full trading/casino stack. Co-authored-by: Cursor <cursoragent@cursor.com>
131 lines
4.2 KiB
PowerShell
131 lines
4.2 KiB
PowerShell
# Gemeinsame Homelab-Hilfen (credentials + Posh-SSH)
|
|
function Read-HomelabKeyValueFile {
|
|
param([string]$Path)
|
|
$map = @{}
|
|
if (-not (Test-Path $Path)) { return $map }
|
|
Get-Content $Path | ForEach-Object {
|
|
$line = $_.Trim()
|
|
if ($line -eq "" -or $line.StartsWith("#")) { return }
|
|
if ($line -match '^([^=]+)=(.*)$') {
|
|
$map[$Matches[1].Trim()] = $Matches[2].Trim()
|
|
}
|
|
}
|
|
return $map
|
|
}
|
|
|
|
function Ensure-PoshSshModule {
|
|
if (-not (Get-Module -ListAvailable -Name Posh-SSH)) {
|
|
Install-Module -Name Posh-SSH -Scope CurrentUser -Force -AllowClobber
|
|
}
|
|
Import-Module Posh-SSH -ErrorAction Stop
|
|
}
|
|
|
|
function Get-HomelabConfig {
|
|
$deployDir = $PSScriptRoot
|
|
$credFile = Join-Path $deployDir "homelab.credentials"
|
|
if (-not (Test-Path $credFile)) {
|
|
throw "deploy/homelab.credentials fehlt."
|
|
}
|
|
|
|
$cred = Read-HomelabKeyValueFile $credFile
|
|
$envFile = Read-HomelabKeyValueFile (Join-Path $deployDir "env.homelab")
|
|
|
|
$hostName = $cred["HOMELAB_HOST"]
|
|
$user = $cred["HOMELAB_USER"]
|
|
$password = $cred["HOMELAB_PASSWORD"]
|
|
$sudoPassword = if ($cred["HOMELAB_SUDO_PASSWORD"]) { $cred["HOMELAB_SUDO_PASSWORD"] } else { $password }
|
|
|
|
if ([string]::IsNullOrWhiteSpace($hostName)) { $hostName = "192.168.178.49" }
|
|
if ([string]::IsNullOrWhiteSpace($user)) { $user = "gizzler" }
|
|
if ([string]::IsNullOrWhiteSpace($password)) {
|
|
throw "HOMELAB_PASSWORD in deploy/homelab.credentials ist leer."
|
|
}
|
|
|
|
$appDir = if ($cred["HOMELAB_APP_DIR"]) { $cred["HOMELAB_APP_DIR"] }
|
|
elseif ($envFile["APP_DIR"]) { $envFile["APP_DIR"] }
|
|
else { "/home/gizzler/bestewebsite/bestewebsite" }
|
|
|
|
$sec = ConvertTo-SecureString $password -AsPlainText -Force
|
|
$psCred = New-Object System.Management.Automation.PSCredential ($user, $sec)
|
|
|
|
return [PSCustomObject]@{
|
|
HostName = $hostName
|
|
User = $user
|
|
Password = $password
|
|
SudoPassword = $sudoPassword
|
|
AppDir = $appDir
|
|
Credential = $psCred
|
|
SshTarget = "${user}@${hostName}"
|
|
}
|
|
}
|
|
|
|
function Resolve-HomelabIPv4 {
|
|
param([string]$HostName)
|
|
if ($HostName -match '^\d+\.\d+\.\d+\.\d+$') { return $HostName }
|
|
try {
|
|
$v4 = [System.Net.Dns]::GetHostAddresses($HostName) |
|
|
Where-Object { $_.AddressFamily -eq [System.Net.Sockets.AddressFamily]::InterNetwork } |
|
|
Select-Object -First 1
|
|
if ($v4) { return $v4.ToString() }
|
|
} catch { }
|
|
return $HostName
|
|
}
|
|
|
|
function New-HomelabSession {
|
|
param($Config)
|
|
Ensure-PoshSshModule
|
|
$target = Resolve-HomelabIPv4 $Config.HostName
|
|
$session = New-SSHSession -ComputerName $target -Credential $Config.Credential -AcceptKey -ConnectionTimeout 30
|
|
if (-not $session) { throw "SSH-Verbindung zu $($Config.User)@${target} fehlgeschlagen." }
|
|
return $session
|
|
}
|
|
|
|
function Invoke-HomelabRemote {
|
|
param(
|
|
$Config,
|
|
[string]$Command,
|
|
[switch]$Sudo,
|
|
[string]$WorkDir = "",
|
|
[int]$TimeoutSeconds = 120
|
|
)
|
|
if ([string]::IsNullOrWhiteSpace($WorkDir)) { $WorkDir = $Config.AppDir }
|
|
|
|
$remoteCmd = $Command
|
|
if ($Sudo) {
|
|
$inner = if ($WorkDir) { "cd '$WorkDir' && $Command" } else { $Command }
|
|
$escaped = $inner.Replace("'", "'\''")
|
|
$remoteCmd = "echo '$($Config.SudoPassword)' | sudo -S bash -lc '$escaped'"
|
|
} elseif ($WorkDir) {
|
|
$remoteCmd = "cd '$WorkDir' && $Command"
|
|
}
|
|
|
|
$session = New-HomelabSession $Config
|
|
try {
|
|
$result = Invoke-SSHCommand -SessionId $session.SessionId -Command $remoteCmd -TimeOut $TimeoutSeconds
|
|
return $result
|
|
}
|
|
finally {
|
|
Remove-SSHSession -SessionId $session.SessionId | Out-Null
|
|
}
|
|
}
|
|
|
|
function Send-HomelabPath {
|
|
param(
|
|
$Config,
|
|
[string]$LocalPath,
|
|
[string]$RemoteDir
|
|
)
|
|
Ensure-PoshSshModule
|
|
$target = Resolve-HomelabIPv4 $Config.HostName
|
|
$remoteDir = ($RemoteDir.TrimEnd('/') + '/')
|
|
|
|
$sftp = New-SFTPSession -ComputerName $target -Credential $Config.Credential -AcceptKey
|
|
if (-not $sftp) { throw "SFTP-Verbindung zu ${target} fehlgeschlagen." }
|
|
try {
|
|
Set-SFTPItem -SessionId $sftp.SessionId -Path $LocalPath -Destination $remoteDir -Force
|
|
}
|
|
finally {
|
|
Remove-SFTPSession -SessionId $sftp.SessionId | Out-Null
|
|
}
|
|
}
|