Initial PlayBull release with Trilogy Hub integration.

Includes homelab deploy tooling, image position/zoom manifest persistence, and full trading/casino stack.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-02 08:31:36 +02:00
commit 94b6cc3be9
60 changed files with 9206 additions and 0 deletions

130
deploy/homelab-lib.ps1 Normal file
View File

@@ -0,0 +1,130 @@
# 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
}
}