mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 23:01:09 +02:00
mana-voice-bot's source default was 3050, which collided with mana-sync. Today the collision is latent (voice-bot isn't deployed anywhere), but sooner or later someone is going to start it on a host that's already running mana-sync and the second one will refuse to bind. Moving to 3024 puts it inside the AI/ML port range alongside its dependencies (stt 3020, tts 3022, image-gen 3023, llm 3025) and away from sync. Updated: - app/main.py — PORT default 3050 → 3024 - start.sh, setup.sh — same fix in the example commands - CLAUDE.md — full rewrite. Old version described "Mac Mini deployment" with launchd; the new version explicitly says "not deployed yet" and documents the seven concrete steps to deploy on the Windows GPU box alongside the other AI services (Scheduled Task, service.pyw, .env, firewall rule, cloudflared route, WINDOWS_GPU_SERVER_SETUP.md update). docs/WINDOWS_GPU_SERVER_SETUP.md: - Added the missing ManaVideoGen scheduled task to all four Start-ScheduledTask snippets — video-gen has been running on the Windows GPU but the doc had never picked it up. - Added a "mana-video-gen (Port 3026)" service section parallel to the existing image-gen one, with venv path, repo pointer, model, etc. - Added a repo-pendants table mapping C:\mana\services\<svc>\ to the corresponding services/<svc>/ directory in the repo, plus a note that changes should flow repo→Windows, not the other way around. docs/PORT_SCHEMA.md: - Reconciled the warning block with the post-cleanup reality: no more active or latent port collisions (image-gen ↔ video-gen and voice-bot ↔ sync are both resolved). Listed the actual ports per host with public URLs. Kept the planned-vs-actual disclaimer for the services that still don't match the aspirational ranges (mana-credits 3061 vs planned 3002, etc).
823 lines
27 KiB
Markdown
823 lines
27 KiB
Markdown
# Windows GPU-Server: Lokale Einrichtung
|
|
|
|
Diese Anleitung wird **am Windows-PC selbst** durchgeführt.
|
|
Ziel: SSH + Grundkonfiguration, damit der Rechner remote steuerbar ist.
|
|
|
|
Danach kann alles Weitere (Ollama, AI-Services, Cloudflare Tunnel) per SSH erledigt werden.
|
|
|
|
---
|
|
|
|
## Checkliste: Nach jedem Neustart
|
|
|
|
> **Wichtig:** Bis der Server-Modus (Schritt 9) vollständig konfiguriert ist, können nach einem Neustart einige Dinge manuell geprüft/repariert werden müssen.
|
|
|
|
PowerShell **als Administrator** ausführen:
|
|
|
|
```powershell
|
|
# 1. Netzwerkprofil auf "Privat" setzen
|
|
# (Windows setzt es nach Neustart manchmal auf "Öffentlich" zurück,
|
|
# was die Firewall verschärft und SSH/Ping blockt)
|
|
Get-NetConnectionProfile | Set-NetConnectionProfile -NetworkCategory Private
|
|
|
|
# 2. SSH-Dienst prüfen (muss "Running" sein)
|
|
Get-Service sshd
|
|
# Falls "Stopped": Start-Service sshd
|
|
|
|
# 3. AI-Services prüfen
|
|
python C:\mana\status.py
|
|
# Falls Services nicht laufen:
|
|
Start-ScheduledTask -TaskName "ManaLLM"
|
|
Start-ScheduledTask -TaskName "ManaSTT"
|
|
Start-ScheduledTask -TaskName "ManaTTS"
|
|
Start-ScheduledTask -TaskName "ManaImageGen"
|
|
Start-ScheduledTask -TaskName "ManaVideoGen"
|
|
```
|
|
|
|
Wenn Schritt 9 (Server-Modus) korrekt konfiguriert ist, sollte der PC:
|
|
- Nie in den Ruhezustand gehen
|
|
- Nach Neustart automatisch einloggen
|
|
- Alle Services automatisch starten (Scheduled Tasks mit AtLogOn)
|
|
- Netzwerkprofil dauerhaft auf "Privat" stehen
|
|
|
|
### Netzwerkprofil dauerhaft auf "Privat" fixieren
|
|
|
|
Damit das Netzwerk nach Neustart nicht wieder auf "Öffentlich" springt:
|
|
|
|
```powershell
|
|
# Variante 1: Per Registry (empfohlen)
|
|
# Erst die aktuelle Netzwerk-ID herausfinden:
|
|
Get-NetConnectionProfile
|
|
|
|
# Dann in der Registry fixieren (ProfileType: 1=Privat, 0=Öffentlich):
|
|
$profiles = Get-ChildItem "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkList\Profiles"
|
|
foreach ($profile in $profiles) {
|
|
Set-ItemProperty -Path $profile.PSPath -Name Category -Value 1
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Erstinstallation
|
|
|
|
### Schritt 1: Computername setzen
|
|
|
|
PowerShell **als Administrator** öffnen (Rechtsklick → Als Administrator ausführen):
|
|
|
|
```powershell
|
|
Rename-Computer -NewName "mana-server-gpu"
|
|
```
|
|
|
|
Noch **nicht** neu starten — erst alle Schritte durchgehen.
|
|
|
|
---
|
|
|
|
## Schritt 2: SSH-Server aktivieren
|
|
|
|
Gleiche Admin-PowerShell:
|
|
|
|
```powershell
|
|
# SSH-Server installieren
|
|
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
|
|
|
|
# SSH-Server starten
|
|
Start-Service sshd
|
|
|
|
# Automatisch bei jedem Start
|
|
Set-Service -Name sshd -StartupType Automatic
|
|
|
|
# Standard-Shell auf PowerShell setzen (statt cmd)
|
|
New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -PropertyType String -Force
|
|
```
|
|
|
|
---
|
|
|
|
## Schritt 3: Statische IP vergeben
|
|
|
|
1. **Einstellungen** → **Netzwerk und Internet** → **Ethernet**
|
|
2. Bei der aktiven Verbindung auf **Bearbeiten** klicken (bei IP-Zuweisung)
|
|
3. Auf **Manuell** umstellen, **IPv4** aktivieren:
|
|
|
|
```
|
|
IP-Adresse: 192.168.178.11
|
|
Subnetzmaske: 255.255.255.0
|
|
Gateway: 192.168.178.1
|
|
Bevorzugter DNS: 192.168.178.1
|
|
Alternativer DNS: 1.1.1.1
|
|
```
|
|
|
|
> Mac Mini ist auf `192.168.178.131`, Gateway ist `192.168.178.1`.
|
|
|
|
---
|
|
|
|
## Schritt 4: Firewall-Ports öffnen
|
|
|
|
Gleiche Admin-PowerShell:
|
|
|
|
```powershell
|
|
# SSH (sollte schon offen sein, sicherheitshalber)
|
|
New-NetFirewallRule -DisplayName "SSH" -Direction Inbound -LocalPort 22 -Protocol TCP -Action Allow
|
|
|
|
# Ollama
|
|
New-NetFirewallRule -DisplayName "Ollama" -Direction Inbound -LocalPort 11434 -Protocol TCP -Action Allow
|
|
|
|
# AI-Services
|
|
New-NetFirewallRule -DisplayName "Mana-STT" -Direction Inbound -LocalPort 3020 -Protocol TCP -Action Allow
|
|
New-NetFirewallRule -DisplayName "Mana-TTS" -Direction Inbound -LocalPort 3022 -Protocol TCP -Action Allow
|
|
New-NetFirewallRule -DisplayName "Mana-Image-Gen" -Direction Inbound -LocalPort 3023 -Protocol TCP -Action Allow
|
|
New-NetFirewallRule -DisplayName "Mana-LLM" -Direction Inbound -LocalPort 3025 -Protocol TCP -Action Allow
|
|
New-NetFirewallRule -DisplayName "Mana-Video-Gen" -Direction Inbound -LocalPort 3026 -Protocol TCP -Action Allow
|
|
```
|
|
|
|
---
|
|
|
|
## Schritt 5: NVIDIA-Treiber prüfen
|
|
|
|
```powershell
|
|
nvidia-smi
|
|
```
|
|
|
|
Falls der Befehl nicht gefunden wird oder der Treiber alt ist (< 535.x):
|
|
1. https://www.nvidia.com/Download/index.aspx → neusten Treiber für deine GPU laden
|
|
2. Installieren, neu starten
|
|
|
|
Falls `nvidia-smi` funktioniert → Treiberversion und GPU-Name notieren.
|
|
|
|
---
|
|
|
|
## Schritt 6: Python 3.11 installieren
|
|
|
|
```powershell
|
|
winget install Python.Python.3.11
|
|
```
|
|
|
|
Falls `winget` nicht verfügbar: https://www.python.org/downloads/ → 3.11.x
|
|
|
|
> **Wichtig:** Bei der Installation "Add Python to PATH" ankreuzen!
|
|
|
|
Prüfen:
|
|
|
|
```powershell
|
|
python --version
|
|
```
|
|
|
|
---
|
|
|
|
## Schritt 7: Git installieren
|
|
|
|
```powershell
|
|
winget install Git.Git
|
|
```
|
|
|
|
Prüfen (neue PowerShell öffnen):
|
|
|
|
```powershell
|
|
git --version
|
|
```
|
|
|
|
---
|
|
|
|
## Schritt 8: Arbeitsverzeichnis anlegen
|
|
|
|
```powershell
|
|
mkdir C:\mana
|
|
mkdir C:\mana\services
|
|
mkdir C:\mana\venvs
|
|
mkdir C:\mana\models
|
|
```
|
|
|
|
---
|
|
|
|
## Schritt 9: Server-Modus konfigurieren (Always-On)
|
|
|
|
Windows ist standardmäßig als Desktop-PC konfiguriert und geht in den Ruhezustand — das führt dazu, dass SSH und alle AI-Services nicht mehr erreichbar sind. Für den Server-Betrieb muss das komplett deaktiviert werden.
|
|
|
|
PowerShell **als Administrator**:
|
|
|
|
```powershell
|
|
# ============================================
|
|
# 1. Energiesparplan auf "Höchstleistung" setzen
|
|
# ============================================
|
|
powercfg /setactive 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c
|
|
|
|
# ============================================
|
|
# 2. Ruhezustand komplett deaktivieren
|
|
# ============================================
|
|
powercfg /hibernate off
|
|
|
|
# Standby deaktivieren (Netzbetrieb)
|
|
powercfg /change standby-timeout-ac 0
|
|
# Bildschirm-Timeout (optional: 0 = nie, oder 30 = 30 Min)
|
|
powercfg /change monitor-timeout-ac 30
|
|
# Festplatten-Timeout deaktivieren
|
|
powercfg /change disk-timeout-ac 0
|
|
|
|
# ============================================
|
|
# 3. Netzwerkadapter darf NICHT in Energiesparmodus
|
|
# ============================================
|
|
# Alle Netzwerkadapter: Energiesparen deaktivieren
|
|
Get-NetAdapter -Physical | ForEach-Object {
|
|
$name = $_.Name
|
|
# Disable "Allow the computer to turn off this device to save power"
|
|
$adapter = Get-WmiObject -Class Win32_NetworkAdapter | Where-Object { $_.NetConnectionID -eq $name }
|
|
if ($adapter) {
|
|
$deviceID = $adapter.PNPDeviceID
|
|
$key = "HKLM:\SYSTEM\CurrentControlSet\Enum\$deviceID\Device Parameters\WDF"
|
|
# Setze PnPCapabilities = 24 (disable power management)
|
|
$regPath = "HKLM:\SYSTEM\CurrentControlSet\Enum\$deviceID"
|
|
if (Test-Path "$regPath\Device Parameters") {
|
|
# Alternative: über Geräte-Manager manuell deaktivieren
|
|
Write-Host "Bitte im Geräte-Manager für '$name' Energiesparen manuell deaktivieren"
|
|
}
|
|
}
|
|
}
|
|
|
|
# ============================================
|
|
# 4. USB-Energiesparen deaktivieren (für Peripherie)
|
|
# ============================================
|
|
powercfg /setacvalueindex SCHEME_CURRENT 2a737441-1930-4402-8d77-b2bebba308a3 48e6b7a6-50f5-4782-a5d4-53bb8f07e226 0
|
|
powercfg /setactive SCHEME_CURRENT
|
|
|
|
# ============================================
|
|
# 5. Schnellstart deaktivieren (verursacht Probleme mit SSH nach Neustart)
|
|
# ============================================
|
|
reg add "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Power" /v HiberbootEnabled /t REG_DWORD /d 0 /f
|
|
|
|
# ============================================
|
|
# 6. Automatischen Neustart nach Windows Update verhindern
|
|
# ============================================
|
|
# Aktive Stunden auf Maximum setzen (verhindert Neustarts tagsüber)
|
|
reg add "HKLM\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings" /v ActiveHoursStart /t REG_DWORD /d 6 /f
|
|
reg add "HKLM\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings" /v ActiveHoursEnd /t REG_DWORD /d 2 /f
|
|
|
|
# ============================================
|
|
# 7. Auto-Login nach Neustart (für Scheduled Tasks)
|
|
# ============================================
|
|
# WICHTIG: Scheduled Tasks mit "AtLogOn" brauchen eine aktive Sitzung.
|
|
# Nach einem Neustart muss der User automatisch eingeloggt werden.
|
|
# Über GUI: netplwiz → Haken bei "Benutzer müssen Benutzernamen und Kennwort eingeben" entfernen
|
|
# Oder per Registry (Passwort wird hier im Klartext gespeichert!):
|
|
# reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v AutoAdminLogon /t REG_SZ /d 1 /f
|
|
# reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultUserName /t REG_SZ /d "tills" /f
|
|
# reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultPassword /t REG_SZ /d "DEIN_PASSWORT" /f
|
|
```
|
|
|
|
### Manuell im Geräte-Manager prüfen
|
|
|
|
1. **Geräte-Manager** öffnen → **Netzwerkadapter** → Rechtsklick auf den Ethernet-Adapter
|
|
2. **Eigenschaften** → **Energieverwaltung**
|
|
3. Haken bei **"Computer kann das Gerät ausschalten, um Energie zu sparen"** entfernen
|
|
|
|
### Energiesparplan verifizieren
|
|
|
|
```powershell
|
|
# Aktiven Energiesparplan anzeigen
|
|
powercfg /getactivescheme
|
|
# Sollte "Höchstleistung" zeigen
|
|
|
|
# Alle Einstellungen prüfen
|
|
powercfg /query
|
|
```
|
|
|
|
---
|
|
|
|
## Schritt 10: Neustart
|
|
|
|
```powershell
|
|
Restart-Computer
|
|
```
|
|
|
|
Nach dem Neustart sollte der PC automatisch einloggen (falls Auto-Login konfiguriert) und die Energiespareinstellungen aktiv sein.
|
|
|
|
---
|
|
|
|
## Schritt 11: SSH-Key einrichten (passwortloser Zugriff)
|
|
|
|
Auf dem **Windows-PC** in PowerShell **als Administrator** ausführen:
|
|
|
|
```powershell
|
|
# Für Admin-User muss der Key in die systemweite Datei:
|
|
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAmtp92RmE6lPhHRg24VSYIvq9ne4+qe61SiR4c+lPWu claude-code@mana" | Out-File -Encoding utf8 -FilePath C:\ProgramData\ssh\administrators_authorized_keys
|
|
|
|
# Berechtigungen setzen (Windows erfordert das für SSH)
|
|
# Vererbung entfernen
|
|
icacls C:\ProgramData\ssh\administrators_authorized_keys /inheritance:r
|
|
|
|
# Berechtigungen setzen (NT AUTHORITY\SYSTEM funktioniert auf allen Sprachen)
|
|
icacls C:\ProgramData\ssh\administrators_authorized_keys /grant "NT AUTHORITY\SYSTEM:(R)"
|
|
|
|
# Admin-Gruppe: Name hängt von der Systemsprache ab, SID ist immer gleich
|
|
$adminGroup = (New-Object System.Security.Principal.SecurityIdentifier("S-1-5-32-544")).Translate([System.Security.Principal.NTAccount]).Value
|
|
icacls C:\ProgramData\ssh\administrators_authorized_keys /grant "${adminGroup}:(R)"
|
|
```
|
|
|
|
> **Warum nicht `~/.ssh/authorized_keys`?** Windows OpenSSH ignoriert diese Datei für Benutzer in der Administratoren-Gruppe. Stattdessen wird `C:\ProgramData\ssh\administrators_authorized_keys` gelesen.
|
|
|
|
---
|
|
|
|
## Schritt 12: SSH testen
|
|
|
|
**Vom Mac (dev-Rechner)** aus testen:
|
|
|
|
```bash
|
|
ssh tills@192.168.178.11
|
|
```
|
|
|
|
Beim ersten Mal Fingerprint bestätigen mit `yes`.
|
|
|
|
Falls erfolgreich, sollte eine PowerShell-Sitzung starten.
|
|
|
|
### Zusätzlich testen:
|
|
|
|
```bash
|
|
# GPU erreichbar?
|
|
ssh tills@192.168.178.11 "nvidia-smi"
|
|
|
|
# Python da?
|
|
ssh tills@192.168.178.11 "python --version"
|
|
```
|
|
|
|
---
|
|
|
|
## Ergebnis
|
|
|
|
Nach diesen Schritten hat der Windows-PC:
|
|
|
|
- [x] Fester Computername (`mana-server-gpu`)
|
|
- [x] SSH-Server (Port 22, Autostart)
|
|
- [x] Statische IP im LAN
|
|
- [x] Firewall-Ports offen für alle AI-Services
|
|
- [x] NVIDIA-Treiber mit CUDA-Support
|
|
- [x] Python 3.11
|
|
- [x] Git
|
|
- [x] Arbeitsverzeichnis `C:\mana\`
|
|
- [x] Server-Modus: Kein Ruhezustand, kein Standby, Höchstleistung
|
|
- [x] Auto-Login nach Neustart (für Scheduled Tasks)
|
|
- [x] Schnellstart deaktiviert (sauberer SSH-Boot)
|
|
|
|
**Alles Weitere (Ollama, AI-Services, Cloudflare Tunnel) wird dann per SSH gemacht.**
|
|
|
|
---
|
|
|
|
## AI-Services Einrichtung (per SSH)
|
|
|
|
Nach der Grundinstallation wurden folgende AI-Services eingerichtet:
|
|
|
|
### Ollama (LLM Inference)
|
|
|
|
- **Port**: 11434
|
|
- **Host-Binding**: `0.0.0.0` (LAN-Zugriff via `OLLAMA_HOST` System-Umgebungsvariable)
|
|
- **Installierte Modelle**:
|
|
- `gemma3:4b` (3.3 GB) - Schnelles Chat-Modell
|
|
- `gemma3:12b` (8.1 GB) - Bessere Qualität
|
|
- `qwen2.5-coder:14b` (9.0 GB) - Code-Generierung
|
|
- `nomic-embed-text` - Embedding-Modell
|
|
|
|
Ollama startet automatisch beim Login (System Tray).
|
|
|
|
### mana-llm (Port 3025)
|
|
|
|
Zentraler LLM-Gateway mit OpenAI-kompatiblem API. Routet Anfragen an Ollama und Cloud-Provider.
|
|
|
|
- **Verzeichnis**: `C:\mana\services\mana-llm\`
|
|
- **venv**: `C:\mana\venvs\llm\`
|
|
- **Config**: `C:\mana\services\mana-llm\.env`
|
|
- **Log**: `C:\mana\services\mana-llm\service.log`
|
|
- **Autostart**: Windows Scheduled Task "ManaLLM" (AtLogOn)
|
|
|
|
### mana-stt (Port 3020)
|
|
|
|
Speech-to-Text mit faster-whisper (CUDA-beschleunigt auf RTX 3090).
|
|
|
|
- **Verzeichnis**: `C:\mana\services\mana-stt\`
|
|
- **venv**: `C:\mana\venvs\stt\`
|
|
- **Config**: `C:\mana\services\mana-stt\.env`
|
|
- **Log**: `C:\mana\services\mana-stt\service.log`
|
|
- **Autostart**: Windows Scheduled Task "ManaSTT" (AtLogOn)
|
|
- **Backend**: `faster-whisper` mit CTranslate2 (CUDA float16)
|
|
- **Default-Modell**: `large-v3-turbo` (~1.6 GB, wird beim ersten Request geladen)
|
|
|
|
### mana-tts (Port 3022)
|
|
|
|
Text-to-Speech mit mehreren Backends:
|
|
|
|
- **Verzeichnis**: `C:\mana\services\mana-tts\`
|
|
- **venv**: `C:\mana\venvs\tts\` (PyTorch 2.5.1+cu121)
|
|
- **Config**: `C:\mana\services\mana-tts\.env`
|
|
- **Log**: `C:\mana\services\mana-tts\service.log`
|
|
- **Autostart**: Windows Scheduled Task "ManaTTS" (AtLogOn)
|
|
- **Backends**:
|
|
- **Kokoro** (82M, CUDA) — Englische Stimmen, ~1s Latenz, 27 Stimmen
|
|
- **Edge TTS** (Cloud) — Deutsche Stimmen (Katja, Conrad, etc.), ~2s Latenz
|
|
- **Piper** (CPU/ONNX) — Lokale deutsche Stimmen (Thorsten, Kerstin), schnell
|
|
- **F5-TTS** (CUDA) — Voice Cloning mit Referenz-Audio
|
|
|
|
### mana-image-gen (Port 3023)
|
|
|
|
Bildgenerierung mit FLUX.1-schnell (12B Parameter) via HuggingFace diffusers.
|
|
|
|
- **Verzeichnis**: `C:\mana\services\mana-image-gen\`
|
|
- **Repo-Pendant**: [`services/mana-image-gen/`](../services/mana-image-gen/) — `service.pyw`, `app/main.py`, `app/flux_service.py`, `app/api_auth.py`, `app/vram_manager.py`
|
|
- **venv**: `C:\mana\venvs\image-gen\` (PyTorch 2.5.1+cu121)
|
|
- **Config**: `C:\mana\services\mana-image-gen\.env` (siehe `services/mana-image-gen/.env.example`)
|
|
- **Log**: `C:\mana\services\mana-image-gen\service.log`
|
|
- **Autostart**: Windows Scheduled Task "ManaImageGen" (AtLogOn)
|
|
- **Modell**: FLUX.1-schnell (Apache 2.0, 4-bit quantisiert via BitsAndBytes)
|
|
- **HuggingFace**: Erfordert Login + Lizenzakzeptanz für gated Model
|
|
|
|
### mana-video-gen (Port 3026)
|
|
|
|
Videogenerierung mit LTX-Video (~2B Parameter) via HuggingFace diffusers + CUDA.
|
|
|
|
- **Verzeichnis**: `C:\mana\services\mana-video-gen\`
|
|
- **Repo-Pendant**: [`services/mana-video-gen/`](../services/mana-video-gen/) — `service.pyw`, `app/main.py`, `app/ltx_service.py`, `setup.sh`, `requirements.txt`
|
|
- **venv**: `C:\mana\venvs\video-gen\` (PyTorch + CUDA + diffusers)
|
|
- **Config**: `C:\mana\services\mana-video-gen\.env`
|
|
- **Log**: `C:\mana\services\mana-video-gen\service.log`
|
|
- **Autostart**: Windows Scheduled Task "ManaVideoGen" (AtLogOn)
|
|
- **Modell**: LTX-Video (Lightricks)
|
|
- **HuggingFace**: HF_TOKEN erforderlich für Model-Download
|
|
|
|
### Repo-Pendants der anderen GPU-Services
|
|
|
|
| Windows-Pfad | Repo-Pfad |
|
|
|---|---|
|
|
| `C:\mana\services\mana-llm\` | [`services/mana-llm/`](../services/mana-llm/) |
|
|
| `C:\mana\services\mana-stt\` | [`services/mana-stt/`](../services/mana-stt/) |
|
|
| `C:\mana\services\mana-tts\` | [`services/mana-tts/`](../services/mana-tts/) |
|
|
|
|
Jeder Service hat im Repo eine `service.pyw` Datei — das ist der Runner, den die Scheduled Tasks aufrufen. Änderungen an einem Service sollten primär im Repo gemacht und dann auf die Windows-Box gespiegelt werden, nicht andersrum.
|
|
|
|
### Management-Skripte
|
|
|
|
```powershell
|
|
# Status aller Services anzeigen
|
|
python C:\mana\status.py
|
|
|
|
# Alle Services starten (falls nicht via Scheduled Task)
|
|
python C:\mana\start-all.py
|
|
|
|
# Alle Services stoppen
|
|
python C:\mana\stop-all.py
|
|
|
|
# Scheduled Tasks manuell starten/stoppen
|
|
Start-ScheduledTask -TaskName "ManaLLM"
|
|
Start-ScheduledTask -TaskName "ManaSTT"
|
|
Start-ScheduledTask -TaskName "ManaTTS"
|
|
Start-ScheduledTask -TaskName "ManaImageGen"
|
|
Start-ScheduledTask -TaskName "ManaVideoGen"
|
|
|
|
# Alle Scheduled Tasks auf einmal anzeigen
|
|
Get-ScheduledTask -TaskName "Mana*" | Format-Table TaskName, State
|
|
```
|
|
|
|
### Zugriff: Öffentliche URLs (von überall)
|
|
|
|
Die GPU-Services sind über den Cloudflare Tunnel des Mac Mini öffentlich erreichbar.
|
|
Auf dem Mac Mini läuft ein TCP-Proxy (`~/gpu-proxy.py` als LaunchAgent), der den Traffic
|
|
an den GPU-Server im LAN weiterleitet.
|
|
|
|
```
|
|
Internet → Cloudflare → Mac Mini (gpu-proxy.py) → GPU Server (LAN)
|
|
```
|
|
|
|
| Service | Öffentliche URL |
|
|
|---------|----------------|
|
|
| mana-llm | `https://gpu-llm.mana.how` |
|
|
| mana-stt | `https://gpu-stt.mana.how` |
|
|
| mana-tts | `https://gpu-tts.mana.how` |
|
|
| mana-image-gen | `https://gpu-img.mana.how` |
|
|
| mana-video-gen | `https://gpu-video.mana.how` |
|
|
| Ollama | `https://gpu-ollama.mana.how` |
|
|
|
|
```bash
|
|
# LLM API
|
|
curl https://gpu-llm.mana.how/health
|
|
curl -X POST https://gpu-llm.mana.how/v1/chat/completions \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"model":"ollama/gemma3:12b","messages":[{"role":"user","content":"Hallo"}]}'
|
|
|
|
# STT API (WhisperX mit Word-Timestamps + Speaker Diarization)
|
|
curl https://gpu-stt.mana.how/health
|
|
curl -X POST https://gpu-stt.mana.how/transcribe \
|
|
-F "file=@recording.wav" -F "language=de" -F "align=true" -F "diarize=true"
|
|
|
|
# TTS API
|
|
curl https://gpu-tts.mana.how/health
|
|
curl -X POST https://gpu-tts.mana.how/synthesize/auto \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"text":"Hallo Welt","voice":"de_katja"}' --output hello.wav
|
|
|
|
# Image Generation (FLUX.2 klein 4B)
|
|
curl -X POST https://gpu-img.mana.how/generate \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"prompt":"A cat","width":1024,"height":1024}'
|
|
|
|
# Video Generation (LTX-Video)
|
|
curl https://gpu-video.mana.how/health
|
|
curl -X POST https://gpu-video.mana.how/generate \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"prompt":"Ocean waves crashing on rocks","width":704,"height":480}'
|
|
|
|
# Ollama direkt
|
|
curl https://gpu-ollama.mana.how/api/tags
|
|
```
|
|
|
|
### Zugriff: LAN (direkt, schneller)
|
|
|
|
Vom Mac Mini oder anderen Geräten im gleichen Netzwerk:
|
|
|
|
```bash
|
|
curl http://192.168.178.11:3025/health # mana-llm
|
|
curl http://192.168.178.11:3020/health # mana-stt
|
|
curl http://192.168.178.11:3022/health # mana-tts
|
|
curl http://192.168.178.11:3023/health # mana-image-gen
|
|
curl http://192.168.178.11:3026/health # mana-video-gen
|
|
curl http://192.168.178.11:11434/api/tags # Ollama
|
|
```
|
|
|
|
### Verzeichnisstruktur
|
|
|
|
```
|
|
C:\mana\
|
|
├── services\
|
|
│ ├── mana-llm\ # LLM Gateway Service (Port 3025)
|
|
│ │ ├── src\ # Python-Quellcode (FastAPI + Provider Router)
|
|
│ │ ├── .env # Konfiguration
|
|
│ │ ├── service.pyw # Service Runner
|
|
│ │ └── service.log # Log
|
|
│ ├── mana-stt\ # Speech-to-Text Service (Port 3020)
|
|
│ │ ├── app\ # Python-Quellcode (faster-whisper CUDA)
|
|
│ │ ├── .env
|
|
│ │ ├── service.pyw
|
|
│ │ └── service.log
|
|
│ ├── mana-tts\ # Text-to-Speech Service (Port 3022)
|
|
│ │ ├── app\ # Python-Quellcode (Kokoro + Edge TTS + Piper)
|
|
│ │ ├── .env
|
|
│ │ ├── service.pyw
|
|
│ │ └── service.log
|
|
│ └── mana-image-gen\ # Bildgenerierung (Port 3023)
|
|
│ ├── app\ # Python-Quellcode (diffusers + FLUX)
|
|
│ ├── output\ # Generierte Bilder (temporär)
|
|
│ ├── .env
|
|
│ ├── service.pyw
|
|
│ └── service.log
|
|
├── venvs\
|
|
│ ├── llm\ # Python venv für mana-llm
|
|
│ ├── stt\ # Python venv für mana-stt (faster-whisper)
|
|
│ ├── tts\ # Python venv für mana-tts (PyTorch+CUDA)
|
|
│ └── image-gen\ # Python venv für mana-image-gen (PyTorch+CUDA+diffusers)
|
|
├── models\ # (reserviert für lokale Modelle)
|
|
├── start-all.py # Alle Services starten
|
|
├── stop-all.py # Alle Services stoppen
|
|
├── status.py # Status-Übersicht
|
|
├── healthcheck.py # Health Check + Auto-Restart (alle 5 Min)
|
|
├── healthcheck.log # Health Check Log
|
|
├── log-rotate.py # Log-Rotation (>10MB → .log.1/.2/.3)
|
|
├── log-shipper.py # Logs an Loki auf Mac Mini senden
|
|
└── log-shipper-state.json # Letzte Leseposition pro Log
|
|
```
|
|
|
|
---
|
|
|
|
## Health Check & Auto-Restart
|
|
|
|
Ein Health-Check-Skript prüft alle 5 Minuten ob die Services laufen und startet gefallene neu.
|
|
Zusätzlich werden Log-Rotation und Log-Shipping (an Loki) ausgeführt.
|
|
|
|
- **Skript**: `C:\mana\healthcheck.py`
|
|
- **Log**: `C:\mana\healthcheck.log`
|
|
- **Scheduled Task**: `ManaHealthCheck` (alle 5 Min)
|
|
- **Ausführungsreihenfolge**: Health Check → Log-Rotation → Log-Shipping
|
|
|
|
```powershell
|
|
# Manuell ausführen
|
|
python C:\mana\healthcheck.py
|
|
|
|
# Log ansehen
|
|
Get-Content C:\mana\healthcheck.log -Tail 20
|
|
```
|
|
|
|
### Log-Rotation
|
|
|
|
- **Skript**: `C:\mana\log-rotate.py`
|
|
- **Trigger**: Wird vom Health-Check alle 5 Min aufgerufen
|
|
- **Schwelle**: Rotiert ab 10 MB
|
|
- **Backups**: 3 Kopien (service.log.1, .2, .3)
|
|
|
|
### Monitoring & Logs (Loki + Grafana)
|
|
|
|
GPU-Service-Logs werden alle 5 Minuten an **Loki** auf dem Mac Mini geschickt und sind über **Grafana** durchsuchbar.
|
|
|
|
```
|
|
GPU Server (healthcheck.py → log-shipper.py)
|
|
→ HTTP POST → Mac Mini (Loki :3100)
|
|
→ Grafana (grafana.mana.how)
|
|
```
|
|
|
|
**Komponenten:**
|
|
|
|
| Komponente | Wo | Beschreibung |
|
|
|---|---|---|
|
|
| `C:\mana\log-shipper.py` | GPU Server | Liest service.log Dateien, pusht neue Zeilen an Loki |
|
|
| `C:\mana\log-shipper-state.json` | GPU Server | Merkt sich letzte Leseposition pro Log |
|
|
| Loki (Docker) | Mac Mini | Log-Aggregator, 30 Tage Retention |
|
|
| VictoriaMetrics | Mac Mini | Scraped `/metrics` und `/health` der GPU-Services alle 15-30s |
|
|
| Grafana | Mac Mini | Dashboard unter `grafana.mana.how` |
|
|
|
|
**Loki-Queries in Grafana** (Explore → Datasource: Loki):
|
|
|
|
```
|
|
{job="mana-stt"} # Alle STT-Logs
|
|
{job="mana-llm"} |= "error" # LLM-Fehler
|
|
{host="gpu-server"} # Alle GPU-Server-Logs
|
|
{job="healthcheck"} |= "DOWN" # Service-Ausfälle
|
|
```
|
|
|
|
**Prometheus-Metriken** (VictoriaMetrics scraped über LAN):
|
|
|
|
| Target | Job | Port |
|
|
|---|---|---|
|
|
| GPU LLM | `gpu-llm` | 3025 (`/metrics`) |
|
|
| GPU STT | `gpu-stt` | 3020 (`/health`) |
|
|
| GPU TTS | `gpu-tts` | 3022 (`/health`) |
|
|
| GPU Image Gen | `gpu-image-gen` | 3023 (`/health`) |
|
|
| GPU Video Gen | `gpu-video-gen` | 3026 (`/health`) |
|
|
|
|
---
|
|
|
|
## TypeScript Client (`@mana/shared-gpu`)
|
|
|
|
Shared Package im Monorepo (`packages/shared-gpu/`) für alle GPU-Services:
|
|
|
|
```typescript
|
|
import { GpuClient } from '@mana/shared-gpu';
|
|
|
|
// Öffentlich (von überall, mit API-Key)
|
|
const gpu = new GpuClient({
|
|
baseUrl: 'https://gpu.mana.how',
|
|
apiKey: process.env.GPU_API_KEY,
|
|
});
|
|
|
|
// Oder LAN (direkt, schneller)
|
|
const gpuLan = new GpuClient({
|
|
baseUrl: 'http://192.168.178.11',
|
|
apiKey: process.env.GPU_API_KEY,
|
|
});
|
|
|
|
// Speech-to-Text (mit Word-Timestamps + Speaker Diarization)
|
|
const transcript = await gpu.stt.transcribe(audioBuffer, 'recording.wav', {
|
|
language: 'de',
|
|
diarize: true,
|
|
maxSpeakers: 3,
|
|
});
|
|
// → { text, words: [{ word, start, end, speaker }], speakers: ['SPEAKER_00', ...] }
|
|
|
|
// Text-to-Speech (Deutsch: Edge TTS, Englisch: Kokoro)
|
|
const { audio } = await gpu.tts.synthesize({ text: 'Hallo Welt', voice: 'de_katja' });
|
|
|
|
// Image Generation (FLUX.2 klein 4B, ~3s @ 1024x1024)
|
|
const image = await gpu.image.generate({ prompt: 'A futuristic city', width: 1024, height: 1024 });
|
|
const imageUrl = gpu.image.imageUrl(image.image_url);
|
|
|
|
// Health Check aller Services
|
|
const health = await gpu.healthCheck();
|
|
// → { stt: true, tts: true, image: true }
|
|
```
|
|
|
|
---
|
|
|
|
## API-Authentifizierung
|
|
|
|
Alle GPU-Services erfordern einen API-Key für Zugriff auf geschützte Endpoints.
|
|
`/health` und `/docs` sind öffentlich (kein Key nötig).
|
|
|
|
**API-Key:** In `.env.development` unter `GPU_API_KEY`
|
|
|
|
**Verwendung:**
|
|
|
|
```bash
|
|
# Mit Header
|
|
curl -H "X-API-Key: $GPU_API_KEY" https://gpu-llm.mana.how/v1/models
|
|
|
|
# Oder als Query-Parameter
|
|
curl "https://gpu-stt.mana.how/models?api_key=$GPU_API_KEY"
|
|
|
|
# Health (kein Key nötig)
|
|
curl https://gpu-llm.mana.how/health
|
|
```
|
|
|
|
**Konfiguration auf dem GPU-Server:**
|
|
|
|
| Service | Env-Variable | Datei |
|
|
|---|---|---|
|
|
| mana-llm | `GPU_API_KEY` | `C:\mana\services\mana-llm\.env` |
|
|
| mana-stt | `API_KEYS`, `INTERNAL_API_KEY` | `C:\mana\services\mana-stt\.env` |
|
|
| mana-tts | `API_KEYS`, `INTERNAL_API_KEY` | `C:\mana\services\mana-tts\.env` |
|
|
| mana-image-gen | `GPU_API_KEY` | `C:\mana\services\mana-image-gen\.env` |
|
|
|
|
---
|
|
|
|
## Fehlerbehebung
|
|
|
|
### Server nicht erreichbar (kein Ping, kein SSH)
|
|
|
|
**Häufigste Ursache: Ruhezustand/Energiesparen nicht deaktiviert.**
|
|
|
|
1. Am PC physisch aufwecken (Taste drücken)
|
|
2. Schritt 9 (Server-Modus) erneut durchführen
|
|
3. Prüfen:
|
|
|
|
```powershell
|
|
# Aktiven Energiesparplan anzeigen
|
|
powercfg /getactivescheme
|
|
# Muss "Höchstleistung" zeigen
|
|
|
|
# Ruhezustand-Status prüfen
|
|
powercfg /availablesleepstates
|
|
# "Ruhezustand" sollte NICHT aufgeführt sein
|
|
|
|
# Standby-Timeout prüfen (muss 0 sein)
|
|
powercfg /query SCHEME_CURRENT SUB_SLEEP STANDBYIDLE
|
|
```
|
|
|
|
### SSH verbindet nicht (PC ist aber an)
|
|
|
|
```powershell
|
|
# Auf dem Windows-PC prüfen:
|
|
Get-Service sshd # Muss "Running" zeigen
|
|
Test-NetConnection -ComputerName localhost -Port 22 # Muss "TcpTestSucceeded: True" zeigen
|
|
|
|
# SSH-Dienst neu starten
|
|
Restart-Service sshd
|
|
```
|
|
|
|
### Services laufen nicht nach Neustart
|
|
|
|
Die Services nutzen Scheduled Tasks mit `AtLogOn` — der User muss eingeloggt sein.
|
|
|
|
```powershell
|
|
# Prüfen ob Tasks registriert sind
|
|
Get-ScheduledTask -TaskName "Mana*" | Format-Table TaskName, State
|
|
|
|
# Manuell starten
|
|
Start-ScheduledTask -TaskName "ManaLLM"
|
|
Start-ScheduledTask -TaskName "ManaSTT"
|
|
Start-ScheduledTask -TaskName "ManaTTS"
|
|
Start-ScheduledTask -TaskName "ManaImageGen"
|
|
Start-ScheduledTask -TaskName "ManaVideoGen"
|
|
|
|
# Status prüfen
|
|
python C:\mana\status.py
|
|
```
|
|
|
|
Falls Tasks als "Ready" statt "Running" angezeigt werden:
|
|
- Auto-Login ist nicht konfiguriert → Schritt 9, Punkt 7
|
|
- Oder: manuell am PC einloggen
|
|
|
|
### Service-Logs prüfen
|
|
|
|
```powershell
|
|
# Letzten 20 Zeilen eines Logs anzeigen
|
|
Get-Content C:\mana\services\mana-llm\service.log -Tail 20
|
|
Get-Content C:\mana\services\mana-stt\service.log -Tail 20
|
|
Get-Content C:\mana\services\mana-tts\service.log -Tail 20
|
|
Get-Content C:\mana\services\mana-image-gen\service.log -Tail 20
|
|
```
|
|
|
|
### nvidia-smi zeigt Fehler
|
|
|
|
- Treiber neu installieren: https://www.nvidia.com/Download/index.aspx
|
|
- PC neu starten
|
|
- Prüfen ob die GPU im Geräte-Manager sichtbar ist
|
|
|
|
### GPU VRAM voll
|
|
|
|
```powershell
|
|
# GPU-Auslastung prüfen
|
|
nvidia-smi
|
|
|
|
# Einzelnen Service stoppen um VRAM freizugeben
|
|
python C:\mana\stop-all.py
|
|
|
|
# Oder gezielt einen Service neu starten
|
|
Stop-ScheduledTask -TaskName "ManaImageGen"
|
|
Start-ScheduledTask -TaskName "ManaImageGen"
|
|
```
|
|
|
|
### IP-Adresse stimmt nicht
|
|
|
|
```powershell
|
|
ipconfig
|
|
# → Ethernet-Adapter prüfen, IPv4-Adresse muss 192.168.178.11 sein
|
|
```
|
|
|
|
### Port-Konflikte prüfen
|
|
|
|
```powershell
|
|
# Alle lauschenden Ports anzeigen (deutsch: "ABHÖREN")
|
|
netstat -ano | Select-String "ABHOR"
|
|
|
|
# Welcher Prozess nutzt einen bestimmten Port?
|
|
netstat -ano | Select-String "3025"
|
|
Get-Process -Id <PID>
|
|
```
|