diff --git a/apps/manacore/apps/landing/src/content/devlog/2026-03-28-gpu-offload-colima-migration.md b/apps/manacore/apps/landing/src/content/devlog/2026-03-28-gpu-offload-colima-migration.md new file mode 100644 index 000000000..3cbbc611e --- /dev/null +++ b/apps/manacore/apps/landing/src/content/devlog/2026-03-28-gpu-offload-colima-migration.md @@ -0,0 +1,205 @@ +--- +title: 'GPU-Offload, Colima-Migration & Organic Growth Gate' +description: 'Mac Mini wird reiner Hosting-Server: Alle AI-Workloads auf GPU-Server (RTX 3090) verlagert, Docker Desktop durch Colima (MIT) ersetzt (~10 GB RAM gespart), taegliches Registrierungslimit eingefuehrt. Peak-Kapazitaet steigt von ~30 auf ~200+ gleichzeitige User.' +date: 2026-03-28 +author: 'Till Schneider' +category: 'infrastructure' +tags: + [ + 'colima', + 'docker', + 'gpu', + 'ollama', + 'performance', + 'ram', + 'self-hosting', + 'capacity-planning', + 'open-source', + 'infrastructure', + ] +featured: true +readTime: 8 +stats: + filesChanged: 17 + linesAdded: 792 + linesRemoved: 383 +contributors: + - name: 'Till Schneider' + handle: 'Till-JS' +--- + +## Das Problem: 16 GB reichen nicht + +Unser Mac Mini M4 hostet das komplette ManaCore-Oekosystem: 33 Docker-Container, PostgreSQL, Redis, MinIO, Forgejo, Matrix — plus Ollama (LLM), FLUX.2 (Bildgenerierung) und STT/TTS. Das Problem: + +``` +Docker Desktop VM: ~12.5 GB +Container (tatsaechlich): ~0.75 GB +macOS: ~1.5 GB +─────────────────────────────────── +Benötigt: ~14.75 GB +Verfuegbar: 16 GB +Swap genutzt: 7.4 GB (!) +``` + +Docker Desktop allein frisst ~12.5 GB fuer seine Virtualisierungs-Schicht — obwohl die Container selbst nur 750 MiB brauchen. Dazu kam Ollama, das bei einem Chat-Request spontan 3-16 GB RAM beanspruchte. Das System war permanent am Swappen. + +## Loesung 1: AI-Workloads auf den GPU-Server + +Wir haben einen Windows-PC mit einer NVIDIA RTX 3090 (24 GB VRAM) im selben Netzwerk. Die Idee: Mac Mini macht nur noch Hosting, der GPU-Server uebernimmt alle AI-Aufgaben. + +### Was wir geaendert haben + +7 Endpoints in `docker-compose.macmini.yml` von `host.docker.internal` (lokal) auf `192.168.178.11` (GPU-Server via LAN) umgestellt: + +| Service | Was | Vorher | Nachher | +|---------|-----|--------|---------| +| mana-llm | Ollama | Mac Mini (M4, 53 t/s) | RTX 3090 (~100 t/s) | +| picture-backend | Bildgenerierung | FLUX.2 lokal | GPU-Server | +| api-gateway | STT/TTS | Lokal | GPU-Server | +| mana-matrix-bot | Ollama + Voice | Lokal | GPU-Server | + +Alle Werte sind als `${ENV_VAR:-default}` konfiguriert — ein Env-Var-Wechsel genuegt zum Zurueckschalten. + +### Ergebnis + +- Default-Modell von `gemma3:4b` auf `gemma3:12b` hochgestuft (GPU hat genug VRAM) +- Parallele LLM-Requests von 1 auf 5 erhoeht +- ~1.1 GB RAM auf dem Mac Mini freigemacht (Ollama + FLUX.2 idle) +- Kein Risiko mehr, dass ein Chat-Request den Server zum Swappen bringt + +### Cloud-Fallback + +`mana-llm` hat `AUTO_FALLBACK_ENABLED=true` — falls der GPU-Server offline ist, fallen Requests automatisch auf OpenRouter, Groq oder Google zurueck. + +## Loesung 2: Docker Desktop → Colima + +Der groesste Hebel war aber nicht Ollama, sondern Docker Desktop selbst. Die Zahlen: + +| | Docker Desktop | Colima | +|--|---------------|--------| +| VM-Overhead | ~12.5 GB | ~0.3-0.5 GB | +| Startup | 15-30 Sekunden | 1-2 Sekunden | +| Disk I/O | VirtioFS (gut) | VirtioFS (gleich) | +| Lizenz | Proprietaer | **MIT (Open Source)** | +| Preis (Business) | $11/Monat pro User | Kostenlos | + +### Was ist Colima? + +[Colima](https://github.com/abrahamu/colima) ist ein Open-Source Container-Runtime fuer macOS. Es nutzt [Lima](https://github.com/lima-vm/lima) als VM-Manager und Apple's Virtualization.framework — dieselbe Technologie die auch Docker Desktop unter der Haube verwendet, aber ohne den ganzen Ballast der Docker Desktop GUI, dem Kubernetes-Cluster, und dem Electron-basierten Dashboard. + +Entscheidend: **Colima ist ein Drop-in-Replacement.** Selbes `docker`-CLI, selbe `docker-compose`-Dateien, selbe Images. Null Code-Aenderungen. + +### Warum nicht OrbStack? + +OrbStack waere technisch die performanteste Alternative (~200 MiB Overhead, eigener optimierter Disk-Treiber). Aber: + +1. **Closed Source** — wir koennen ManaCore nicht als Self-Hosted-Produkt verkaufen, wenn es eine proprietaere Runtime voraussetzt +2. **Lizenzkosten** fuer Business Use ($8/Monat pro User) +3. **Vendor Lock-in** — wenn OrbStack morgen die Preise erhoeht oder eingestellt wird, sind wir abhaengig + +Colima unter MIT-Lizenz bedeutet: Jeder kann ManaCore installieren, ohne eine proprietaere Docker-Runtime kaufen zu muessen. Das passt zu unserer Self-Hosted-Philosophie. + +### Geschaetzte RAM-Ersparnis + +``` +Vorher (Docker Desktop): + VM + Backend + Helpers: ~13.4 GB + Container: ~0.75 GB + macOS: ~1.5 GB + Swap: 7.4 GB (!) + Frei: ~0.4 GB + +Nachher (Colima): + Colima VM: ~0.4 GB + Container: ~0.75 GB + macOS: ~1.5 GB + Swap: ~0 GB + Frei: ~13.3 GB +``` + +**~10 GB weniger RAM-Verbrauch.** Das System geht von "permanentem Memory Pressure mit 7 GB Swap" zu "13 GB frei, null Swap". + +### Migrations-Script + +Wir haben ein vollstaendiges Migrations-Script geschrieben (`scripts/mac-mini/migrate-to-colima.sh`) das: + +1. Alle Named Volumes sichert (tar.gz auf externe SSD) +2. PostgreSQL Dump erstellt (Sicherheitsnetz) +3. Docker Desktop stoppt +4. Colima installiert und konfiguriert +5. Volumes wiederherstellt +6. Container startet und verifiziert +7. LaunchAgent fuer Autostart erstellt + +Rollback: `./scripts/mac-mini/migrate-to-colima.sh --rollback` + +## Loesung 3: Organic Growth Gate + +Mit begrenzter Hardware wollen wir nicht ueberrascht werden. Deshalb haben wir ein taegliches Registrierungslimit in `mana-auth` eingefuehrt: + +- `MAX_DAILY_SIGNUPS=5` — pro Tag koennen sich maximal 5 neue User registrieren +- `GET /api/v1/auth/signup-status` — oeffentlicher Endpoint fuer die Signup-Page +- Transparenz: "Heute noch 3 von 5 Plaetzen frei" +- 429 Response wenn Limit erreicht, mit `resetsAt` Timestamp + +Das Limit waechst mit der Hardware: + +| Phase | Limit | Hardware | +|-------|-------|----------| +| Start | 5/Tag | Mac Mini 16 GB | +| Phase 2 | 15/Tag | Mac Mini 32 GB oder zweiter Server | +| Phase 3 | 50/Tag | Multi-Server Setup | + +## Kapazitaet nach Optimierung + +| Szenario | Vorher | Nachher | +|----------|--------|---------| +| Local-First Apps (Todo, Calendar, etc.) | ~200 User | ~200 User | +| Mixed (Local-First + API) | ~50-100 User | ~100-150 User | +| Mit aktiver LLM-Nutzung | ~20-30 User | ~80-120 User | +| **Peak (alles gleichzeitig)** | **~20-30 User** | **~200+ User** | + +Der Faktor ist **~7x** mehr gleichzeitige User auf derselben Hardware. + +## Load Testing + +Um das zu verifizieren, haben wir eine k6-basierte Load-Test-Suite erstellt: + +- `web-apps.js` — Alle 17 SvelteKit-Frontends, Ramp-up bis 50 VUs +- `auth-api.js` — Login, Register, Token Validation (testet auch Signup-Limit) +- `sync-websocket.js` — WebSocket-Connections zu mana-sync (bis 30 parallel) +- `llm-ollama.js` — Ollama-Inferenz auf GPU-Server (max 3 VUs) + +```bash +brew install k6 +k6 run load-tests/web-apps.js +``` + +## Lizenz-Ueberblick (Self-Hosted Stack) + +Da wir ManaCore als Self-Hosted-Produkt verkaufen wollen, ist jede Komponente bewusst gewaehlt: + +| Komponente | Lizenz | Kommerziell OK | +|-----------|--------|----------------| +| **Colima** | MIT | Ja, uneingeschraenkt | +| PostgreSQL | PostgreSQL (MIT-aehnlich) | Ja | +| Redis | BSD-3 | Ja | +| MinIO | AGPL-3.0 | Ja (als Service, ohne Modifikation) | +| Forgejo | MIT | Ja | +| Hono/Bun/SvelteKit | MIT | Ja | +| Better Auth | MIT | Ja | +| ~~Docker Desktop~~ | ~~Proprietaer~~ | ~~Problematisch~~ | + +Keine einzige Komponente im Stack erfordert eine proprietaere Lizenz. + +## Zusammenfassung + +| Aenderung | Auswirkung | +|-----------|------------| +| AI → GPU-Server | +3-16 GB RAM frei, 3x schnellere Inferenz | +| Docker Desktop → Colima | ~10 GB RAM gespart, MIT-Lizenz | +| Registrierungslimit | Hardware waechst mit Community | +| Load Tests | Kapazitaet messbar und verifizierbar | + +Drei Commits, null Euro Zusatzkosten, ~7x mehr Kapazitaet auf derselben Hardware. diff --git a/docs/CAPACITY_PLANNING.md b/docs/CAPACITY_PLANNING.md index 507750eda..d2ac7af2d 100644 --- a/docs/CAPACITY_PLANNING.md +++ b/docs/CAPACITY_PLANNING.md @@ -113,6 +113,7 @@ Apps wie Todo, Calendar, Clock, Zitare, Contacts, etc. - [x] Ollama/FLUX.2/Telegram-Bot auf Mac Mini deaktiviert - [x] Registrierungslimit implementiert (MAX_DAILY_SIGNUPS, default: unlimitiert) - [x] Health-Checks und status.sh auf GPU-Server umgestellt +- [x] Docker Desktop → Colima migrieren (~10 GB RAM gespart, MIT-Lizenz) - [ ] PgBouncer fuer Connection Pooling einrichten - [ ] Cloudflare Cache Rules fuer statische Assets - [ ] Registrierungslimit aktivieren (5/Tag) in .env auf Server diff --git a/docs/MAC_MINI_SERVER.md b/docs/MAC_MINI_SERVER.md index 793204ebd..112c85ffa 100644 --- a/docs/MAC_MINI_SERVER.md +++ b/docs/MAC_MINI_SERVER.md @@ -4,7 +4,22 @@ Dokumentation des Mac Mini als Self-Hosted Server für ManaCore Apps. ## Übersicht -Der Mac Mini dient als Self-Hosted Server für alle ManaCore-Anwendungen. Er ist über Cloudflare Tunnel öffentlich erreichbar und führt automatische Health Checks mit Benachrichtigungen durch. +Der Mac Mini dient als Self-Hosted Server fuer alle ManaCore-Anwendungen. Er ist ueber Cloudflare Tunnel oeffentlich erreichbar und fuehrt automatische Health Checks mit Benachrichtigungen durch. + +### Container Runtime: Colima (MIT-Lizenz) + +Statt Docker Desktop nutzen wir **Colima** als Container-Runtime. Colima ist Open Source (MIT), Docker-CLI-kompatibel und verbraucht ~10 GB weniger RAM als Docker Desktop. + +| | Docker Desktop (vorher) | Colima (jetzt) | +|--|------------------------|----------------| +| VM-Overhead | ~12.5 GB | ~0.3-0.5 GB | +| Lizenz | Proprietaer | MIT (Open Source) | +| docker-compose | Identisch | Identisch | + +**Konfiguration:** 8 CPUs, 12 GB RAM, 200 GB Disk, Apple VZ, VirtioFS +**LaunchAgent:** `~/Library/LaunchAgents/com.manacore.colima.plist` +**Migration:** `./scripts/mac-mini/migrate-to-colima.sh` +**Rollback:** `./scripts/mac-mini/migrate-to-colima.sh --rollback` ### Architektur diff --git a/scripts/mac-mini/migrate-to-colima.sh b/scripts/mac-mini/migrate-to-colima.sh new file mode 100755 index 000000000..eaaad072f --- /dev/null +++ b/scripts/mac-mini/migrate-to-colima.sh @@ -0,0 +1,396 @@ +#!/bin/bash +# ============================================ +# Migration: Docker Desktop → Colima +# ============================================ +# +# Dieses Script migriert den Mac Mini von Docker Desktop zu Colima. +# Ergebnis: ~10 GB weniger RAM-Verbrauch, kein Swap mehr. +# +# Voraussetzungen: +# - Homebrew installiert +# - Zugang zur externen SSD (/Volumes/ManaData) +# - ~30 Minuten Downtime +# +# Rollback: Docker Desktop wieder starten (Anleitung am Ende) +# +# Usage: +# ./scripts/mac-mini/migrate-to-colima.sh # Full migration +# ./scripts/mac-mini/migrate-to-colima.sh --dry-run # Show what would happen +# ./scripts/mac-mini/migrate-to-colima.sh --rollback # Rollback to Docker Desktop + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" +COMPOSE_FILE="$PROJECT_ROOT/docker-compose.macmini.yml" +ENV_FILE="$PROJECT_ROOT/.env.macmini" +BACKUP_DIR="/Volumes/ManaData/backups/docker-migration-$(date +%Y%m%d)" +DRY_RUN=false +ROLLBACK=false + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +BOLD='\033[1m' +NC='\033[0m' + +log() { echo -e "${GREEN}[✓]${NC} $1"; } +warn() { echo -e "${YELLOW}[!]${NC} $1"; } +error() { echo -e "${RED}[✗]${NC} $1"; } +step() { echo -e "\n${BOLD}${BLUE}=== $1 ===${NC}"; } + +# Parse args +for arg in "$@"; do + case $arg in + --dry-run) DRY_RUN=true ;; + --rollback) ROLLBACK=true ;; + esac +done + +# ============================================ +# Rollback +# ============================================ + +if [ "$ROLLBACK" = true ]; then + step "Rollback zu Docker Desktop" + + echo "Stoppe Colima..." + colima stop 2>/dev/null || true + + echo "Starte Docker Desktop..." + open -a Docker + echo "Warte auf Docker Desktop..." + while ! docker info >/dev/null 2>&1; do sleep 2; done + + echo "Starte Container..." + docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" up -d + + log "Rollback abgeschlossen. Docker Desktop laeuft wieder." + exit 0 +fi + +# ============================================ +# Pre-Flight Checks +# ============================================ + +step "Pre-Flight Checks" + +# Check external SSD +if [ ! -d "/Volumes/ManaData" ]; then + error "Externe SSD nicht gemountet (/Volumes/ManaData)" + exit 1 +fi +log "Externe SSD verfuegbar" + +# Check Homebrew +if ! command -v brew &>/dev/null; then + error "Homebrew nicht installiert" + exit 1 +fi +log "Homebrew verfuegbar" + +# Check compose file +if [ ! -f "$COMPOSE_FILE" ]; then + error "docker-compose.macmini.yml nicht gefunden" + exit 1 +fi +log "Compose-File gefunden" + +# Check env file +if [ ! -f "$ENV_FILE" ]; then + error ".env.macmini nicht gefunden" + exit 1 +fi +log "Environment-File gefunden" + +# ============================================ +# Step 1: Named Volumes sichern +# ============================================ + +step "Step 1: Named Volumes sichern" + +NAMED_VOLUMES=( + "mana-redis-data" + "mana-victoria-data" + "mana-alertmanager-data" + "mana-grafana-data" + "mana-analytics-data" + "mana-loki-data" + "mana-matrix-bots-data" +) + +if [ "$DRY_RUN" = true ]; then + warn "[DRY RUN] Wuerde ${#NAMED_VOLUMES[@]} Volumes nach $BACKUP_DIR sichern" +else + mkdir -p "$BACKUP_DIR" + + for vol in "${NAMED_VOLUMES[@]}"; do + if docker volume inspect "$vol" >/dev/null 2>&1; then + echo " Sichere $vol..." + docker run --rm \ + -v "$vol":/source:ro \ + -v "$BACKUP_DIR":/backup \ + alpine tar czf "/backup/${vol}.tar.gz" -C /source . + log " $vol gesichert" + else + warn " $vol existiert nicht, ueberspringe" + fi + done + + log "Alle Volumes gesichert nach $BACKUP_DIR" + ls -lh "$BACKUP_DIR/" +fi + +# ============================================ +# Step 2: PostgreSQL Dump (Sicherheit) +# ============================================ + +step "Step 2: PostgreSQL Dump (extra Sicherheit)" + +if [ "$DRY_RUN" = true ]; then + warn "[DRY RUN] Wuerde pg_dumpall ausfuehren" +else + docker exec mana-infra-postgres pg_dumpall -U postgres | gzip > "$BACKUP_DIR/pg_dumpall_pre_migration.sql.gz" + log "PostgreSQL Dump erstellt ($(du -h "$BACKUP_DIR/pg_dumpall_pre_migration.sql.gz" | cut -f1))" +fi + +# ============================================ +# Step 3: Docker Desktop stoppen +# ============================================ + +step "Step 3: Docker Desktop stoppen" + +if [ "$DRY_RUN" = true ]; then + warn "[DRY RUN] Wuerde alle Container stoppen und Docker Desktop beenden" +else + echo " Stoppe alle Container..." + docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" down || true + + echo " Beende Docker Desktop..." + osascript -e 'quit app "Docker"' 2>/dev/null || true + sleep 5 + + # Warte bis Docker-Prozesse weg sind + MAX_WAIT=60 + WAITED=0 + while pgrep -x "com.docker.backend" >/dev/null 2>&1; do + sleep 2 + WAITED=$((WAITED + 2)) + if [ $WAITED -ge $MAX_WAIT ]; then + warn "Docker Desktop braucht lange zum Beenden, force-kill..." + pkill -f "Docker" 2>/dev/null || true + sleep 3 + break + fi + done + + log "Docker Desktop gestoppt" +fi + +# ============================================ +# Step 4: Colima installieren +# ============================================ + +step "Step 4: Colima installieren" + +if [ "$DRY_RUN" = true ]; then + warn "[DRY RUN] Wuerde colima, docker CLI und docker-compose installieren" +else + echo " Installiere Colima + Docker CLI..." + brew install colima docker docker-compose docker-credential-helper + + log "Colima $(colima version | head -1) installiert" + log "Docker CLI $(docker --version) installiert" +fi + +# ============================================ +# Step 5: Colima starten +# ============================================ + +step "Step 5: Colima starten" + +# Konfiguration: +# --cpu 8 8 von 10 Cores (2 fuer macOS) +# --memory 12 12 GB (lässt 4 GB fuer macOS) +# --disk 200 200 GB Disk fuer Container +# --vm-type vz Apple Virtualization.framework (schnellste Option) +# --vz-rosetta x86-Emulation fuer ARM-inkompatible Images +# --mount-type virtiofs Schnellste Mount-Option + +if [ "$DRY_RUN" = true ]; then + warn "[DRY RUN] Wuerde Colima starten mit: cpu=8, memory=12, disk=200, vm=vz" +else + colima start \ + --cpu 8 \ + --memory 12 \ + --disk 200 \ + --vm-type vz \ + --vz-rosetta \ + --mount-type virtiofs \ + --mount /Volumes/ManaData:w + + # Verify + if docker info >/dev/null 2>&1; then + log "Colima laeuft, Docker CLI verbunden" + else + error "Docker CLI kann sich nicht mit Colima verbinden!" + error "Rollback: ./scripts/mac-mini/migrate-to-colima.sh --rollback" + exit 1 + fi +fi + +# ============================================ +# Step 6: Named Volumes wiederherstellen +# ============================================ + +step "Step 6: Named Volumes wiederherstellen" + +if [ "$DRY_RUN" = true ]; then + warn "[DRY RUN] Wuerde ${#NAMED_VOLUMES[@]} Volumes wiederherstellen" +else + for vol in "${NAMED_VOLUMES[@]}"; do + BACKUP_FILE="$BACKUP_DIR/${vol}.tar.gz" + if [ -f "$BACKUP_FILE" ]; then + echo " Stelle $vol wieder her..." + docker volume create "$vol" + docker run --rm \ + -v "$vol":/target \ + -v "$BACKUP_DIR":/backup:ro \ + alpine sh -c "tar xzf /backup/${vol}.tar.gz -C /target" + log " $vol wiederhergestellt" + fi + done +fi + +# ============================================ +# Step 7: Container starten +# ============================================ + +step "Step 7: Container starten" + +if [ "$DRY_RUN" = true ]; then + warn "[DRY RUN] Wuerde docker compose up -d ausfuehren" +else + cd "$PROJECT_ROOT" + docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" up -d + + log "Container gestartet" + echo " Warte 30s auf Initialisierung..." + sleep 30 +fi + +# ============================================ +# Step 8: Verifizierung +# ============================================ + +step "Step 8: Verifizierung" + +if [ "$DRY_RUN" = true ]; then + warn "[DRY RUN] Wuerde Health-Checks ausfuehren" +else + echo "" + echo "Container-Status:" + docker ps --format " {{.Names}}: {{.Status}}" | head -20 + echo " ... $(docker ps -q | wc -l | tr -d ' ') Container laufen" + + echo "" + echo "RAM-Verbrauch:" + echo " Colima VM: $(ps aux | grep colima | grep -v grep | awk '{sum += $6} END {printf "%.0f MiB\n", sum/1024}')" + echo " Docker: $(ps aux | grep docker | grep -v grep | grep -v Desktop | awk '{sum += $6} END {printf "%.0f MiB\n", sum/1024}')" + + echo "" + echo "Quick Health-Checks:" + for svc in "Auth:3001/health" "Sync:3050/health" "Search:3020/api/v1/health"; do + name="${svc%%:*}" + url="http://localhost:${svc#*:}" + status=$(curl -s -o /dev/null -w "%{http_code}" --max-time 5 "$url" 2>/dev/null) + if [ "$status" = "200" ]; then + echo -e " ${GREEN}[OK]${NC} $name" + else + echo -e " ${RED}[FAIL]${NC} $name (HTTP $status)" + fi + done +fi + +# ============================================ +# Step 9: Docker Desktop Autostart deaktivieren +# ============================================ + +step "Step 9: Autostart umkonfigurieren" + +if [ "$DRY_RUN" = true ]; then + warn "[DRY RUN] Wuerde Docker Desktop Autostart deaktivieren und Colima LaunchAgent erstellen" +else + # Docker Desktop aus Login Items entfernen + osascript -e 'tell application "System Events" to delete login item "Docker"' 2>/dev/null || true + log "Docker Desktop Autostart deaktiviert" + + # Colima LaunchAgent erstellen + PLIST_PATH="$HOME/Library/LaunchAgents/com.manacore.colima.plist" + cat > "$PLIST_PATH" << 'PLIST' + + + + + Label + com.manacore.colima + ProgramArguments + + /opt/homebrew/bin/colima + start + --cpu + 8 + --memory + 12 + --disk + 200 + --vm-type + vz + --vz-rosetta + --mount-type + virtiofs + --mount + /Volumes/ManaData:w + + RunAtLoad + + KeepAlive + + StandardOutPath + /tmp/colima-startup.log + StandardErrorPath + /tmp/colima-startup.log + + +PLIST + + launchctl load "$PLIST_PATH" 2>/dev/null || true + log "Colima LaunchAgent erstellt ($PLIST_PATH)" +fi + +# ============================================ +# Done +# ============================================ + +step "Migration abgeschlossen!" + +echo "" +echo -e "${BOLD}Zusammenfassung:${NC}" +echo " Runtime: Docker Desktop → Colima (MIT-Lizenz)" +echo " VM: Virtualization.framework (Apple VZ)" +echo " Backup: $BACKUP_DIR" +echo "" +echo -e "${BOLD}Naechste Schritte:${NC}" +echo " 1. Health-Check: ./scripts/mac-mini/health-check.sh" +echo " 2. Alle Apps testen: curl https://mana.how" +echo " 3. RAM pruefen: memory_pressure" +echo "" +echo -e "${BOLD}Bei Problemen:${NC}" +echo " Rollback: ./scripts/mac-mini/migrate-to-colima.sh --rollback" +echo "" +echo -e "${BOLD}Docker Desktop deinstallieren (optional, nach 1 Woche Testbetrieb):${NC}" +echo " brew uninstall --cask docker" +echo " rm -rf ~/Library/Containers/com.docker.docker" +echo ""