Zwei Ursachen, beide auf der KI-Box nachgewiesen:
1. llama.cpp fand auch mit Treiber 615 keine Karte ("unsupported display
driver / cuda driver combination"). Das llama-swap-Image traegt in seiner
ld.so.conf die eigene CUDA-Kompatibilitaets-libcuda (575) VOR dem vom
Container-Toolkit eingehaengten Host-Treiber (615) ein. Die Kompatibilitaets-
bibliothek hilft nur Rechenzentrumskarten; bei GeForce scheitert llama.cpp
damit — mit aelterem Treiber ("forward compatibility …") wie mit neuerem —
und rechnet still auf der CPU. Jetzt LD_LIBRARY_PATH mit dem Host-Treiber
zuerst. Auf der Box getestet: llama.cpp sieht CUDA0 + CUDA1. Whisper und
F5-TTS (andere Images) sehen ihre Karte mit 615 ohnehin.
2. Nach dem Reboot erreichte kein Container den RVS ("Temporary failure in name
resolution"). Debian traegt die Netzwerkkarte als allow-hotplug ein; darauf
wartet network-online.target nicht. Docker startete die Container 2 s nach
"online", bevor DHCP den DNS-Server lieferte ("DNS resolver has no external
nameservers"), und die Container behalten diesen leeren Stand. Passiert bei
jedem Reboot. bootstrap.sh legt jetzt ein systemd-Drop-in an: Docker wartet
vor dem Start bis zu 90 s auf einen Nameserver in /etc/resolv.conf, dann
startet es trotzdem. Netzkonfiguration bleibt unangetastet. Escaping und
beide Pfade (DNS da / nicht da) in einer echten systemd-Unit getestet.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
433 lines
20 KiB
Bash
Executable File
433 lines
20 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
#
|
|
# ARIA KI-Box (gpubox) Bootstrap — frisches Debian Trixie → startklarer
|
|
# GPU-Satelliten-Host fuer den xtts-Stack (Voxtral/Whisper STT, F5-TTS, lokales LLM).
|
|
#
|
|
# Ablauf nach `git clone`:
|
|
# cd ARIA-AGENT/xtts
|
|
# sudo ./bootstrap.sh # richtet Treiber + Docker + NVIDIA-Toolkit ein
|
|
# # (falls Treiber frisch installiert: einmal `sudo reboot`, dann Script erneut)
|
|
# sudo ./bootstrap.sh --up # dazu: xtts-Stack (Whisper+F5+LLM) hochziehen
|
|
#
|
|
# Optionen:
|
|
# --up am Ende den xtts-Stack starten (Default-Profil, OHNE voxtral)
|
|
# --upgrade-driver NVIDIA-Treiber aus NVIDIAs eigener Paketquelle fuer Debian 13
|
|
# (Debian selbst hat max. 550 = CUDA 12.4 — zu alt fuer die
|
|
# aktuellen llama.cpp/llama-swap-Images, die CUDA 12.8/12.9
|
|
# brauchen; ohne Upgrade rechnet das LLM still auf der CPU).
|
|
# Spielt erst durch, zeigt den Plan, fragt nach. Danach REBOOT.
|
|
# Default-Bootstrap laesst den Treiber unangetastet.
|
|
# --yes bei --upgrade-driver nicht nachfragen
|
|
# --token <TOK> RVS_TOKEN in xtts/.env eintragen (alternativ: env RVS_TOKEN=...)
|
|
# --rvs-host <H> RVS_HOST setzen (Default aus .env.example)
|
|
#
|
|
# IDEMPOTENT: bereits erledigte Schritte werden uebersprungen. Nach dem
|
|
# Treiber-Reboot einfach nochmal ausfuehren — der Rest laeuft dann durch.
|
|
#
|
|
set -euo pipefail
|
|
|
|
# ── CLI ──
|
|
DO_UP=0
|
|
DO_UPGRADE_DRIVER=0
|
|
ASSUME_YES=0
|
|
RVS_TOKEN_ARG="${RVS_TOKEN:-}"
|
|
RVS_HOST_ARG="${RVS_HOST:-}"
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--up) DO_UP=1; shift ;;
|
|
--upgrade-driver) DO_UPGRADE_DRIVER=1; shift ;;
|
|
--yes|-y) ASSUME_YES=1; shift ;;
|
|
--token) RVS_TOKEN_ARG="${2:-}"; shift 2 ;;
|
|
--rvs-host) RVS_HOST_ARG="${2:-}"; shift 2 ;;
|
|
-h|--help) grep '^#' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;;
|
|
*) echo "Unbekannte Option: $1"; exit 1 ;;
|
|
esac
|
|
done
|
|
|
|
# ── Log-Helfer ──
|
|
c_g="\033[1;32m"; c_y="\033[1;33m"; c_r="\033[1;31m"; c_b="\033[1;34m"; c_0="\033[0m"
|
|
STEP=0
|
|
step() { STEP=$((STEP+1)); echo -e "\n${c_b}[${STEP}] $*${c_0}"; }
|
|
ok() { echo -e " ${c_g}✓${c_0} $*"; }
|
|
warn() { echo -e " ${c_y}!${c_0} $*"; }
|
|
die() { echo -e "${c_r}✗ $*${c_0}" >&2; exit 1; }
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
XTTS_DIR="$REPO_ROOT/xtts"
|
|
|
|
# ── Preflight ──
|
|
[[ "$(id -u)" -eq 0 ]] || die "Bitte als root ausfuehren (sudo ./bootstrap.sh)."
|
|
command -v apt-get >/dev/null || die "Kein apt-get — dieses Script ist fuer Debian/Trixie."
|
|
export DEBIAN_FRONTEND=noninteractive
|
|
|
|
echo -e "${c_b}=== ARIA KI-Box Bootstrap ===${c_0}"
|
|
echo "Repo: $REPO_ROOT"
|
|
echo "xtts: $XTTS_DIR"
|
|
|
|
# ── 1. Basis-Pakete ──
|
|
step "Basis-Pakete"
|
|
apt-get update -qq
|
|
apt-get install -y -qq ca-certificates curl gnupg git lsb-release >/dev/null
|
|
ok "ca-certificates, curl, gnupg, git"
|
|
|
|
# ── 2. non-free Repos aktivieren (Trixie deb822 + Legacy) ──
|
|
step "APT-Komponenten (contrib non-free non-free-firmware)"
|
|
# Ergaenzt die drei Komponenten in JEDER Components:-Zeile einer deb822-Datei —
|
|
# pro Zeile nur was fehlt, reihenfolge-robust, idempotent. Die Adressen pruefen
|
|
# ganze Woerter (non-free-firmware zaehlt NICHT als non-free).
|
|
add_components() {
|
|
sed -i -E '/^[Cc]omponents:/{
|
|
/(^|[[:space:]])contrib([[:space:]]|$)/!s/$/ contrib/
|
|
/(^|[[:space:]])non-free([[:space:]]|$)/!s/$/ non-free/
|
|
/(^|[[:space:]])non-free-firmware([[:space:]]|$)/!s/$/ non-free-firmware/
|
|
}' "$1"
|
|
}
|
|
ENABLED_ANY=0
|
|
shopt -s nullglob
|
|
for f in /etc/apt/sources.list.d/*.sources; do
|
|
grep -qE '^[Cc]omponents:' "$f" || continue
|
|
b="$(md5sum "$f")"; add_components "$f"; a="$(md5sum "$f")"
|
|
if [[ "$b" != "$a" ]]; then ENABLED_ANY=1; ok "aktualisiert: $(basename "$f")"; fi
|
|
done
|
|
shopt -u nullglob
|
|
# Legacy /etc/apt/sources.list (deb-Zeilen)
|
|
if [[ -f /etc/apt/sources.list ]] && grep -qE '^deb ' /etc/apt/sources.list; then
|
|
if ! grep -qE '^deb .*[[:space:]]non-free([[:space:]]|$)' /etc/apt/sources.list; then
|
|
sed -i -E '/^deb .*debian/ s/$/ contrib non-free non-free-firmware/' /etc/apt/sources.list
|
|
ENABLED_ANY=1; ok "aktualisiert: sources.list"
|
|
fi
|
|
fi
|
|
[[ $ENABLED_ANY -eq 0 ]] && ok "non-free schon aktiv"
|
|
apt-get update -qq # immer neu einlesen, damit der Kandidat sicher da ist
|
|
|
|
# ── 2b. (opt-in) Treiber-Upgrade ueber NVIDIAs Paketquelle fuer Debian 13 ──
|
|
# Debian (auch trixie-backports) hat hoechstens 550 = CUDA 12.4. Die aktuellen
|
|
# llama.cpp-/llama-swap-Images brauchen CUDA 12.8/12.9 → mit 550 meldet
|
|
# llama.cpp "failed to initialize CUDA … forward compatibility …", findet keine
|
|
# Karte und rechnet STILL auf der CPU ("ready" meldet es trotzdem).
|
|
# NVIDIAs Quelle hat die Pakete unter denselben Namen, nur neuer — apt
|
|
# aktualisiert an Ort und Stelle. Alte Debian-Teilpakete (nvidia-driver-bin,
|
|
# nvidia-alternative, …) sind in den neuen aufgegangen und werden entfernt.
|
|
# Das Container-Toolkit bleibt unberuehrt — ohne es saehe kein Container die GPU,
|
|
# darum bricht das Script ab, falls apt es anfassen wollte.
|
|
# NUR mit --upgrade-driver, damit ein laufendes Setup nicht ungewollt angefasst wird.
|
|
NV_REPO="https://developer.download.nvidia.com/compute/cuda/repos/debian13/x86_64"
|
|
MIN_DRIVER_MAJOR=575 # CUDA 12.9 braucht mindestens Treiber 575
|
|
|
|
# Nachbereitung nach dem Wechsel auf NVIDIAs Pakete. Zwei Stolperfallen, die
|
|
# erst bei der echten Installation sichtbar wurden (nicht in apt -s):
|
|
# 1. NVIDIAs Paket "nvidia-smi" ist nur noch ein leeres Doku-Paket — das
|
|
# Programm (und Bibliotheken, die das Container-Toolkit braucht) steckt in
|
|
# "nvidia-driver-cuda". Ohne: kein nvidia-smi, Container ohne GPU.
|
|
# 2. /etc/modprobe.d/nvidia.conf (sperrt den freien nouveau-Treiber) war
|
|
# vorher ein Verweis ueber das Alternativen-System. Die entfernten
|
|
# Altpakete nehmen ihn mit, dpkg legt die neue Datei nur als .dpkg-new ab.
|
|
# Ohne Sperre laedt nach dem Reboot nouveau statt nvidia.
|
|
# Idempotent — repariert auch eine Box, die schon auf dem neuen Treiber ist.
|
|
nv_postfix() {
|
|
if ! command -v nvidia-smi >/dev/null 2>&1 && apt-cache show nvidia-driver-cuda >/dev/null 2>&1; then
|
|
warn "nvidia-smi fehlt — installiere nvidia-driver-cuda (enthaelt es)"
|
|
apt-get install -y nvidia-driver-cuda
|
|
fi
|
|
find /etc/modprobe.d -maxdepth 1 -name 'nvidia*.conf' -xtype l -print -delete 2>/dev/null \
|
|
| sed 's/^/ toter Verweis entfernt: /' || true
|
|
if [[ ! -e /etc/modprobe.d/nvidia.conf && -e /etc/modprobe.d/nvidia.conf.dpkg-new ]]; then
|
|
mv /etc/modprobe.d/nvidia.conf.dpkg-new /etc/modprobe.d/nvidia.conf
|
|
ok "/etc/modprobe.d/nvidia.conf aktiviert (sperrt nouveau)"
|
|
NV_INITRAMFS=1
|
|
fi
|
|
if ! grep -rqs "^blacklist nouveau" /etc/modprobe.d /usr/lib/modprobe.d /lib/modprobe.d; then
|
|
mkdir -p /etc/modprobe.d
|
|
if printf 'blacklist nouveau\nblacklist nova-core\n' > /etc/modprobe.d/aria-blacklist-nouveau.conf; then
|
|
ok "nouveau gesperrt (/etc/modprobe.d/aria-blacklist-nouveau.conf)"
|
|
NV_INITRAMFS=1
|
|
else
|
|
warn "nouveau-Sperre konnte nicht geschrieben werden — nach dem Reboot laedt evtl. nouveau statt nvidia"
|
|
fi
|
|
fi
|
|
if [[ "${NV_INITRAMFS:-0}" -eq 1 ]] || lsmod | grep -q '^nouveau'; then
|
|
if update-initramfs -u -k all >/dev/null 2>&1; then
|
|
ok "initramfs neu gebaut (Sperre greift schon beim Booten)"
|
|
else
|
|
warn "update-initramfs fehlgeschlagen — bitte von Hand: update-initramfs -u -k all"
|
|
fi
|
|
NV_NEED_REBOOT=1
|
|
fi
|
|
}
|
|
if [[ "$DO_UPGRADE_DRIVER" -eq 1 ]]; then
|
|
step "NVIDIA-Treiber-Upgrade (NVIDIAs Paketquelle fuer Debian 13)"
|
|
CUR="$(nvidia-smi --query-gpu=driver_version --format=csv,noheader 2>/dev/null | head -1 || true)"
|
|
if [[ -z "$CUR" ]]; then CUR="$(dpkg-query -W -f='${Version}' nvidia-driver 2>/dev/null || true)"; fi
|
|
CUR_MAJOR="${CUR%%.*}"
|
|
if [[ "$CUR_MAJOR" =~ ^[0-9]+$ && "$CUR_MAJOR" -ge "$MIN_DRIVER_MAJOR" ]]; then
|
|
ok "Treiber ${CUR} ist neu genug (>= ${MIN_DRIVER_MAJOR})"
|
|
nv_postfix
|
|
if lsmod | grep -q '^nouveau' || ! nvidia-smi >/dev/null 2>&1; then
|
|
echo
|
|
echo -e "${c_y}==> REBOOT noetig (nouveau ist noch geladen / Treiber noch nicht aktiv):${c_0}"
|
|
echo -e "${c_y} sudo reboot → danach: nvidia-smi und cd xtts && docker compose up -d${c_0}"
|
|
exit 0
|
|
fi
|
|
ok "nvidia-smi laeuft, nouveau nicht geladen — alles in Ordnung"
|
|
else
|
|
ok "aktuell: ${CUR:-kein Treiber} — Ziel: >= ${MIN_DRIVER_MAJOR}"
|
|
KEYRING_NEW=0
|
|
if ! dpkg -s cuda-keyring >/dev/null 2>&1; then
|
|
curl -fsSL "$NV_REPO/cuda-keyring_1.1-1_all.deb" -o /tmp/cuda-keyring.deb \
|
|
|| die "NVIDIA-Paketquelle nicht erreichbar ($NV_REPO)"
|
|
dpkg -i /tmp/cuda-keyring.deb >/dev/null && KEYRING_NEW=1
|
|
ok "NVIDIA-Paketquelle eingetragen"
|
|
fi
|
|
undo_keyring() { [[ "$KEYRING_NEW" -eq 1 ]] && dpkg -r cuda-keyring >/dev/null 2>&1 && apt-get update -qq || true; }
|
|
apt-get update -qq
|
|
apt-get install -y -qq linux-headers-amd64 >/dev/null 2>&1 || true
|
|
apt-get install -y -qq "linux-headers-$(uname -r)" >/dev/null 2>&1 || true
|
|
|
|
NV_PKGS="nvidia-driver nvidia-kernel-dkms libcuda1"
|
|
# Bei NVIDIA steckt nvidia-smi in nvidia-driver-cuda (das Paket "nvidia-smi"
|
|
# ist dort leer). Fallback fuer eine Quelle, die es anders schneidet.
|
|
if apt-cache show nvidia-driver-cuda >/dev/null 2>&1; then
|
|
NV_PKGS="$NV_PKGS nvidia-driver-cuda"
|
|
else
|
|
NV_PKGS="$NV_PKGS nvidia-smi"
|
|
fi
|
|
for p in nvidia-persistenced nvidia-modprobe; do
|
|
if dpkg -s "$p" >/dev/null 2>&1; then NV_PKGS="$NV_PKGS $p"; fi
|
|
done
|
|
|
|
# Erst durchspielen — aendert nichts.
|
|
if ! SIM="$(apt-get -s install -y $NV_PKGS 2>&1)"; then
|
|
echo "$SIM" | grep -E "^E:|Kollidiert|Hängt ab|Depends|Conflicts" | head -15 || true
|
|
undo_keyring
|
|
die "apt findet keinen sauberen Weg — NICHTS geaendert (Quelle wieder entfernt)."
|
|
fi
|
|
if echo "$SIM" | grep -qE '^(Remv|Inst) (nvidia-container|libnvidia-container)'; then
|
|
undo_keyring
|
|
die "Das Upgrade wuerde das NVIDIA-Container-Toolkit anfassen — abgebrochen, NICHTS geaendert."
|
|
fi
|
|
NEWV="$(echo "$SIM" | sed -nE 's/^Inst nvidia-driver (\[[^]]*\] )?\(([^ ]+).*/\2/p' | head -1 || true)"
|
|
echo
|
|
echo -e " Plan: Treiber ${CUR:-?} → ${c_g}${NEWV:-?}${c_0}"
|
|
echo "$SIM" | grep -E "^[0-9]+ (aktualisiert|upgraded)" | head -1 | sed 's/^/ /' || true
|
|
REMV="$(echo "$SIM" | sed -nE 's/^Remv ([^ ]+).*/\1/p' | paste -sd' ' || true)"
|
|
if [[ -n "$REMV" ]]; then echo " entfernt (in den neuen Paketen aufgegangen): $REMV"; fi
|
|
echo " Container-Toolkit: bleibt unberuehrt"
|
|
echo " Danach ist ein REBOOT noetig (neues Kernelmodul)."
|
|
if [[ "$ASSUME_YES" -ne 1 && -t 0 ]]; then
|
|
read -r -p " Jetzt ausfuehren? [j/N] " ans
|
|
if [[ ! "$ans" =~ ^[jJyY] ]]; then
|
|
undo_keyring
|
|
die "Abgebrochen — NICHTS geaendert."
|
|
fi
|
|
fi
|
|
|
|
apt-get install -y $NV_PKGS
|
|
dkms autoinstall >/dev/null 2>&1 || true
|
|
nv_postfix
|
|
GOT="$(dpkg-query -W -f='${Version}' nvidia-driver 2>/dev/null || echo '?')"
|
|
[[ "${GOT%%.*}" =~ ^[0-9]+$ && "${GOT%%.*}" -ge "$MIN_DRIVER_MAJOR" ]] \
|
|
|| die "Installiert ist ${GOT} — erwartet >= ${MIN_DRIVER_MAJOR}. Bitte Ausgabe oben pruefen."
|
|
# -F: der Kernelname enthaelt "+" — als Regex gelesen passte er nie.
|
|
# Geprueft wird jeder installierte Kernel (apt kann gerade einen neueren
|
|
# mitgebracht haben, der beim Reboot startet).
|
|
for k in /lib/modules/*/; do
|
|
k="$(basename "$k")"
|
|
if [[ -d "/usr/src/linux-headers-$k" ]]; then
|
|
if dkms status 2>/dev/null | grep -F "$k" | grep -q installed; then
|
|
ok "Kernelmodul fuer $k gebaut"
|
|
else
|
|
warn "Kernelmodul fuer $k NICHT gebaut — vor dem Reboot: dkms autoinstall -k $k"
|
|
fi
|
|
fi
|
|
done
|
|
command -v nvidia-smi >/dev/null 2>&1 || warn "nvidia-smi fehlt nach der Installation — bitte melden"
|
|
ok "nvidia-driver ${GOT} installiert"
|
|
echo
|
|
echo -e "${c_y}==> REBOOT noetig, damit der neue Treiber laedt:${c_0}"
|
|
echo -e "${c_y} sudo reboot${c_0}"
|
|
echo -e "${c_y} danach: nvidia-smi (zeigt ${GOT%%-*} und eine CUDA-Version >= 12.9)${c_0}"
|
|
echo -e "${c_y} und: cd xtts && docker compose up -d${c_0}"
|
|
exit 0
|
|
fi
|
|
fi
|
|
|
|
# ── 2c. Docker wartet beim Booten auf DNS ──
|
|
# Debian traegt die Netzwerkkarte als "allow-hotplug" ein — darauf wartet
|
|
# network-online.target NICHT. Docker startet die Container dann, bevor DHCP den
|
|
# DNS-Server geliefert hat ("DNS resolver has no external nameservers"), und die
|
|
# Container behalten diesen leeren Stand: kein RVS, keine Verbindung, bis man
|
|
# sie neu erzeugt. Passiert bei jedem Reboot.
|
|
# Abhilfe ohne die Netzkonfiguration anzufassen: Docker wartet vor dem Start bis
|
|
# zu 90 s, bis /etc/resolv.conf einen Nameserver hat.
|
|
step "Docker wartet beim Booten auf DNS"
|
|
DROPIN=/etc/systemd/system/docker.service.d/aria-wait-dns.conf
|
|
if [[ -f "$DROPIN" ]]; then
|
|
ok "schon eingerichtet ($DROPIN)"
|
|
else
|
|
mkdir -p "$(dirname "$DROPIN")"
|
|
cat > "$DROPIN" <<'EOF'
|
|
# ARIA bootstrap.sh: Container erst starten, wenn DNS da ist (sonst merken sie
|
|
# sich "keine Nameserver" und erreichen den RVS nie). Siehe xtts/bootstrap.sh.
|
|
[Unit]
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
[Service]
|
|
ExecStartPre=/bin/sh -c 'for i in $(seq 1 90); do grep -q "^nameserver" /etc/resolv.conf && exit 0; sleep 1; done; echo "kein DNS nach 90 s — starte trotzdem"; exit 0'
|
|
EOF
|
|
systemctl daemon-reload
|
|
ok "eingerichtet — greift ab dem naechsten Boot"
|
|
fi
|
|
|
|
# ── 3. NVIDIA-Treiber ──
|
|
step "NVIDIA-Treiber"
|
|
if nvidia-smi >/dev/null 2>&1; then
|
|
DRV="$(nvidia-smi --query-gpu=driver_version --format=csv,noheader 2>/dev/null | head -1 || true)"
|
|
ok "Treiber ${DRV} aktiv: $(nvidia-smi --query-gpu=name --format=csv,noheader | paste -sd', ')"
|
|
DRIVER_ACTIVE=1
|
|
# Fuer das lokale LLM zu alt? Dann laeuft es still auf der CPU — das soll man
|
|
# hier sehen, nicht erst an einer leeren Karte in nvidia-smi.
|
|
PROFILES="$(grep -E '^COMPOSE_PROFILES=' "$XTTS_DIR/.env" 2>/dev/null | cut -d= -f2- || true)"
|
|
if [[ "${DRV%%.*}" =~ ^[0-9]+$ && "${DRV%%.*}" -lt "$MIN_DRIVER_MAJOR" && ( -z "$PROFILES" || "$PROFILES" == *llm* ) ]]; then
|
|
warn "Treiber ${DRV} ist zu alt fuer das lokale LLM (braucht >= ${MIN_DRIVER_MAJOR})."
|
|
warn " Folge: llama.cpp findet keine Karte und rechnet auf der CPU."
|
|
warn " Abhilfe: sudo ./bootstrap.sh --upgrade-driver (zeigt erst den Plan, fragt nach)"
|
|
fi
|
|
else
|
|
if dpkg -l | grep -q '^ii nvidia-driver '; then
|
|
warn "Treiber installiert, aber nvidia-smi antwortet nicht → REBOOT noetig."
|
|
DRIVER_ACTIVE=0
|
|
else
|
|
# KEIN separater Kandidaten-Check — die apt-cache-Ausgabe ist locale-/pipe-
|
|
# fragil (hat faelschlich "kein Kandidat" gemeldet). Der Install IST der Test:
|
|
# direkt installieren; schlaegt er fehl, einmal volles apt-get update + Retry,
|
|
# dann erst mit Diagnose abbrechen.
|
|
# Kernel-Header ZUERST — sonst ueberspringt DKMS den Modulbau ("No kernel
|
|
# headers were found") und nvidia-smi kann spaeter nicht mit dem Treiber reden.
|
|
warn "Kernel-Header + nvidia-driver installieren (DKMS-Build, dauert)…"
|
|
apt-get install -y linux-headers-amd64 || true
|
|
apt-get install -y "linux-headers-$(uname -r)" || true
|
|
if ! apt-get install -y nvidia-driver firmware-misc-nonfree; then
|
|
warn "Install fehlgeschlagen — volles 'apt-get update' + zweiter Versuch…"
|
|
apt-get update
|
|
if ! apt-get install -y nvidia-driver firmware-misc-nonfree; then
|
|
echo
|
|
warn "nvidia-driver liess sich nicht installieren. Aktive Quellen:"
|
|
grep -rhE '^[Cc]omponents:' /etc/apt/sources.list.d/*.sources 2>/dev/null | sed 's/^/ /' || true
|
|
grep -E '^deb ' /etc/apt/sources.list 2>/dev/null | sed 's/^/ /' || true
|
|
die "Pruefe 'apt-cache policy nvidia-driver' + Netz/non-free."
|
|
fi
|
|
fi
|
|
# Falls nvidia-kernel-dkms schon (ohne Header) installiert war: Modul jetzt bauen.
|
|
dkms autoinstall >/dev/null 2>&1 || true
|
|
ok "nvidia-driver + Kernel-Modul installiert"
|
|
DRIVER_ACTIVE=0
|
|
fi
|
|
fi
|
|
|
|
# ── 4. Docker Engine + Compose-Plugin ──
|
|
step "Docker"
|
|
if command -v docker >/dev/null 2>&1; then
|
|
ok "Docker vorhanden: $(docker --version)"
|
|
else
|
|
warn "Installiere Docker (offizielles get.docker.com)…"
|
|
curl -fsSL https://get.docker.com | sh >/dev/null
|
|
systemctl enable --now docker >/dev/null 2>&1 || true
|
|
ok "Docker installiert: $(docker --version)"
|
|
fi
|
|
if docker compose version >/dev/null 2>&1; then
|
|
ok "Compose-Plugin: $(docker compose version | head -1)"
|
|
else
|
|
warn "Compose-Plugin fehlt — installiere docker-compose-plugin…"
|
|
apt-get install -y -qq docker-compose-plugin >/dev/null || \
|
|
warn "Konnte docker-compose-plugin nicht via apt holen — get.docker.com bringt es normalerweise mit."
|
|
fi
|
|
|
|
# ── 5. NVIDIA Container Toolkit ──
|
|
step "NVIDIA Container Toolkit"
|
|
NCT_LIST="/etc/apt/sources.list.d/nvidia-container-toolkit.list"
|
|
NCT_KEY="/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg"
|
|
if ! dpkg -l | grep -q '^ii nvidia-container-toolkit '; then
|
|
[[ -f "$NCT_KEY" ]] || curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey \
|
|
| gpg --dearmor -o "$NCT_KEY"
|
|
if [[ ! -f "$NCT_LIST" ]]; then
|
|
curl -fsSL https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list \
|
|
| sed "s#deb https://#deb [signed-by=${NCT_KEY}] https://#g" > "$NCT_LIST"
|
|
fi
|
|
apt-get update -qq
|
|
apt-get install -y -qq nvidia-container-toolkit >/dev/null
|
|
ok "nvidia-container-toolkit installiert"
|
|
else
|
|
ok "nvidia-container-toolkit vorhanden"
|
|
fi
|
|
# Docker-Runtime auf NVIDIA konfigurieren (idempotent)
|
|
if ! grep -q '"nvidia"' /etc/docker/daemon.json 2>/dev/null; then
|
|
nvidia-ctk runtime configure --runtime=docker >/dev/null
|
|
systemctl restart docker
|
|
ok "Docker-Runtime auf NVIDIA konfiguriert + Docker neugestartet"
|
|
else
|
|
ok "Docker-Runtime bereits NVIDIA-konfiguriert"
|
|
fi
|
|
|
|
# ── 6. xtts/.env vorbereiten ──
|
|
step "xtts/.env"
|
|
if [[ -f "$XTTS_DIR/.env" ]]; then
|
|
ok ".env existiert bereits (unangetastet)"
|
|
else
|
|
cp "$XTTS_DIR/.env.example" "$XTTS_DIR/.env"
|
|
ok ".env aus .env.example erstellt"
|
|
fi
|
|
if [[ -n "$RVS_TOKEN_ARG" ]]; then
|
|
sed -i -E "s#^RVS_TOKEN=.*#RVS_TOKEN=${RVS_TOKEN_ARG}#" "$XTTS_DIR/.env"
|
|
ok "RVS_TOKEN eingetragen"
|
|
fi
|
|
if [[ -n "$RVS_HOST_ARG" ]]; then
|
|
sed -i -E "s#^RVS_HOST=.*#RVS_HOST=${RVS_HOST_ARG}#" "$XTTS_DIR/.env"
|
|
ok "RVS_HOST=${RVS_HOST_ARG} eingetragen"
|
|
fi
|
|
if grep -q '^RVS_TOKEN=dein_token_hier' "$XTTS_DIR/.env"; then
|
|
warn "RVS_TOKEN ist noch der Platzhalter — vor dem Start setzen:"
|
|
warn " nano $XTTS_DIR/.env (oder: sudo ./bootstrap.sh --token <TOKEN>)"
|
|
fi
|
|
warn "Stimm-Daten (nicht in git): falls von der alten Box noch vorhanden, xtts/voice-id/"
|
|
warn " + xtts/voices/ herkopieren. Sonst egal — in der App neu anlegen:"
|
|
warn " Sprache neu enrollen (Speaker-ID, sonst fail-open) + F5-Referenz neu hochladen."
|
|
|
|
# ── 7. GPU-im-Container verifizieren ──
|
|
step "GPU-im-Container Test"
|
|
if [[ "${DRIVER_ACTIVE:-0}" -eq 1 ]]; then
|
|
if docker run --rm --gpus all nvidia/cuda:12.4.0-base-ubuntu22.04 nvidia-smi >/dev/null 2>&1; then
|
|
ok "Docker sieht die GPU — KI-Box ist einsatzbereit."
|
|
GPU_READY=1
|
|
else
|
|
warn "Host-Treiber ok, aber Container sieht die GPU nicht — Toolkit/Runtime pruefen."
|
|
GPU_READY=0
|
|
fi
|
|
else
|
|
warn "Treiber noch nicht aktiv → Test uebersprungen."
|
|
echo
|
|
echo -e "${c_y}==> REBOOT noetig, dann Script erneut ausfuehren:${c_0}"
|
|
echo -e "${c_y} sudo reboot && (nach dem Boot) sudo ./bootstrap.sh${c_0}"
|
|
exit 0
|
|
fi
|
|
|
|
# ── 8. Optional: xtts-Stack hochziehen ──
|
|
if [[ $DO_UP -eq 1 && "${GPU_READY:-0}" -eq 1 ]]; then
|
|
step "xtts-Stack starten (Default-Profil: Whisper + F5 + LLM — OHNE voxtral)"
|
|
warn "Erster Start laedt Modelle (mehrere GB via HuggingFace) — kann dauern."
|
|
( cd "$XTTS_DIR" && docker compose up -d --build )
|
|
ok "Stack laeuft. Logs: docker logs -f aria-whisper-bridge"
|
|
echo
|
|
echo " voxtral (STT via Voxtral) braucht >=16 GB VRAM → erst mit der 24-GB-Karte:"
|
|
echo " cd $XTTS_DIR && docker compose stop whisper-bridge && docker compose --profile voxtral up -d --build"
|
|
fi
|
|
|
|
# ── Abschluss ──
|
|
echo
|
|
echo -e "${c_g}=== Fertig. KI-Box startklar. ===${c_0}"
|
|
if [[ $DO_UP -eq 0 ]]; then
|
|
echo "Naechster Schritt — Stack starten:"
|
|
echo " cd $XTTS_DIR && docker compose up -d --build"
|
|
echo "oder direkt: sudo ./bootstrap.sh --up"
|
|
fi
|