mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-15 05:01:08 +02:00
Three docs updates landing the institutional knowledge from today's
Memoro voice recording deploy:
- docs/MAC_MINI_SERVER.md: architecture diagram updated to show the
two-tunnel setup (cloudflared on the Mac Mini for *.mana.how
except gpu-*, plus a separate cloudflared running as a Windows
Service on the GPU box for gpu-*.mana.how). New "GPU Tunnel
(mana-gpu-server)" section explains how to add hostnames in the
Cloudflare dashboard, the standard 502 debug ladder (DNS misroute,
service stopped, scheduled task crashed, missing public hostname),
and how the API key flows from the Windows .env through Mac Mini
.env to the mana-web container.
- docs/ENVIRONMENT_VARIABLES.md: STT section updated to reflect that
MANA_STT_URL/API_KEY are now wired into the mana-web container via
docker-compose.macmini.yml (committed in 42bd2a3a0). Health-check
command added; cross-link to MAC_MINI_SERVER.md for the debug ladder.
- docs/POSTMORTEM_2026-04-07.md (new): full incident timeline of
today's deploy. Six root causes (tunnel never started, DB wiped
without re-push, untracked module-registry files, uncommitted
Dockerfile heap bump, missing compose env vars, /offline prerender
500). Three "what went poorly" honest assessments (premature P0
alarm, miscounted commits, clumsy stash dance). Action items split
by priority — high priority is the clean-clone build CI job, which
would have caught half the issues today.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
898 lines
30 KiB
Markdown
898 lines
30 KiB
Markdown
# Mac Mini Server Setup
|
|
|
|
Dokumentation des Mac Mini als Self-Hosted Server für Mana Apps.
|
|
|
|
## Übersicht
|
|
|
|
Der Mac Mini dient als Self-Hosted Server fuer alle Mana-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.mana.colima.plist`
|
|
**Migration:** `./scripts/mac-mini/migrate-to-colima.sh`
|
|
**Rollback:** `./scripts/mac-mini/migrate-to-colima.sh --rollback`
|
|
|
|
### Architektur
|
|
|
|
```
|
|
Internet
|
|
│
|
|
▼
|
|
Cloudflare Tunnel (cloudflared)
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ Mac Mini M4 (mana-server) │
|
|
│ │
|
|
│ ┌─────────────────┐ ┌─────────────────┐ │
|
|
│ │ PostgreSQL │ │ Redis │ │
|
|
│ │ (Docker) │ │ (Docker) │ │
|
|
│ └─────────────────┘ └─────────────────┘ │
|
|
│ │
|
|
│ ┌─────────────────────────────────────────────────────┐ │
|
|
│ │ Docker Container (~61 Services) │ │
|
|
│ │ ├── mana-auth (Port 3001) │ │
|
|
│ │ ├── dashboard-web (Port 5173) │ │
|
|
│ │ ├── chat-web (Port 3000) │ │
|
|
│ │ ├── todo-web (Port 5188) │ │
|
|
│ │ ├── calendar-web (Port 5186) │ │
|
|
│ │ ├── clock-web (Port 5187) │ │
|
|
│ │ ├── mana-sync (Go) (Port 3050) │ │
|
|
│ │ ├── mana-llm (Port 3020) │ │
|
|
│ │ └── ... (19 web apps, core services, monitoring) │ │
|
|
│ └─────────────────────────────────────────────────────┘ │
|
|
│ │ │
|
|
│ │ LAN (192.168.178.11) │
|
|
│ ▼ │
|
|
│ ┌─────────────────────────────────────────────────────┐ │
|
|
│ │ GPU Server (Windows, RTX 3090, 24 GB VRAM) │ │
|
|
│ │ ├── Ollama (Port 11434) - gemma3:12b │ │
|
|
│ │ ├── STT (Whisper) (Port 3020) │ │
|
|
│ │ ├── TTS (Port 3022) │ │
|
|
│ │ ├── Image Gen (FLUX) (Port 3023) │ │
|
|
│ │ └── cloudflared (Windows Service, Tunnel │ │
|
|
│ │ mana-gpu-server) │ │
|
|
│ │ → gpu-*.mana.how │ │
|
|
│ └─────────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ ┌─────────────────────────────────────────────────────┐ │
|
|
│ │ LaunchAgents (Autostart, Mac Mini) │ │
|
|
│ │ ├── cloudflared (Tunnel mana-server, │ │
|
|
│ │ │ → all .mana.how except │ │
|
|
│ │ │ gpu-*) │ │
|
|
│ │ ├── docker-startup (Container beim Boot) │ │
|
|
│ │ └── health-check (alle 5 Minuten) │ │
|
|
│ └─────────────────────────────────────────────────────┘ │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
> **Two-tunnel setup**: There are two Cloudflare tunnels in this stack.
|
|
> The **mana-server** tunnel runs on the Mac Mini (LaunchAgent, locally-managed
|
|
> via `~/.cloudflared/config.yml`) and handles every `*.mana.how` route except
|
|
> the GPU ones. The **mana-gpu-server** tunnel runs on the Windows GPU box as
|
|
> a Windows Service (token-managed via the Cloudflare dashboard, NOT a local
|
|
> config.yml) and handles `gpu-stt`, `gpu-llm`, `gpu-tts`, `gpu-img`,
|
|
> `gpu-ollama`. See the "GPU Tunnel" section below for adding new hostnames.
|
|
|
|
### Öffentliche URLs
|
|
|
|
| Service | URL |
|
|
|---------|-----|
|
|
| Dashboard | https://mana.how |
|
|
| Auth API | https://auth.mana.how |
|
|
| Chat | https://chat.mana.how |
|
|
| Todo | https://todo.mana.how |
|
|
| Calendar | https://calendar.mana.how |
|
|
| Clock | https://clock.mana.how |
|
|
| Matrix (Synapse) | https://matrix.mana.how |
|
|
| Element Web | https://element.mana.how |
|
|
|
|
## SSH-Zugang
|
|
|
|
### Verbindung
|
|
|
|
```bash
|
|
ssh mana-server
|
|
```
|
|
|
|
SSH-Config (`~/.ssh/config`):
|
|
|
|
```
|
|
# Lokales Netzwerk (direkt)
|
|
Host mana-server
|
|
HostName 192.168.178.131
|
|
User mana
|
|
|
|
# Über Cloudflare Tunnel (von extern)
|
|
Host mana-server-remote
|
|
HostName mac-mini.mana.how
|
|
User mana
|
|
ProxyCommand /opt/homebrew/bin/cloudflared access ssh --hostname %h
|
|
```
|
|
|
|
### Projekt-Verzeichnis
|
|
|
|
```bash
|
|
cd ~/projects/mana-monorepo
|
|
```
|
|
|
|
## CI/CD
|
|
|
|
Ein GitHub Actions Self-Hosted Runner läuft nativ auf dem Mac Mini und deployt automatisch bei Push auf `main`.
|
|
|
|
- **CD Workflow:** `.github/workflows/cd-macmini.yml`
|
|
- **Mirror Workflow:** `.github/workflows/mirror-to-forgejo.yml` (GitHub → Forgejo Sync)
|
|
- **Runner:** `mac-mini` (self-hosted, macOS, ARM64, LaunchAgent)
|
|
- **Manuelles Deployment:** https://github.com/Memo-2023/mana-monorepo/actions/workflows/cd-macmini.yml
|
|
|
|
### Forgejo (Mirror-Only)
|
|
|
|
Forgejo v11 läuft als Push-Mirror von GitHub — kein CI/CD, nur Backup und Sichtbarkeit.
|
|
|
|
- **URL:** https://git.mana.how (Port 3041)
|
|
- **SSH:** Port 2222
|
|
- **Sync:** Automatisch bei jedem Push auf `main` via GitHub Actions
|
|
- **Kein Runner:** Forgejo Runner hat kein macOS-Binary, Docker-Runner kann nicht auf Host zugreifen
|
|
|
|
```
|
|
lokal → git push → GitHub → CD (nativer Runner) → Docker deploy
|
|
→ Mirror → Forgejo (Backup)
|
|
```
|
|
|
|
## Wichtige Befehle
|
|
|
|
### Status & Monitoring
|
|
|
|
```bash
|
|
# HTTP-Erreichbarkeit aller mana.how Domains prüfen (liest aus cloudflared-config.yml)
|
|
pnpm check:status
|
|
# oder direkt:
|
|
bash scripts/check-status.sh
|
|
|
|
# Übersicht aller Services
|
|
./scripts/mac-mini/status.sh
|
|
|
|
# Health Check manuell ausführen
|
|
./scripts/mac-mini/health-check.sh
|
|
|
|
# Docker Container Status
|
|
docker ps
|
|
|
|
# Logs eines Containers
|
|
docker logs mana-chat-backend
|
|
docker logs -f mana-chat-backend # Live-Logs
|
|
```
|
|
|
|
**Grafana Uptime-Dashboard:** `grafana.mana.how` → Ordner "Mana" → **"Mana Uptime"**
|
|
Zeigt probe_success und probe_duration_seconds aller Dienste via Blackbox Exporter (Port 9115).
|
|
Alerts: WebAppDown (2 min), APIDown (1 min), InfraToolDown (3 min), GPUServiceDown (5 min), SlowHTTPResponse (5 min > 5s).
|
|
|
|
### Public Status Page (status.mana.how)
|
|
|
|
Statische HTML-Seite, die alle 60 Sekunden vom Container `mana-status-gen` neu generiert wird.
|
|
|
|
| Komponente | Pfad |
|
|
|---|---|
|
|
| Generator-Script | `scripts/generate-status-page.sh` |
|
|
| Docker-Service | `status-page-gen` in `docker-compose.macmini.yml` |
|
|
| Output | `/Volumes/ManaData/landings/status/index.html` + `status.json` |
|
|
| Nginx-Config | `docker/nginx/landings.conf` → `status.mana.how` |
|
|
|
|
**Datenquellen:**
|
|
- **Service-Uptime:** VictoriaMetrics via Blackbox Exporter (`probe_success`, `probe_duration_seconds`)
|
|
- **App Release Tiers:** Automatisch aus `packages/shared-branding/src/mana-apps.ts` geparst (per awk, read-only Volume-Mount). Zeigt welche Apps in welchem Tier (founder/alpha/beta/public) sind.
|
|
|
|
**Automatische Aktualisierung:** Änderungen an `requiredTier` in `mana-apps.ts` werden nach dem nächsten `git pull` auf dem Server automatisch beim nächsten 60s-Refresh auf der Statusseite sichtbar — kein Container-Restart nötig, da die Datei live gemountet ist.
|
|
|
|
**`status.json`** wird parallel generiert und enthält Service-Status + Tier-Daten als JSON (genutzt von ManaScore Live-Badges).
|
|
|
|
### Service Management
|
|
|
|
```bash
|
|
# Alle Container neustarten
|
|
./scripts/mac-mini/restart.sh
|
|
|
|
# Alle Container stoppen
|
|
./scripts/mac-mini/stop.sh
|
|
|
|
# Einzelnen Container neustarten
|
|
docker restart mana-chat-backend
|
|
|
|
# Neueste Images pullen und Container aktualisieren
|
|
./scripts/mac-mini/deploy.sh
|
|
```
|
|
|
|
### Autostart Management
|
|
|
|
```bash
|
|
# LaunchAgents Status prüfen
|
|
launchctl list | grep -E "(cloudflare|mana)"
|
|
|
|
# Health Check manuell triggern
|
|
launchctl start com.mana.health-check
|
|
|
|
# Service neuladen
|
|
launchctl unload ~/Library/LaunchAgents/com.mana.docker-startup.plist
|
|
launchctl load ~/Library/LaunchAgents/com.mana.docker-startup.plist
|
|
```
|
|
|
|
## GPU Tunnel (mana-gpu-server)
|
|
|
|
The Windows GPU box is **not** reached via the Mac Mini's tunnel. It runs its
|
|
own Cloudflare tunnel as a Windows Service, exposing five public hostnames:
|
|
|
|
| Hostname | Local target on Windows | Service |
|
|
|---|---|---|
|
|
| `gpu-stt.mana.how` | `localhost:3020` | mana-stt (Whisper) |
|
|
| `gpu-llm.mana.how` | `localhost:3025` | mana-llm |
|
|
| `gpu-tts.mana.how` | `localhost:3022` | mana-tts |
|
|
| `gpu-img.mana.how` | `localhost:3023` | mana-image-gen (FLUX) |
|
|
| `gpu-ollama.mana.how` | `localhost:11434` | Ollama |
|
|
|
|
The connector itself runs as the Windows Service `Cloudflared`, installed via
|
|
`cloudflared.exe service install <TOKEN>`. **Token-managed** means the routing
|
|
config (which hostname → which local port) lives in the Cloudflare Zero Trust
|
|
dashboard, **not** in any local config file. Editing
|
|
`~/.cloudflared/config.yml` on the Windows box has no effect on this tunnel.
|
|
|
|
### Adding a new GPU hostname
|
|
|
|
1. **Cloudflare dashboard**: Zero Trust → Networks → Tunnels → `mana-gpu-server`
|
|
→ Public Hostname → "Add a public hostname" with `Service Type: HTTP` and
|
|
`URL: localhost:<PORT>`. The dashboard creates both the DNS CNAME and the
|
|
ingress rule in one step.
|
|
2. **Verify**: `curl https://<new-host>.mana.how/health` should return 200 within
|
|
a few seconds (no need to restart the connector — it picks up dashboard
|
|
changes automatically).
|
|
|
|
### If a `gpu-*` hostname returns 502
|
|
|
|
Most likely the DNS CNAME points at a different tunnel (e.g. `mana-server`
|
|
instead of `mana-gpu-server`). To force-repoint from the Mac Mini:
|
|
|
|
```bash
|
|
ssh mana-server "/opt/homebrew/bin/cloudflared tunnel route dns \
|
|
--overwrite-dns 83454e8e-d7f5-4954-b2cb-0307c2dba7a6 <hostname>"
|
|
```
|
|
|
|
(`83454e8e-…` is the `mana-gpu-server` tunnel UUID. Use the UUID, not the
|
|
name — the CLI resolves the name against the wrong tunnel context otherwise.)
|
|
|
|
Other 502 root causes to check, in order of likelihood:
|
|
|
|
1. **Cloudflared service stopped on Windows**: `ssh mana-gpu "Get-Service Cloudflared"` → must show `Running`. Restart with `Restart-Service Cloudflared`.
|
|
2. **Origin service down**: `ssh mana-gpu "Get-ScheduledTask -TaskName ManaSTT"` → must show `Running`. The Python service runs as a Scheduled Task with `RestartCount=5, RestartInterval=PT1M`, so a crash should self-heal within ~1 min.
|
|
3. **Public Hostname missing in dashboard**: tunnel has zero ingress rules for the requested hostname.
|
|
|
|
### API key for STT proxy
|
|
|
|
The unified mana-web container's `/api/v1/memoro/transcribe` and
|
|
`/api/v1/dreams/transcribe` proxies need `MANA_STT_API_KEY` to authenticate
|
|
against `gpu-stt.mana.how`. The key:
|
|
|
|
- Lives in **Mac Mini `~/projects/mana-monorepo/.env`** (gitignored)
|
|
- Is referenced from `docker-compose.macmini.yml` as `${MANA_STT_API_KEY:-}`
|
|
- The source-of-truth is `services/mana-stt/.env` on the Windows GPU box (`API_KEYS=<key>:<name>`)
|
|
|
|
To rotate: append a new entry on the Windows side, restart the `ManaSTT`
|
|
scheduled task, update both `.env` files (Mac Mini + any local dev), restart
|
|
`mana-app-web`. Use a separate key per consumer (`mana-web`, future apps) so
|
|
they can be revoked individually.
|
|
|
|
## Autostart-Konfiguration
|
|
|
|
Drei LaunchAgents sorgen fuer automatischen Betrieb:
|
|
|
|
### 1. Cloudflare Tunnel
|
|
|
|
**Datei:** `~/Library/LaunchAgents/com.cloudflare.cloudflared.plist`
|
|
|
|
- Startet beim Login
|
|
- Haelt den Tunnel zu Cloudflare offen (mana-server tunnel only — the
|
|
GPU tunnel runs on the Windows box as a Windows Service, not here)
|
|
- Automatischer Neustart bei Absturz
|
|
|
|
### 2. Docker Container Startup
|
|
|
|
**Datei:** `~/Library/LaunchAgents/com.mana.docker-startup.plist`
|
|
|
|
- Startet beim Login
|
|
- Wartet auf Docker Desktop
|
|
- Fuehrt `docker compose up -d` aus
|
|
- Erstellt fehlende Datenbanken automatisch
|
|
|
|
### 3. Health Check
|
|
|
|
**Datei:** `~/Library/LaunchAgents/com.mana.health-check.plist`
|
|
|
|
- Laeuft alle 5 Minuten
|
|
- Prueft alle Services (HTTP + Docker)
|
|
- Sendet Benachrichtigungen bei Fehlern
|
|
|
|
### Deaktivierte LaunchAgents
|
|
|
|
Diese LaunchAgents sind seit der GPU-Server-Migration deaktiviert:
|
|
- `homebrew.mxcl.ollama.plist` — LLM laeuft auf GPU-Server
|
|
- `com.mana.image-gen.plist` — Bildgenerierung laeuft auf GPU-Server
|
|
- `com.mana.telegram-ollama-bot.plist` — Bot deaktiviert
|
|
|
|
### Setup neu ausführen
|
|
|
|
Falls die LaunchAgents neu eingerichtet werden müssen:
|
|
|
|
```bash
|
|
./scripts/mac-mini/setup-autostart.sh
|
|
```
|
|
|
|
## Benachrichtigungen
|
|
|
|
### Konfiguration
|
|
|
|
**Datei:** `.env.notifications`
|
|
|
|
```bash
|
|
# Telegram
|
|
TELEGRAM_BOT_TOKEN=xxx
|
|
TELEGRAM_CHAT_ID=xxx
|
|
|
|
# Email
|
|
EMAIL_TO=your@email.com
|
|
EMAIL_FROM=mana@mana.how
|
|
|
|
# ntfy.sh (optional)
|
|
NTFY_TOPIC=your-topic
|
|
```
|
|
|
|
### Telegram Bot
|
|
|
|
- **Bot:** @alterts_mana_bot
|
|
- **Chat ID:** 7117174865
|
|
- Sendet Alerts mit:
|
|
- Fehlgeschlagene Services
|
|
- Hostname und Zeitstempel
|
|
- Anleitung zur Fehlersuche
|
|
|
|
### Email
|
|
|
|
- Verwendet `msmtp` als SMTP-Client
|
|
- Konfiguration in `~/.msmtprc`
|
|
- Gmail mit App-Password
|
|
|
|
### Benachrichtigung testen
|
|
|
|
```bash
|
|
# Test-Nachricht senden
|
|
curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
|
|
-d "chat_id=${TELEGRAM_CHAT_ID}" \
|
|
-d "text=Test notification"
|
|
```
|
|
|
|
## Docker Compose
|
|
|
|
**Datei:** `docker-compose.macmini.yml`
|
|
|
|
### Container-Namen
|
|
|
|
| Container | Service |
|
|
|-----------|---------|
|
|
| mana-postgres | PostgreSQL Datenbank |
|
|
| mana-redis | Redis Cache |
|
|
| mana-auth | Auth Service |
|
|
| mana-dashboard-web | Dashboard |
|
|
| mana-chat-backend | Chat API |
|
|
| mana-chat-web | Chat Frontend |
|
|
| mana-todo-backend | Todo API |
|
|
| mana-todo-web | Todo Frontend |
|
|
| mana-calendar-backend | Calendar API |
|
|
| mana-calendar-web | Calendar Frontend |
|
|
| mana-clock-backend | Clock API |
|
|
| mana-clock-web | Clock Frontend |
|
|
| mana-synapse | Matrix Homeserver |
|
|
| mana-element | Element Web Client |
|
|
|
|
### Nützliche Docker-Befehle
|
|
|
|
```bash
|
|
# Alle Container starten
|
|
docker compose -f docker-compose.macmini.yml up -d
|
|
|
|
# Alle Container stoppen
|
|
docker compose -f docker-compose.macmini.yml down
|
|
|
|
# Container neustarten
|
|
docker compose -f docker-compose.macmini.yml restart
|
|
|
|
# Neueste Images pullen
|
|
docker compose -f docker-compose.macmini.yml pull
|
|
|
|
# Logs aller Container
|
|
docker compose -f docker-compose.macmini.yml logs -f
|
|
|
|
# Einzelnen Service neustarten
|
|
docker compose -f docker-compose.macmini.yml restart chat-backend
|
|
```
|
|
|
|
## Cloudflare Tunnel
|
|
|
|
### Konfiguration
|
|
|
|
**Datei:** `~/.cloudflared/config.yml`
|
|
|
|
> ⚠️ **Wichtig:** Dies ist eine separate Datei vom Repo-File `cloudflared-config.yml`.
|
|
> Neue Hostnames müssen in **beiden** Dateien eingetragen werden:
|
|
> 1. `cloudflared-config.yml` im Repo (für Dokumentation und Git-History)
|
|
> 2. `~/.cloudflared/config.yml` auf dem Server (was cloudflared tatsächlich liest)
|
|
> 3. DNS-Eintrag anlegen: `cloudflared tunnel route dns <tunnel-id> <hostname>`
|
|
> 4. Cloudflared neu starten: `launchctl stop com.cloudflare.cloudflared && launchctl start com.cloudflare.cloudflared`
|
|
|
|
```yaml
|
|
tunnel: mana-tunnel
|
|
credentials-file: ~/.cloudflared/credentials.json
|
|
|
|
ingress:
|
|
- hostname: mana.how
|
|
service: http://localhost:5173
|
|
- hostname: auth.mana.how
|
|
service: http://localhost:3001
|
|
- hostname: chat.mana.how
|
|
service: http://localhost:3000
|
|
# ... weitere Services
|
|
- service: http_status:404
|
|
```
|
|
|
|
### Tunnel Status
|
|
|
|
```bash
|
|
# Prüfen ob cloudflared läuft
|
|
pgrep -x cloudflared
|
|
|
|
# Tunnel-Logs
|
|
tail -f ~/.cloudflared/cloudflared.log
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
### Container startet nicht
|
|
|
|
```bash
|
|
# Logs prüfen
|
|
docker logs mana-<service-name>
|
|
|
|
# Container manuell starten
|
|
docker start mana-<service-name>
|
|
|
|
# Bei Problemen: Container neu erstellen
|
|
docker compose -f docker-compose.macmini.yml up -d --force-recreate <service-name>
|
|
```
|
|
|
|
### Tunnel nicht erreichbar
|
|
|
|
```bash
|
|
# cloudflared Status
|
|
pgrep -x cloudflared
|
|
|
|
# cloudflared neustarten
|
|
launchctl stop com.cloudflare.cloudflared
|
|
launchctl start com.cloudflare.cloudflared
|
|
|
|
# Logs prüfen
|
|
tail -100 ~/.cloudflared/cloudflared.log
|
|
```
|
|
|
|
### Datenbank-Probleme
|
|
|
|
```bash
|
|
# PostgreSQL Status
|
|
docker exec mana-postgres pg_isready -U postgres
|
|
|
|
# Datenbanken auflisten
|
|
docker exec mana-postgres psql -U postgres -c "\l"
|
|
|
|
# Datenbank manuell erstellen
|
|
docker exec mana-postgres psql -U postgres -c "CREATE DATABASE chat_db;"
|
|
```
|
|
|
|
### Health Check Fehler
|
|
|
|
```bash
|
|
# Health Check manuell ausführen
|
|
./scripts/mac-mini/health-check.sh
|
|
|
|
# Einzelnen Service testen
|
|
curl -s http://localhost:3002/api/v1/health
|
|
curl -s http://localhost:3000/
|
|
```
|
|
|
|
The health check monitors:
|
|
- All backend APIs and web frontends
|
|
- Infrastructure (PostgreSQL, Redis)
|
|
- Matrix services (Synapse, Element, all bots)
|
|
- Monitoring stack (Grafana, Umami, GlitchTip, VictoriaMetrics)
|
|
- Alerting stack (vmalert, Alertmanager, Alert Notifier)
|
|
- Disk space for `/` and `/Volumes/ManaData` (warning at 80%, critical at 90%)
|
|
- Cloudflare Tunnel (cloudflared process)
|
|
|
|
### Docker PATH auf dem Server
|
|
|
|
Bei SSH-Zugriff ist Docker nicht im Standard-PATH. Für Remote-Befehle:
|
|
|
|
```bash
|
|
# Docker liegt unter Docker Desktop
|
|
PATH=/Applications/Docker.app/Contents/Resources/bin:$PATH
|
|
|
|
# Beispiel: Remote docker compose
|
|
ssh mana-server "PATH=/Applications/Docker.app/Contents/Resources/bin:\$PATH && docker compose -f ~/projects/mana-monorepo/docker-compose.macmini.yml restart grafana"
|
|
```
|
|
|
|
### Container existiert nicht (wurde nie erstellt)
|
|
|
|
Wenn ein Service im Health-Check als `HTTP 000` erscheint und `docker ps -a` den Container nicht zeigt, wurde er vermutlich beim letzten Deploy übersprungen:
|
|
|
|
```bash
|
|
# Container erstellen und starten (Beispiel: Project Doc Bot)
|
|
docker compose -f docker-compose.macmini.yml up -d matrix-project-doc-bot
|
|
|
|
# Nach Restart prüfen
|
|
docker ps --filter name=mana-matrix-bot-projectdoc --format '{{.Names}} {{.Status}}'
|
|
```
|
|
|
|
## Wartung
|
|
|
|
### Updates einspielen
|
|
|
|
```bash
|
|
# Neuesten Code holen
|
|
git pull
|
|
|
|
# Neue Images pullen und deployen
|
|
./scripts/mac-mini/deploy.sh
|
|
|
|
# Einzelne App bauen und deployen (empfohlen)
|
|
./scripts/mac-mini/build-app.sh todo-web
|
|
./scripts/mac-mini/build-app.sh todo-web todo-backend
|
|
|
|
# Base Images neu bauen (nach Änderungen an shared packages)
|
|
./scripts/mac-mini/build-app.sh --base
|
|
```
|
|
|
|
### Docker Base Images
|
|
|
|
Alle Web-Apps werden auf einem vorgebauten Base Image aufgebaut, um Build-Zeit und Memory-Verbrauch zu reduzieren. Backend-Server verwenden `docker/Dockerfile.hono-server` (Hono + Bun) direkt.
|
|
|
|
| Base Image | Dockerfile | Verwendet von |
|
|
|------------|-----------|---------------|
|
|
| `sveltekit-base:local` | `docker/Dockerfile.sveltekit-base` | Alle SvelteKit Web-Apps |
|
|
|
|
Das Base Image enthaelt alle Shared Packages (`packages/`) vorinstalliert und vorgebaut. App-Dockerfiles muessen nur noch ihren app-spezifischen Code kopieren.
|
|
|
|
**Base Image neu bauen** wenn sich Shared Packages aendern:
|
|
|
|
```bash
|
|
./scripts/mac-mini/build-app.sh --base
|
|
```
|
|
|
|
### Build-Script (`build-app.sh`)
|
|
|
|
Das Script prüft vor dem Build den verfügbaren RAM und stoppt Monitoring-Container **nur wenn nötig** (< 3 GB frei). Alle Container haben explizite `mem_limit` Obergrenzen in der `docker-compose.macmini.yml`, sodass der tatsächliche Verbrauch typischerweise 50-70% der Limits beträgt und genug Headroom für Builds bleibt.
|
|
|
|
**Was es tut:**
|
|
1. Prüft verfügbaren RAM in der Colima VM
|
|
2. Stoppt 13 Monitoring-Container nur wenn < 3 GB frei (vorher: immer)
|
|
3. Baut die angegebenen Services
|
|
4. Startet Monitoring bei Exit automatisch wieder (auch bei Fehler/Ctrl+C via `trap`)
|
|
|
|
```bash
|
|
# Einzelne App
|
|
./scripts/mac-mini/build-app.sh todo-web
|
|
|
|
# Mehrere Apps
|
|
./scripts/mac-mini/build-app.sh todo-web todo-backend
|
|
|
|
# Alle Web-Apps
|
|
./scripts/mac-mini/build-app.sh --all-web
|
|
|
|
# Monitoring immer stoppen (altes Verhalten)
|
|
./scripts/mac-mini/build-app.sh --force-free todo-web
|
|
```
|
|
|
|
### Memory Baseline
|
|
|
|
Misst den tatsächlichen RAM-Verbrauch aller Container, sortiert nach Kategorie:
|
|
|
|
```bash
|
|
# Einmalige Messung mit Zusammenfassung
|
|
./scripts/mac-mini/memory-baseline.sh
|
|
|
|
# Live-Monitoring (docker stats)
|
|
./scripts/mac-mini/memory-baseline.sh --watch
|
|
```
|
|
|
|
### Memory-Limits
|
|
|
|
Alle 63 Container haben explizite `mem_limit` in `docker-compose.macmini.yml`:
|
|
|
|
| Kategorie | Container | Budget |
|
|
|-----------|-----------|--------|
|
|
| Infrastructure | 6 | 1.712 MB |
|
|
| Forgejo (mirror-only) | 1 | 512 MB |
|
|
| Core (Hono/Bun) | 5 | 704 MB |
|
|
| Go Services | 5 | 384 MB |
|
|
| Other Backend | 3 | 576 MB |
|
|
| Matrix | 4 | 784 MB |
|
|
| Web Apps | 20 | 2.560 MB |
|
|
| LLM | 2 | 384 MB |
|
|
| Monitoring | 14 | 1.792 MB |
|
|
| Games/Auto | 2 | 192 MB |
|
|
| **Total** | **63** | **9.856 MB (9,6 GiB)** |
|
|
|
|
Colima VM: 12 GiB → Headroom: ~2,4 GiB (Limits) / ~5-6 GiB (real)
|
|
|
|
### Backup
|
|
|
|
Die PostgreSQL-Datenbank sollte regelmäßig gesichert werden:
|
|
|
|
```bash
|
|
# Backup erstellen
|
|
docker exec mana-postgres pg_dumpall -U postgres > backup_$(date +%Y%m%d).sql
|
|
|
|
# Backup wiederherstellen
|
|
cat backup_20260123.sql | docker exec -i mana-postgres psql -U postgres
|
|
```
|
|
|
|
### Logs aufräumen
|
|
|
|
```bash
|
|
# Docker Logs beschränken (bereits in compose konfiguriert)
|
|
# max-size: 10m, max-file: 3
|
|
|
|
# Alte Docker Images entfernen
|
|
docker image prune -a
|
|
```
|
|
|
|
## Skript-Übersicht
|
|
|
|
| Skript | Beschreibung |
|
|
|--------|--------------|
|
|
| `setup-autostart.sh` | Richtet LaunchAgents ein (einmalig) |
|
|
| `setup-notifications.sh` | Interaktives Notification-Setup |
|
|
| `startup.sh` | Wird von launchd beim Boot aufgerufen |
|
|
| `health-check.sh` | Prüft Services, sendet Alerts |
|
|
| `status.sh` | Zeigt Übersicht aller Services |
|
|
| `restart.sh` | Startet alle Container neu |
|
|
| `stop.sh` | Stoppt alle Container |
|
|
| `deploy.sh` | Pullt neue Images und startet neu |
|
|
| `build-app.sh` | Baut einzelne Apps (smart memory check, stoppt Monitoring nur wenn nötig) |
|
|
| `memory-baseline.sh` | Misst RAM-Verbrauch aller Container nach Kategorie |
|
|
|
|
## Hardware
|
|
|
|
- **Chip:** Apple M4 (10 Cores)
|
|
- **RAM:** 16 GB Unified Memory
|
|
- **Interne SSD:** 228 GB
|
|
- **Externe SSD:** 4 TB (ManaData)
|
|
|
|
## AI-Workloads (GPU-Server)
|
|
|
|
Alle AI-Services (LLM, Bildgenerierung, STT, TTS) laufen auf dem Windows GPU-Server (RTX 3090, 24 GB VRAM) unter `192.168.178.11`. Der Mac Mini ist reiner Hosting-Server fuer Web, API, DB und Sync.
|
|
|
|
| Service | GPU-Server Port | Zugriff aus Docker |
|
|
|---------|----------------|-------------------|
|
|
| Ollama (LLM) | 11434 | `http://192.168.178.11:11434` |
|
|
| STT (Whisper) | 3020 | `http://192.168.178.11:3020` |
|
|
| TTS | 3022 | `http://192.168.178.11:3022` |
|
|
| Image Gen | 3023 | `http://192.168.178.11:3023` |
|
|
|
|
Alle Werte sind per Env-Var ueberschreibbar (`OLLAMA_URL`, `STT_SERVICE_URL`, `TTS_SERVICE_URL`, `IMAGE_GEN_SERVICE_URL`).
|
|
|
|
Cloud-Fallback bei GPU-Server-Ausfall: `mana-llm` hat `AUTO_FALLBACK_ENABLED=true` (OpenRouter, Groq, Google).
|
|
|
|
### Ollama/FLUX.2 auf dem Mac Mini (deaktiviert)
|
|
|
|
Ollama und FLUX.2 waren frueher lokal installiert, sind aber seit 2026-03-28 deaktiviert. Die Modelle liegen noch auf der SSD als Backup:
|
|
- `/Volumes/ManaData/ollama/` (~58 GB)
|
|
- `/Volumes/ManaData/flux2/` (~15 GB)
|
|
|
|
Bei Bedarf reaktivieren:
|
|
```bash
|
|
brew services start ollama
|
|
launchctl load ~/Library/LaunchAgents/com.mana.image-gen.plist
|
|
```
|
|
|
|
## Externe 4TB SSD
|
|
|
|
Die externe SSD wird für persistente Daten verwendet - sowohl für große Dateien (AI-Modelle) als auch für kritische Datenbanken (PostgreSQL, MinIO).
|
|
|
|
### Mount-Punkt
|
|
|
|
- **Volume:** `/Volumes/ManaData`
|
|
- **Geschwindigkeit:** ~1 GB/s (USB-C/Thunderbolt)
|
|
|
|
### Verzeichnisstruktur
|
|
|
|
```
|
|
/Volumes/ManaData/
|
|
├── Docker/ # Docker Desktop Daten (~228 GB) ⭐ Kritisch
|
|
│ └── com.docker.docker/ # Symlink von ~/Library/Containers/
|
|
├── postgres/ # PostgreSQL Datenbank (~200 MB) ⭐ Kritisch
|
|
├── minio/ # MinIO Object Storage (Storage App)
|
|
├── backups/ # PostgreSQL Backups (täglich 3:00)
|
|
├── ollama/ # LLM Modelle (~58 GB)
|
|
├── flux2/ # FLUX.2 Bildgenerierung (~15 GB)
|
|
├── stt-models/ # Speech-to-Text Modelle (~19 GB)
|
|
└── matrix/ # Matrix Synapse Daten
|
|
```
|
|
|
|
### Docker auf externer SSD
|
|
|
|
Docker Desktop läuft komplett von der externen SSD um die interne SSD zu entlasten:
|
|
|
|
**Symlink:**
|
|
```
|
|
~/Library/Containers/com.docker.docker -> /Volumes/ManaData/Docker/com.docker.docker
|
|
```
|
|
|
|
**Vorteile:**
|
|
- Interne SSD hat ~80GB mehr freien Speicher
|
|
- Docker kann unbegrenzt wachsen (3.5TB verfügbar)
|
|
- Keine Speicherprobleme beim Pullen großer Images
|
|
|
|
**Wichtig:** Die externe SSD muss IMMER angeschlossen sein, wenn Docker läuft!
|
|
|
|
### Vorteile der SSD-Speicherung
|
|
|
|
| Aspekt | Docker VM | Externe SSD |
|
|
|--------|-----------|-------------|
|
|
| **Bei Docker-Reset** | ❌ Daten weg | ✅ Daten bleiben |
|
|
| **Bei macOS-Neuinstall** | ❌ Daten weg | ✅ Daten bleiben |
|
|
| **Performance** | Langsamer | ~20-30% schneller |
|
|
| **Backup** | Schwieriger | Einfacher |
|
|
|
|
### Docker-Integration
|
|
|
|
Die folgenden Services nutzen direkte SSD-Mounts (kein Docker Volume):
|
|
|
|
| Service | SSD-Pfad | docker-compose.macmini.yml |
|
|
|---------|----------|---------------------------|
|
|
| PostgreSQL | `/Volumes/ManaData/postgres` | `volumes: - /Volumes/ManaData/postgres:/var/lib/postgresql/data` |
|
|
| MinIO | `/Volumes/ManaData/minio` | `volumes: - /Volumes/ManaData/minio:/data` |
|
|
|
|
### Symlinks (archiviert, fuer Backup-Modelle)
|
|
|
|
| Original | Symlink | Status |
|
|
|----------|---------|--------|
|
|
| `~/.ollama` | `/Volumes/ManaData/ollama` | Deaktiviert (GPU-Server) |
|
|
| `~/stt-models` | `/Volumes/ManaData/stt-models` | Deaktiviert (GPU-Server) |
|
|
| `~/flux2` | `/Volumes/ManaData/flux2` | Deaktiviert (GPU-Server) |
|
|
|
|
### SSD prüfen
|
|
|
|
```bash
|
|
# Mount-Status
|
|
df -h /Volumes/ManaData
|
|
|
|
# Nutzung
|
|
du -sh /Volumes/ManaData/*/
|
|
|
|
# Speed-Test
|
|
dd if=/dev/zero of=/Volumes/ManaData/test bs=1m count=1024 && rm /Volumes/ManaData/test
|
|
```
|
|
|
|
### Automatische Backups
|
|
|
|
PostgreSQL-Backups laufen täglich um 3:00 Uhr:
|
|
|
|
```bash
|
|
# Backup-Skript
|
|
/Users/mana/backup-postgres.sh
|
|
|
|
# Backup-Verzeichnis
|
|
/Volumes/ManaData/backups/postgres/
|
|
|
|
# Retention: 30 Tage
|
|
```
|
|
|
|
### Docker Desktop Voraussetzung
|
|
|
|
Docker Desktop benötigt "Full Disk Access" für SSD-Mounts:
|
|
|
|
```
|
|
Systemeinstellungen → Datenschutz & Sicherheit → Voller Festplattenzugriff → Docker.app ✅
|
|
```
|
|
|
|
## Matrix (DSGVO-konformes Messaging)
|
|
|
|
Matrix ist eine DSGVO-konforme Alternative zu Telegram für Bot-Kommunikation.
|
|
|
|
### Komponenten
|
|
|
|
| Service | Port | Beschreibung |
|
|
|---------|------|--------------|
|
|
| Synapse | 8008 | Matrix Homeserver |
|
|
| Element Web | 8087 | Web-Client |
|
|
|
|
### Matrix Bots
|
|
|
|
Alle Matrix Bots laufen als Docker Container und werden via GHCR (GitHub Container Registry) deployed. Watchtower aktualisiert sie automatisch bei neuen Images.
|
|
|
|
| Bot | Port | Beschreibung |
|
|
|-----|------|--------------|
|
|
| matrix-mana-bot | 4010 | Gateway - alle Features in einem Bot |
|
|
| matrix-ollama-bot | 4011 | KI-Chat via GPU-Server Ollama |
|
|
| matrix-stats-bot | 4012 | Server-Statistiken & Monitoring |
|
|
| matrix-project-doc-bot | 4013 | Projekt-Dokumentation aus Fotos/Voice/Text |
|
|
| matrix-todo-bot | 4014 | Aufgabenverwaltung |
|
|
| matrix-calendar-bot | 4015 | Termine & Events |
|
|
| matrix-nutriphi-bot | 4016 | Ernährungstracking |
|
|
| matrix-zitare-bot | 4017 | Tägliche Zitate |
|
|
| matrix-clock-bot | 4018 | Timer & Wecker |
|
|
| matrix-tts-bot | 4019 | Text-to-Speech |
|
|
|
|
**Health Checks:**
|
|
```bash
|
|
# Alle Bots prüfen
|
|
for port in 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019; do
|
|
echo -n "Port $port: "
|
|
curl -s http://localhost:$port/health | jq -r '.status // "error"'
|
|
done
|
|
```
|
|
|
|
**Logs:**
|
|
```bash
|
|
# Logs eines Bots
|
|
docker logs matrix-mana-bot -f
|
|
|
|
# Alle Matrix Bots
|
|
docker ps | grep matrix-.*-bot
|
|
```
|
|
|
|
**Bot neu starten:**
|
|
```bash
|
|
docker compose -f docker-compose.macmini.yml restart matrix-mana-bot
|
|
```
|
|
|
|
**Images manuell aktualisieren:**
|
|
```bash
|
|
docker compose -f docker-compose.macmini.yml pull matrix-mana-bot
|
|
docker compose -f docker-compose.macmini.yml up -d matrix-mana-bot
|
|
```
|
|
|
|
### Setup
|
|
|
|
```bash
|
|
# Matrix initialisieren
|
|
./scripts/mac-mini/setup-matrix.sh
|
|
|
|
# Services starten
|
|
docker compose -f docker-compose.macmini.yml up -d synapse element-web
|
|
|
|
# Admin-User erstellen
|
|
docker exec -it mana-synapse register_new_matrix_user \
|
|
-c /data/homeserver.yaml http://localhost:8008 -a
|
|
```
|
|
|
|
### Dokumentation
|
|
|
|
Siehe [MATRIX_SELF_HOSTING.md](./MATRIX_SELF_HOSTING.md) für detaillierte Anleitung.
|
|
|
|
## Chronologie der Einrichtung
|
|
|
|
1. **Docker Setup** - PostgreSQL, Redis, App-Container
|
|
2. **Cloudflare Tunnel** - Oeffentliche Erreichbarkeit
|
|
3. **SSH via Cloudflare Access** - Sicherer Remote-Zugang
|
|
4. **LaunchAgents** - Autostart bei Boot
|
|
5. **Health Checks** - Automatische Ueberwachung
|
|
6. **Telegram Notifications** - Alerts bei Fehlern
|
|
7. **Email Notifications** - Redundante Benachrichtigung
|
|
8. ~~**Ollama** - Lokale LLM-Inferenz~~ → Migriert auf GPU-Server (2026-03-28)
|
|
9. ~~**Telegram Ollama Bot**~~ → Deaktiviert (2026-03-28)
|
|
10. **Matrix Synapse** - DSGVO-konformes Messaging
|
|
11. **GPU-Server Offload** - Alle AI-Workloads auf RTX 3090 (2026-03-28)
|