# xtts — AI-Box (Compute-Node) Setup & Bootstrap Der `xtts`-Stack sind ARIAs GPU-Dienste (STT: Voxtral/Whisper · TTS: F5-TTS · lokales LLM). Er läuft auf einer oder mehreren **AI-Boxen** — jede per `.env` konfiguriert (`COMPOSE_PROFILES`, GPU-Zuordnung). Details zu Profilen/GPU-Wahl stehen im Haupt-README (Abschnitt „Compute-Nodes"). `bootstrap.sh` macht aus einem frisch installierten **Debian Trixie** (headless, nur SSH) einen startklaren GPU-Host für diesen Stack. ## Was das Script tut 1. Basis-Pakete (curl, gnupg, git …) 2. `contrib non-free non-free-firmware` aktivieren (Trixie-**deb822**-Format berücksichtigt) 3. **NVIDIA-Treiber** installieren (`nvidia-driver` + firmware) 4. **Docker** Engine + Compose-Plugin 5. **NVIDIA Container Toolkit** + Docker-Runtime auf NVIDIA konfigurieren 6. `xtts/.env` aus `.env.example` anlegen (RVS_TOKEN optional gleich setzen) 7. **GPU-im-Container-Test** (`docker run --gpus all … nvidia-smi`) 8. optional (`--up`): den `xtts`-Stack hochziehen Alles **idempotent** — mehrfach ausführbar. ## Ablauf ```bash git clone ARIA-AGENT cd ARIA-AGENT/xtts sudo ./bootstrap.sh # → Wenn der Treiber frisch installiert wurde: einmal neu starten, dann nochmal: sudo reboot # … nach dem Boot: cd ARIA-AGENT/xtts sudo ./bootstrap.sh --up --token ``` Der Treiber-Reboot ist normal (Kernel-Modul wird erst beim Boot geladen). Beim zweiten Lauf überspringt das Script alles Erledigte und macht nur noch den GPU-Test + Stack-Start. ## Optionen | Option | Wirkung | |---|---| | `--up` | am Ende `docker compose up -d --build` (Default-Profil) | | `--token ` | `RVS_TOKEN` in `xtts/.env` eintragen (auch via `RVS_TOKEN=…` env) | | `--rvs-host ` | `RVS_HOST` setzen | | `--upgrade-driver` | NVIDIA-Treiber aus **NVIDIAs** Paketquelle für Debian 13 (siehe unten). Spielt erst durch, zeigt den Plan, fragt nach. Danach Reboot. | | `--yes` | bei `--upgrade-driver` nicht nachfragen | ## Treiber für das lokale LLM: `--upgrade-driver` Debian hat höchstens Treiber **550** (CUDA 12.4). Die aktuellen llama.cpp- und llama-swap-Images brauchen CUDA 12.8/12.9. Mit 550 meldet llama.cpp beim Start `failed to initialize CUDA … forward compatibility …`, findet **keine** Karte und rechnet still auf der **CPU** — das Modell meldet trotzdem „bereit". Erkennbar daran, dass `nvidia-smi` auf der LLM-Karte kaum Speicher belegt zeigt. ```bash cd ARIA-AGENT/xtts sudo ./bootstrap.sh --upgrade-driver sudo reboot nvidia-smi # zeigt den neuen Treiber und eine CUDA-Version >= 12.9 docker compose up -d ``` Das Script trägt NVIDIAs Paketquelle ein und aktualisiert Treiber, Kernelmodul, `nvidia-smi` und `libcuda1` an Ort und Stelle (gleiche Paketnamen, neuere Version). Alte Debian-Teilpakete, die in den neuen aufgegangen sind, werden entfernt. Das **NVIDIA-Container-Toolkit bleibt unberührt** — würde apt es anfassen wollen, bricht das Script ab, ohne etwas zu ändern. Ebenso, wenn apt keinen sauberen Weg findet; die Paketquelle wird dann wieder entfernt. Whisper und F5-TTS laufen mit dem neuen Treiber weiter (neuere Treiber können ältere CUDA-Versionen). ## Wichtig - **Stimm-Daten** (nicht in git): falls von der alten Box noch vorhanden, `xtts/voice-id/` (Speaker-Fingerprint) + `xtts/voices/` (F5-Referenz) herkopieren. Sonst egal — in der App neu anlegen: Stimme neu enrollen (ohne Fingerprint läuft die Speaker-ID fail-open, alles geht durch) + F5-Voice-Referenz neu hochladen. - **Voxtral bleibt aus** auf der 3060 (braucht ≥16 GB VRAM). Das Default-Profil fährt Whisper (mit dem M0.1-Fix) + F5-TTS + lokales LLM. Voxtral erst mit der 24-GB-Karte: `docker compose stop whisper-bridge && docker compose --profile voxtral up -d --build`. - **Erster Start lädt Modelle** (mehrere GB via HuggingFace nach `xtts/hf-cache` + `xtts/models`) — genug Platz (1 TB NVMe ✓) und etwas Geduld. - **Box im selben Netz wie der RVS** (z.B. Rechenzentrum, direkt auf die interne IP statt NAT-Hairpin): in `xtts/.env` `RVS_HOST=` + **`RVS_SNI=`** (Name, für den das Caddy-Zert gilt). Ohne das scheitert TLS an `tlsv1 alert internal error`. Zuhause / normal: `RVS_SNI` leer lassen. ## Verifizieren ```bash nvidia-smi # Host sieht die GPU docker run --rm --gpus all nvidia/cuda:12.4.0-base-ubuntu22.04 nvidia-smi # Container auch docker logs -f aria-whisper-bridge # "RVS verbunden" + service_status ready ``` ## Lokales LLM von außen nutzen (OpenAI-Endpunkt) `llama-swap` spricht **OpenAI-kompatibel** (`/v1/chat/completions`, `/v1/models`). Damit können Fremd-Tools direkt auf das lokale Modell: **OpenHands**, Continue, Open WebUI, Aider … ``` Base-URL: http://:/v1 Modell: qwen3-8b (oder ein anderer Key aus llama-swap/config.yaml) API-Key: LLM_OPENAI_KEY (falls gesetzt) ``` In der `.env`: | Variable | Bedeutung | |---|---| | `LLM_OPENAI_BIND` | `127.0.0.1` = nur diese Maschine (**Default, sicher**) · `0.0.0.0` = ganzes LAN | | `LLM_OPENAI_PORT` | Host-Port (Default `8081`) | | `LLM_OPENAI_KEY` | API-Key; leer = **ohne Authentifizierung** | > ⚠️ `LLM_OPENAI_BIND=0.0.0.0` **ohne** `LLM_OPENAI_KEY` heißt: jeder im Netz kann > das Modell benutzen. Entweder Key setzen oder auf localhost gebunden lassen. **Wo wird was konfiguriert?** - **Port und Erreichbarkeit** immer in der `.env`. Beides ist ein Docker-Port-Mapping und steht beim Container-Start fest — es lässt sich nicht aus der Ferne ändern. - **API-Key**: entweder in der `.env` **oder** — wenn dort leer — in der ARIA-Diagnostic unter *Compute-Flotte* bei der jeweiligen Box. Dort abgelegt landet er auf der Box unter `/models/openai_key.json` (Rechte 0600). - **Die `.env` hat immer Vorrang.** Steht `LLM_OPENAI_KEY` dort, ist das Feld in der Diagnostic **schreibgeschützt** (🔒-Hinweis). - Ein geänderter Key greift, sobald ein Modell das **nächste Mal geladen** wird (llama-server bekommt ihn per `--api-key`). Laufendes Modell also einmal entladen lassen (TTL) oder ein anderes Modell anfragen. Prüfen: ```bash curl -s http://localhost:8081/v1/models # ohne Key curl -s -H "Authorization: Bearer $LLM_OPENAI_KEY" \ http://localhost:8081/v1/models # mit Key ``` ## OpenHands (optionales Profil) OpenHands ist **rein optional** und liegt in einem eigenen Profil. Wer es nicht in `COMPOSE_PROFILES` aufführt, bei dem wird der Container **gar nicht erst angelegt** — das Image wird nicht einmal geladen. Für den normalen ARIA-Betrieb also einfach weglassen: ```bash COMPOSE_PROFILES=voxtral,f5tts,llm docker compose up -d # ohne OpenHands COMPOSE_PROFILES=llm,openhands docker compose up -d # mit OpenHands ``` Dann `http://:` (Default `3000`) öffnen. Das lokale Modell ist schon vorbelegt (`OPENHANDS_LLM_BASE_URL`, `OPENHANDS_LLM_MODEL`) und in der Oberfläche änderbar. | Variable | Bedeutung | |---|---| | `OPENHANDS_BIND` | `127.0.0.1` (Default) oder `0.0.0.0` fürs LAN | | `OPENHANDS_PORT` | Host-Port (Default `3000`) | | `OPENHANDS_LLM_BASE_URL` | Default `http://llama-swap:8080/v1` (Container-intern — **nicht** der Host-Port) | | `OPENHANDS_LLM_MODEL` | Default `openai/qwen3-8b` | > ⚠️ OpenHands startet eigene Arbeits-Container und bekommt dafür den **Docker-Socket**. > Das ist faktisch Root-Zugriff auf diese Maschine — wer die Oberfläche erreicht, > kann im Zweifel alles auf der Box. > > **Deshalb bleibt `OPENHANDS_BIND` auf `127.0.0.1`.** Von einem anderen Rechner > greifst Du per SSH-Tunnel zu, statt den Port ins LAN zu öffnen: > ```bash > ssh -L 3000:127.0.0.1:3000 user@box # dann lokal http://localhost:3000 > ``` > Das kostet nichts und ist die wirksamste Absicherung, solange der Socket > durchgereicht wird. Wer echte Isolation braucht: OpenHands in eine eigene VM, > oder einen rootless Docker-Daemon als Beiwagen statt des Host-Sockets. Ohne das Profil ändert sich nichts: Wer nur ARIAs Box fahren will, startet OpenHands gar nicht.