mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 19:01:08 +02:00
docs: add comprehensive guide for recommended server services
Detailed documentation covering: - Current infrastructure overview (what's already running) - Critical additions: Backup (restic/borgmatic), Logging (Loki+Promtail) - Important additions: Uptime Kuma, Reverse Proxy (Traefik/Caddy) - Recommended additions: Secrets Management (Vault/Infisical), API Gateway - Optional services: CI/CD Runner, Whisper STT, Container Registry - Apps already developed but not yet deployed (Zitare, Picture, etc.) - Prioritized roadmap for implementation Each service includes: what it is, why it's needed, Docker Compose examples, and resource requirements. https://claude.ai/code/session_015LN6cVr58JJRBGEe2CTpHL
This commit is contained in:
parent
bea066c7f8
commit
c03f2e5d83
1 changed files with 962 additions and 0 deletions
962
docs/RECOMMENDED_SERVICES.md
Normal file
962
docs/RECOMMENDED_SERVICES.md
Normal file
|
|
@ -0,0 +1,962 @@
|
||||||
|
# Empfohlene Services für den Mac Mini Server
|
||||||
|
|
||||||
|
Diese Dokumentation beschreibt Services, die die bestehende Infrastruktur sinnvoll ergänzen würden. Für jeden Service wird erklärt: Was ist es? Warum braucht man es? Wie würde es integriert?
|
||||||
|
|
||||||
|
## Inhaltsverzeichnis
|
||||||
|
|
||||||
|
1. [Aktuelle Infrastruktur](#aktuelle-infrastruktur)
|
||||||
|
2. [Kritische Ergänzungen](#kritische-ergänzungen)
|
||||||
|
- [Backup-Lösung (restic/borgmatic)](#1-backup-lösung-resticborgmatic)
|
||||||
|
- [Zentrales Logging (Loki + Promtail)](#2-zentrales-logging-loki--promtail)
|
||||||
|
3. [Wichtige Ergänzungen](#wichtige-ergänzungen)
|
||||||
|
- [Uptime Monitoring (Uptime Kuma)](#3-uptime-monitoring-uptime-kuma)
|
||||||
|
- [Reverse Proxy (Traefik/Caddy)](#4-reverse-proxy-traefikcaddy)
|
||||||
|
4. [Empfohlene Ergänzungen](#empfohlene-ergänzungen)
|
||||||
|
- [Secrets Management (Vault/Infisical)](#5-secrets-management-vaultinfisical)
|
||||||
|
- [API Gateway (Kong)](#6-api-gateway-kong)
|
||||||
|
5. [Optionale Ergänzungen](#optionale-ergänzungen)
|
||||||
|
- [CI/CD Runner](#7-cicd-runner)
|
||||||
|
- [Container Registry](#8-container-registry)
|
||||||
|
- [Speech-to-Text (Whisper)](#9-speech-to-text-whisper)
|
||||||
|
6. [Noch nicht deployed (bereits entwickelt)](#noch-nicht-deployed-bereits-entwickelt)
|
||||||
|
7. [Priorisierte Roadmap](#priorisierte-roadmap)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Aktuelle Infrastruktur
|
||||||
|
|
||||||
|
### Was bereits läuft
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────────────────┐
|
||||||
|
│ INFRASTRUKTUR │
|
||||||
|
│ ├── PostgreSQL Relationale Datenbank für alle Apps │
|
||||||
|
│ ├── Redis Cache & Session-Store │
|
||||||
|
│ ├── MinIO S3-kompatibler Object Storage │
|
||||||
|
│ └── Cloudflare Tunnel für öffentliche Erreichbarkeit │
|
||||||
|
├─────────────────────────────────────────────────────────────────────────┤
|
||||||
|
│ AUTH & CORE │
|
||||||
|
│ ├── mana-core-auth Zentraler Auth-Service (Better Auth + EdDSA JWT) │
|
||||||
|
│ └── manacore-web Dashboard für alle Apps │
|
||||||
|
├─────────────────────────────────────────────────────────────────────────┤
|
||||||
|
│ PRODUKTIVITÄTS-APPS (je Backend + Web) │
|
||||||
|
│ ├── Chat AI-Chat mit verschiedenen Modellen │
|
||||||
|
│ ├── Todo Aufgabenverwaltung │
|
||||||
|
│ ├── Calendar Kalender & Termine │
|
||||||
|
│ ├── Clock Zeiterfassung │
|
||||||
|
│ ├── Contacts Kontaktverwaltung │
|
||||||
|
│ ├── Storage Cloud-Speicher │
|
||||||
|
│ ├── Presi Präsentationen │
|
||||||
|
│ └── NutriPhi Ernährungstracking │
|
||||||
|
├─────────────────────────────────────────────────────────────────────────┤
|
||||||
|
│ MONITORING │
|
||||||
|
│ ├── VictoriaMetrics Zeitreihen-Datenbank für Metriken │
|
||||||
|
│ ├── Grafana Dashboards & Visualisierung │
|
||||||
|
│ ├── Pushgateway Metriken von Batch-Jobs │
|
||||||
|
│ ├── Node Exporter Host-Metriken (CPU, RAM, Disk) │
|
||||||
|
│ ├── cAdvisor Container-Metriken │
|
||||||
|
│ ├── Postgres Exp. PostgreSQL-Metriken │
|
||||||
|
│ └── Redis Exporter Redis-Metriken │
|
||||||
|
├─────────────────────────────────────────────────────────────────────────┤
|
||||||
|
│ AUTOMATION & ANALYTICS │
|
||||||
|
│ ├── n8n Workflow-Automation (wie Zapier) │
|
||||||
|
│ ├── Watchtower Automatische Container-Updates │
|
||||||
|
│ └── Umami Privacy-freundliche Web-Analytics │
|
||||||
|
├─────────────────────────────────────────────────────────────────────────┤
|
||||||
|
│ MATRIX (DSGVO-KONFORM) │
|
||||||
|
│ ├── Synapse Matrix Homeserver │
|
||||||
|
│ ├── Element Web Web-Client für Matrix │
|
||||||
|
│ └── 8 Bots Ollama, Stats, Doc, Calendar, Todo, etc. │
|
||||||
|
├─────────────────────────────────────────────────────────────────────────┤
|
||||||
|
│ KI-SERVICES │
|
||||||
|
│ ├── Ollama Lokale LLM-Inferenz (nativ, Metal GPU) │
|
||||||
|
│ ├── Telegram Bot Ollama-Chat via Telegram │
|
||||||
|
│ └── Telegram Stats Server-Status via Telegram │
|
||||||
|
└─────────────────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### Was fehlt
|
||||||
|
|
||||||
|
| Bereich | Lücke | Risiko |
|
||||||
|
|---------|-------|--------|
|
||||||
|
| **Backup** | Kein automatisches Backup | Datenverlust bei Hardware-Ausfall |
|
||||||
|
| **Logging** | Logs nur in einzelnen Containern | Schwierige Fehlersuche |
|
||||||
|
| **Externe Überwachung** | Nur interne Health-Checks | Kein Alarm wenn Server offline |
|
||||||
|
| **Secrets** | .env Dateien auf Disk | Sicherheitsrisiko |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Kritische Ergänzungen
|
||||||
|
|
||||||
|
### 1. Backup-Lösung (restic/borgmatic)
|
||||||
|
|
||||||
|
#### Was ist das?
|
||||||
|
|
||||||
|
**Backup-Tools** erstellen automatische Sicherungskopien deiner Daten und speichern sie an einem sicheren Ort (lokal oder remote). Bei einem Ausfall können alle Daten wiederhergestellt werden.
|
||||||
|
|
||||||
|
- **restic**: Modernes Backup-Tool mit Deduplizierung und Verschlüsselung
|
||||||
|
- **borgmatic**: Wrapper um Borg Backup mit einfacher YAML-Konfiguration
|
||||||
|
|
||||||
|
#### Warum braucht man das?
|
||||||
|
|
||||||
|
```
|
||||||
|
OHNE BACKUP:
|
||||||
|
┌──────────────┐ Hardware-Defekt ┌──────────────┐
|
||||||
|
│ PostgreSQL │ ────────────────────> │ ALLE DATEN │
|
||||||
|
│ MinIO │ │ VERLOREN │
|
||||||
|
│ Volumes │ │ 💀 │
|
||||||
|
└──────────────┘ └──────────────┘
|
||||||
|
|
||||||
|
MIT BACKUP:
|
||||||
|
┌──────────────┐ Hardware-Defekt ┌──────────────┐
|
||||||
|
│ PostgreSQL │ ────────────────────> │ Neuer Mac │
|
||||||
|
│ MinIO │ │ Mini kaufen │
|
||||||
|
│ Volumes │ └──────┬───────┘
|
||||||
|
└──────────────┘ │
|
||||||
|
│ │
|
||||||
|
│ Täglich 3:00 Uhr │ Restore
|
||||||
|
▼ ▼
|
||||||
|
┌──────────────┐ ┌──────────────┐
|
||||||
|
│ Hetzner │ ────────────────────> │ Alles wie │
|
||||||
|
│ Storage Box │ │ vorher │
|
||||||
|
│ (20€/TB) │ │ ✓ │
|
||||||
|
└──────────────┘ └──────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
**Konkrete Szenarien:**
|
||||||
|
- SSD-Ausfall → Alle Datenbanken weg
|
||||||
|
- Versehentliches `DROP TABLE` → Daten unwiederbringlich
|
||||||
|
- Ransomware → Verschlüsselte Daten
|
||||||
|
- macOS-Update schlägt fehl → System nicht bootbar
|
||||||
|
|
||||||
|
#### Wie würde es integriert?
|
||||||
|
|
||||||
|
**Docker-Compose Ergänzung:**
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
backup:
|
||||||
|
image: mazzolino/restic:latest
|
||||||
|
container_name: manacore-backup
|
||||||
|
hostname: macmini-backup
|
||||||
|
environment:
|
||||||
|
# Backup-Ziel (Hetzner Storage Box)
|
||||||
|
RESTIC_REPOSITORY: sftp:u123456@u123456.your-storagebox.de:/backups
|
||||||
|
RESTIC_PASSWORD: ${BACKUP_PASSWORD}
|
||||||
|
|
||||||
|
# Backup-Zeitplan
|
||||||
|
BACKUP_CRON: "0 3 * * *" # Täglich 3:00 Uhr
|
||||||
|
|
||||||
|
# Aufbewahrung
|
||||||
|
RESTIC_KEEP_DAILY: 7
|
||||||
|
RESTIC_KEEP_WEEKLY: 4
|
||||||
|
RESTIC_KEEP_MONTHLY: 12
|
||||||
|
volumes:
|
||||||
|
# PostgreSQL Daten
|
||||||
|
- postgres_data:/data/postgres:ro
|
||||||
|
# MinIO Daten
|
||||||
|
- minio_data:/data/minio:ro
|
||||||
|
# App-Volumes
|
||||||
|
- synapse_data:/data/synapse:ro
|
||||||
|
# SSH-Key für Hetzner
|
||||||
|
- ./backup/ssh:/root/.ssh:ro
|
||||||
|
depends_on:
|
||||||
|
- postgres
|
||||||
|
- minio
|
||||||
|
```
|
||||||
|
|
||||||
|
**Pre-Backup Script für PostgreSQL:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
# Vor dem Backup: Konsistenten DB-Dump erstellen
|
||||||
|
docker exec manacore-postgres pg_dumpall -U postgres > /backup/postgres_dump.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
**Kosten:**
|
||||||
|
- Hetzner Storage Box: ~3,50€/Monat für 100 GB
|
||||||
|
- Hetzner Object Storage: ~2,50€/Monat für 100 GB
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2. Zentrales Logging (Loki + Promtail)
|
||||||
|
|
||||||
|
#### Was ist das?
|
||||||
|
|
||||||
|
**Loki** ist ein Log-Aggregationssystem (wie Elasticsearch, aber leichtgewichtiger). **Promtail** sammelt Logs von allen Containern und sendet sie an Loki. Die Logs können dann in **Grafana** durchsucht und analysiert werden.
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
||||||
|
│ chat-backend│ │ todo-backend│ │ auth-service│
|
||||||
|
│ Logs │ │ Logs │ │ Logs │
|
||||||
|
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
|
||||||
|
│ │ │
|
||||||
|
└────────────────┼────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌───────────────┐
|
||||||
|
│ Promtail │ Sammelt alle Logs
|
||||||
|
│ (Agent) │
|
||||||
|
└───────┬───────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌───────────────┐
|
||||||
|
│ Loki │ Speichert & Indexiert
|
||||||
|
│ (Server) │
|
||||||
|
└───────┬───────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌───────────────┐
|
||||||
|
│ Grafana │ Suche & Dashboards
|
||||||
|
│ (bereits da) │
|
||||||
|
└───────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Warum braucht man das?
|
||||||
|
|
||||||
|
**Aktuelles Problem:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Fehler in der App? Du musst jeden Container einzeln durchsuchen:
|
||||||
|
docker logs manacore-chat-backend | grep error
|
||||||
|
docker logs manacore-todo-backend | grep error
|
||||||
|
docker logs manacore-auth | grep error
|
||||||
|
docker logs manacore-calendar-backend | grep error
|
||||||
|
# ... 15+ weitere Container
|
||||||
|
```
|
||||||
|
|
||||||
|
**Mit Loki:**
|
||||||
|
|
||||||
|
```
|
||||||
|
Grafana Query: {job="docker"} |= "error" | json | level="error"
|
||||||
|
→ Alle Fehler aller Container in einer Ansicht
|
||||||
|
→ Filterbar nach App, Zeit, User, Request-ID
|
||||||
|
→ Korrelation zwischen Services möglich
|
||||||
|
```
|
||||||
|
|
||||||
|
**Konkrete Vorteile:**
|
||||||
|
|
||||||
|
| Situation | Ohne Loki | Mit Loki |
|
||||||
|
|-----------|-----------|----------|
|
||||||
|
| User meldet Fehler | 20 Min. Suche in 15 Containern | 30 Sek. Query nach Request-ID |
|
||||||
|
| Performance-Problem | Unklar welcher Service | Timeline aller Requests |
|
||||||
|
| Security-Incident | Logs evtl. schon rotiert | 30 Tage Retention |
|
||||||
|
| Debugging nachts | Logs am nächsten Tag weg | Alles gespeichert |
|
||||||
|
|
||||||
|
#### Wie würde es integriert?
|
||||||
|
|
||||||
|
**Docker-Compose Ergänzung:**
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
loki:
|
||||||
|
image: grafana/loki:3.0.0
|
||||||
|
container_name: manacore-loki
|
||||||
|
ports:
|
||||||
|
- "3100:3100"
|
||||||
|
volumes:
|
||||||
|
- ./loki/config.yaml:/etc/loki/config.yaml
|
||||||
|
- loki_data:/loki
|
||||||
|
command: -config.file=/etc/loki/config.yaml
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
promtail:
|
||||||
|
image: grafana/promtail:3.0.0
|
||||||
|
container_name: manacore-promtail
|
||||||
|
volumes:
|
||||||
|
- ./promtail/config.yaml:/etc/promtail/config.yaml
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||||
|
- /var/lib/docker/containers:/var/lib/docker/containers:ro
|
||||||
|
command: -config.file=/etc/promtail/config.yaml
|
||||||
|
restart: unless-stopped
|
||||||
|
```
|
||||||
|
|
||||||
|
**Loki Config (loki/config.yaml):**
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
auth_enabled: false
|
||||||
|
|
||||||
|
server:
|
||||||
|
http_listen_port: 3100
|
||||||
|
|
||||||
|
common:
|
||||||
|
ring:
|
||||||
|
instance_addr: 127.0.0.1
|
||||||
|
kvstore:
|
||||||
|
store: inmemory
|
||||||
|
replication_factor: 1
|
||||||
|
path_prefix: /loki
|
||||||
|
|
||||||
|
schema_config:
|
||||||
|
configs:
|
||||||
|
- from: 2024-01-01
|
||||||
|
store: tsdb
|
||||||
|
object_store: filesystem
|
||||||
|
schema: v13
|
||||||
|
index:
|
||||||
|
prefix: index_
|
||||||
|
period: 24h
|
||||||
|
|
||||||
|
storage_config:
|
||||||
|
filesystem:
|
||||||
|
directory: /loki/chunks
|
||||||
|
|
||||||
|
limits_config:
|
||||||
|
retention_period: 744h # 31 Tage
|
||||||
|
```
|
||||||
|
|
||||||
|
**Promtail Config (promtail/config.yaml):**
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
server:
|
||||||
|
http_listen_port: 9080
|
||||||
|
|
||||||
|
positions:
|
||||||
|
filename: /tmp/positions.yaml
|
||||||
|
|
||||||
|
clients:
|
||||||
|
- url: http://loki:3100/loki/api/v1/push
|
||||||
|
|
||||||
|
scrape_configs:
|
||||||
|
- job_name: docker
|
||||||
|
docker_sd_configs:
|
||||||
|
- host: unix:///var/run/docker.sock
|
||||||
|
refresh_interval: 5s
|
||||||
|
relabel_configs:
|
||||||
|
- source_labels: ['__meta_docker_container_name']
|
||||||
|
regex: '/(.*)'
|
||||||
|
target_label: 'container'
|
||||||
|
- source_labels: ['__meta_docker_container_label_com_docker_compose_service']
|
||||||
|
target_label: 'service'
|
||||||
|
```
|
||||||
|
|
||||||
|
**Ressourcen:**
|
||||||
|
- RAM: ~200-500 MB für Loki
|
||||||
|
- Disk: ~1-5 GB für 30 Tage Logs
|
||||||
|
- CPU: Minimal
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Wichtige Ergänzungen
|
||||||
|
|
||||||
|
### 3. Uptime Monitoring (Uptime Kuma)
|
||||||
|
|
||||||
|
#### Was ist das?
|
||||||
|
|
||||||
|
**Uptime Kuma** ist ein Self-Hosted Monitoring-Tool, das regelmäßig deine Services von außen prüft und bei Ausfällen alarmiert. Es bietet auch eine öffentliche Status-Seite.
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────────┐
|
||||||
|
│ UPTIME KUMA │
|
||||||
|
│ │
|
||||||
|
│ Checks alle 60 Sekunden: │
|
||||||
|
│ │
|
||||||
|
│ ✓ https://mana.how 200 OK Latenz: 142ms │
|
||||||
|
│ ✓ https://chat.mana.how 200 OK Latenz: 89ms │
|
||||||
|
│ ✓ https://auth.mana.how/health 200 OK Latenz: 45ms │
|
||||||
|
│ ✗ https://calendar.mana.how 503 Error ← ALARM! │
|
||||||
|
│ ✓ https://matrix.mana.how 200 OK Latenz: 234ms │
|
||||||
|
│ │
|
||||||
|
│ Uptime (30 Tage): │
|
||||||
|
│ ████████████████████████████░░ 99.7% │
|
||||||
|
└─────────────────────────────────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────┐
|
||||||
|
│ Benachrichtigungen: │
|
||||||
|
│ • Telegram │
|
||||||
|
│ • Matrix │
|
||||||
|
│ • Email │
|
||||||
|
│ • Webhook │
|
||||||
|
└─────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Warum braucht man das?
|
||||||
|
|
||||||
|
**Unterschied zu internen Health-Checks:**
|
||||||
|
|
||||||
|
| Aspekt | Interner Health-Check | Uptime Kuma |
|
||||||
|
|--------|----------------------|-------------|
|
||||||
|
| **Perspektive** | Vom Server selbst | Von außen (wie User) |
|
||||||
|
| **Erkennt** | Container-Crash | DNS, Cloudflare, SSL, Container |
|
||||||
|
| **Server offline** | Keine Benachrichtigung! | Sofort Alarm |
|
||||||
|
| **Tunnel-Problem** | Nicht erkennbar | Erkennbar |
|
||||||
|
| **SSL-Ablauf** | Nicht geprüft | Warnung vor Ablauf |
|
||||||
|
|
||||||
|
**Beispiel:** Der Mac Mini läuft, aber Cloudflare Tunnel ist down:
|
||||||
|
- Interner Health-Check: "Alles OK" ✓
|
||||||
|
- Uptime Kuma (extern): "Alle Services down!" → Alarm
|
||||||
|
|
||||||
|
#### Wie würde es integriert?
|
||||||
|
|
||||||
|
**Option A: Auf einem externen VPS (empfohlen)**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Auf einem 3€/Monat VPS (Hetzner/Netcup)
|
||||||
|
docker run -d \
|
||||||
|
--name uptime-kuma \
|
||||||
|
-p 3001:3001 \
|
||||||
|
-v uptime-kuma:/app/data \
|
||||||
|
louislam/uptime-kuma:1
|
||||||
|
```
|
||||||
|
|
||||||
|
**Option B: Auf dem Mac Mini selbst (eingeschränkt)**
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# docker-compose.macmini.yml
|
||||||
|
services:
|
||||||
|
uptime-kuma:
|
||||||
|
image: louislam/uptime-kuma:1
|
||||||
|
container_name: manacore-uptime-kuma
|
||||||
|
ports:
|
||||||
|
- "3099:3001"
|
||||||
|
volumes:
|
||||||
|
- uptime_kuma_data:/app/data
|
||||||
|
restart: unless-stopped
|
||||||
|
```
|
||||||
|
|
||||||
|
**Einrichtung:**
|
||||||
|
|
||||||
|
1. Web-Interface öffnen: `https://status.mana.how`
|
||||||
|
2. Monitors hinzufügen:
|
||||||
|
- Type: HTTP(s)
|
||||||
|
- URL: `https://chat.mana.how`
|
||||||
|
- Interval: 60 Sekunden
|
||||||
|
- Retry: 3
|
||||||
|
3. Benachrichtigungen konfigurieren (Telegram, Matrix)
|
||||||
|
4. Status-Page erstellen und öffentlich machen
|
||||||
|
|
||||||
|
**Ressourcen:**
|
||||||
|
- RAM: ~100-200 MB
|
||||||
|
- Disk: ~50 MB
|
||||||
|
- CPU: Minimal
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4. Reverse Proxy (Traefik/Caddy)
|
||||||
|
|
||||||
|
#### Was ist das?
|
||||||
|
|
||||||
|
Ein **Reverse Proxy** ist ein Vermittler zwischen eingehenden Anfragen und deinen Backend-Services. Er bietet:
|
||||||
|
- Automatische SSL-Zertifikate
|
||||||
|
- Load Balancing
|
||||||
|
- Request-Routing
|
||||||
|
- Middleware (Auth, Rate-Limiting, Headers)
|
||||||
|
|
||||||
|
```
|
||||||
|
OHNE REVERSE PROXY:
|
||||||
|
┌──────────┐
|
||||||
|
│ Internet │──┬──> :3000 chat-web
|
||||||
|
│ │ ├──> :3001 auth
|
||||||
|
│ │ ├──> :3002 chat-backend
|
||||||
|
│ │ ├──> :5173 dashboard
|
||||||
|
│ │ └──> :8008 synapse
|
||||||
|
└──────────┘ (Cloudflare muss jeden Port einzeln routen)
|
||||||
|
|
||||||
|
MIT REVERSE PROXY:
|
||||||
|
┌──────────┐ ┌─────────────────┐ ┌──────────────┐
|
||||||
|
│ Internet │─────>│ Traefik │─────>│ Container │
|
||||||
|
│ │ :443 │ │ │ │
|
||||||
|
│ │ │ chat.mana.how │──────│ chat-web │
|
||||||
|
│ │ │ auth.mana.how │──────│ auth │
|
||||||
|
│ │ │ api.chat.mana.* │──────│ chat-backend │
|
||||||
|
└──────────┘ └─────────────────┘ └──────────────┘
|
||||||
|
│
|
||||||
|
├── SSL Termination
|
||||||
|
├── Rate Limiting
|
||||||
|
├── Request Logging
|
||||||
|
└── Health Checks
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Warum braucht man das?
|
||||||
|
|
||||||
|
**Aktuell:**
|
||||||
|
- Cloudflare Tunnel macht das Routing
|
||||||
|
- Funktioniert, aber:
|
||||||
|
- Keine lokalen SSL-Zertifikate zwischen Containern
|
||||||
|
- Keine einheitliche Request-Logs
|
||||||
|
- Kein Rate-Limiting
|
||||||
|
- Cloudflare-Konfiguration nötig für jeden neuen Service
|
||||||
|
|
||||||
|
**Mit Traefik:**
|
||||||
|
- Service hinzufügen → automatisch erreichbar
|
||||||
|
- Einheitliche Logs aller Requests
|
||||||
|
- Rate-Limiting gegen Missbrauch
|
||||||
|
- Dashboard mit Traffic-Übersicht
|
||||||
|
|
||||||
|
#### Wie würde es integriert?
|
||||||
|
|
||||||
|
**Docker-Compose Ergänzung:**
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
traefik:
|
||||||
|
image: traefik:v3.0
|
||||||
|
container_name: manacore-traefik
|
||||||
|
command:
|
||||||
|
- "--api.dashboard=true"
|
||||||
|
- "--providers.docker=true"
|
||||||
|
- "--providers.docker.exposedbydefault=false"
|
||||||
|
- "--entrypoints.web.address=:80"
|
||||||
|
- "--entrypoints.websecure.address=:443"
|
||||||
|
- "--accesslog=true"
|
||||||
|
- "--accesslog.filepath=/logs/access.log"
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
- "443:443"
|
||||||
|
- "8080:8080" # Dashboard
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||||
|
- traefik_logs:/logs
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.dashboard.rule=Host(`traefik.mana.how`)"
|
||||||
|
- "traefik.http.routers.dashboard.service=api@internal"
|
||||||
|
|
||||||
|
chat-web:
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.chat.rule=Host(`chat.mana.how`)"
|
||||||
|
- "traefik.http.services.chat.loadbalancer.server.port=3000"
|
||||||
|
# Rate Limiting
|
||||||
|
- "traefik.http.middlewares.chat-ratelimit.ratelimit.average=100"
|
||||||
|
- "traefik.http.middlewares.chat-ratelimit.ratelimit.burst=50"
|
||||||
|
- "traefik.http.routers.chat.middlewares=chat-ratelimit"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Alternative: Caddy**
|
||||||
|
|
||||||
|
Caddy ist einfacher zu konfigurieren und hat automatisches HTTPS:
|
||||||
|
|
||||||
|
```
|
||||||
|
# Caddyfile
|
||||||
|
chat.mana.how {
|
||||||
|
reverse_proxy chat-web:3000
|
||||||
|
}
|
||||||
|
|
||||||
|
auth.mana.how {
|
||||||
|
reverse_proxy mana-core-auth:3001
|
||||||
|
}
|
||||||
|
|
||||||
|
api.chat.mana.how {
|
||||||
|
reverse_proxy chat-backend:3002
|
||||||
|
|
||||||
|
@api path /api/*
|
||||||
|
rate_limit @api 100r/m
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Ressourcen:**
|
||||||
|
- RAM: ~50-100 MB
|
||||||
|
- CPU: Minimal
|
||||||
|
- Disk: Logs
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Empfohlene Ergänzungen
|
||||||
|
|
||||||
|
### 5. Secrets Management (Vault/Infisical)
|
||||||
|
|
||||||
|
#### Was ist das?
|
||||||
|
|
||||||
|
**Secrets Management** ist ein System zur sicheren Speicherung und Verteilung von sensiblen Daten wie:
|
||||||
|
- Datenbank-Passwörter
|
||||||
|
- API-Keys
|
||||||
|
- JWT-Secrets
|
||||||
|
- Verschlüsselungsschlüssel
|
||||||
|
|
||||||
|
```
|
||||||
|
OHNE SECRETS MANAGEMENT:
|
||||||
|
┌─────────────────────────────────────┐
|
||||||
|
│ .env Datei auf Disk │
|
||||||
|
│ │
|
||||||
|
│ DATABASE_PASSWORD=supersecret123 │ ← Im Klartext!
|
||||||
|
│ JWT_SECRET=myverysecretkey │ ← Wer lesen kann, sieht alles
|
||||||
|
│ OPENAI_API_KEY=sk-abc123... │ ← Git-History?
|
||||||
|
└─────────────────────────────────────┘
|
||||||
|
|
||||||
|
MIT VAULT:
|
||||||
|
┌─────────────────────────────────────┐
|
||||||
|
│ Vault (verschlüsselt) │
|
||||||
|
│ │
|
||||||
|
│ ┌─────────────────────────────┐ │
|
||||||
|
│ │ ████████████████████████ │ │ ← Verschlüsselt
|
||||||
|
│ │ ████████████████████████ │ │ ← Zugriff nur mit Token
|
||||||
|
│ │ ████████████████████████ │ │ ← Audit-Log wer was las
|
||||||
|
│ └─────────────────────────────┘ │
|
||||||
|
└─────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼ App startet und fragt Vault
|
||||||
|
┌─────────────────────────────────────┐
|
||||||
|
│ Container bekommt Secrets │
|
||||||
|
│ nur in den Speicher │
|
||||||
|
│ (nie auf Disk) │
|
||||||
|
└─────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Warum braucht man das?
|
||||||
|
|
||||||
|
| Aspekt | .env Dateien | Vault/Infisical |
|
||||||
|
|--------|--------------|-----------------|
|
||||||
|
| **Speicherung** | Klartext auf Disk | Verschlüsselt |
|
||||||
|
| **Zugriffskontrolle** | Filesystem-Rechte | Policies & Tokens |
|
||||||
|
| **Audit** | Keins | Wer hat wann was gelesen |
|
||||||
|
| **Rotation** | Manuell | Automatisch möglich |
|
||||||
|
| **Git-Sicherheit** | .gitignore kann vergessen werden | Secrets nie in Git |
|
||||||
|
| **Backup** | Klartext im Backup | Verschlüsselt |
|
||||||
|
|
||||||
|
**Szenarien:**
|
||||||
|
|
||||||
|
1. **Laptop gestohlen** mit Git-Repo → .env lesbar
|
||||||
|
2. **Mitarbeiter verlässt Team** → Alle Secrets rotieren?
|
||||||
|
3. **Security-Audit** → Wer hatte Zugriff auf welche Secrets?
|
||||||
|
4. **Compliance** → DSGVO verlangt Schutz sensibler Daten
|
||||||
|
|
||||||
|
#### Wie würde es integriert?
|
||||||
|
|
||||||
|
**Option A: HashiCorp Vault (Enterprise-Grade)**
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
vault:
|
||||||
|
image: hashicorp/vault:1.15
|
||||||
|
container_name: manacore-vault
|
||||||
|
ports:
|
||||||
|
- "8200:8200"
|
||||||
|
environment:
|
||||||
|
VAULT_DEV_ROOT_TOKEN_ID: "dev-token"
|
||||||
|
VAULT_DEV_LISTEN_ADDRESS: "0.0.0.0:8200"
|
||||||
|
cap_add:
|
||||||
|
- IPC_LOCK
|
||||||
|
volumes:
|
||||||
|
- vault_data:/vault/data
|
||||||
|
```
|
||||||
|
|
||||||
|
**Option B: Infisical (Einfacher, Open-Source)**
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
infisical:
|
||||||
|
image: infisical/infisical:latest
|
||||||
|
container_name: manacore-infisical
|
||||||
|
ports:
|
||||||
|
- "8080:8080"
|
||||||
|
environment:
|
||||||
|
ENCRYPTION_KEY: ${INFISICAL_ENCRYPTION_KEY}
|
||||||
|
MONGO_URL: mongodb://mongo:27017/infisical
|
||||||
|
depends_on:
|
||||||
|
- mongo
|
||||||
|
```
|
||||||
|
|
||||||
|
**Verwendung in Apps:**
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Statt process.env.DATABASE_PASSWORD
|
||||||
|
import { InfisicalClient } from "@infisical/sdk";
|
||||||
|
|
||||||
|
const client = new InfisicalClient({
|
||||||
|
token: process.env.INFISICAL_TOKEN,
|
||||||
|
});
|
||||||
|
|
||||||
|
const secret = await client.getSecret({
|
||||||
|
secretName: "DATABASE_PASSWORD",
|
||||||
|
environment: "production",
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 6. API Gateway (Kong)
|
||||||
|
|
||||||
|
#### Was ist das?
|
||||||
|
|
||||||
|
Ein **API Gateway** ist ein zentraler Eintrittspunkt für alle API-Anfragen. Es bietet:
|
||||||
|
- Authentifizierung & Autorisierung
|
||||||
|
- Rate Limiting
|
||||||
|
- Request/Response Transformation
|
||||||
|
- Caching
|
||||||
|
- Analytics
|
||||||
|
|
||||||
|
```
|
||||||
|
┌──────────┐ ┌─────────────────┐ ┌──────────────┐
|
||||||
|
│ Client │─────>│ Kong Gateway │─────>│ Backends │
|
||||||
|
│ (App) │ │ │ │ │
|
||||||
|
└──────────┘ │ • Auth prüfen │ │ chat-backend │
|
||||||
|
│ • Rate Limit │ │ todo-backend │
|
||||||
|
│ • Transform │ │ calendar-api │
|
||||||
|
│ • Cache │ │ etc. │
|
||||||
|
│ • Log │ │ │
|
||||||
|
└─────────────────┘ └──────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Warum braucht man das?
|
||||||
|
|
||||||
|
**Aktuell:**
|
||||||
|
- Jeder Backend-Service macht eigenes Rate-Limiting
|
||||||
|
- Auth wird in jedem Service einzeln geprüft
|
||||||
|
- Keine zentrale API-Übersicht
|
||||||
|
|
||||||
|
**Mit Kong:**
|
||||||
|
- Ein Ort für alle API-Regeln
|
||||||
|
- Einheitliche Rate-Limits
|
||||||
|
- API-Key Management
|
||||||
|
- Plugin-System für Erweiterungen
|
||||||
|
|
||||||
|
**Wann sinnvoll:**
|
||||||
|
- Viele externe API-Consumer
|
||||||
|
- Verschiedene Rate-Limits für verschiedene User
|
||||||
|
- API-Monetarisierung (Pläne, Quotas)
|
||||||
|
- Komplexe Auth-Anforderungen
|
||||||
|
|
||||||
|
**Wann NICHT nötig:**
|
||||||
|
- Nur interne Apps
|
||||||
|
- Wenige User
|
||||||
|
- Einfache Auth-Anforderungen
|
||||||
|
|
||||||
|
#### Wie würde es integriert?
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
kong:
|
||||||
|
image: kong:3.5
|
||||||
|
container_name: manacore-kong
|
||||||
|
environment:
|
||||||
|
KONG_DATABASE: "off"
|
||||||
|
KONG_DECLARATIVE_CONFIG: /etc/kong/kong.yml
|
||||||
|
KONG_PROXY_ACCESS_LOG: /dev/stdout
|
||||||
|
KONG_ADMIN_ACCESS_LOG: /dev/stdout
|
||||||
|
ports:
|
||||||
|
- "8000:8000" # Proxy
|
||||||
|
- "8001:8001" # Admin API
|
||||||
|
- "8443:8443" # Proxy SSL
|
||||||
|
volumes:
|
||||||
|
- ./kong/kong.yml:/etc/kong/kong.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
**Kong Config (kong.yml):**
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
_format_version: "3.0"
|
||||||
|
|
||||||
|
services:
|
||||||
|
- name: chat-api
|
||||||
|
url: http://chat-backend:3002
|
||||||
|
routes:
|
||||||
|
- name: chat-route
|
||||||
|
paths:
|
||||||
|
- /api/chat
|
||||||
|
plugins:
|
||||||
|
- name: rate-limiting
|
||||||
|
config:
|
||||||
|
minute: 100
|
||||||
|
policy: local
|
||||||
|
- name: key-auth
|
||||||
|
config:
|
||||||
|
key_names:
|
||||||
|
- X-API-Key
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Optionale Ergänzungen
|
||||||
|
|
||||||
|
### 7. CI/CD Runner
|
||||||
|
|
||||||
|
#### Was ist das?
|
||||||
|
|
||||||
|
Ein **CI/CD Runner** führt Build- und Deploy-Prozesse aus. Statt auf GitHub's Servern zu bauen, läuft alles lokal.
|
||||||
|
|
||||||
|
#### Warum könnte man das brauchen?
|
||||||
|
|
||||||
|
| Aspekt | GitHub Actions | Self-Hosted Runner |
|
||||||
|
|--------|---------------|-------------------|
|
||||||
|
| **Kosten** | Minuten-Limit (2000/Monat free) | Unbegrenzt |
|
||||||
|
| **Geschwindigkeit** | Geteilte Ressourcen | Dedizierte Hardware |
|
||||||
|
| **Secrets** | In GitHub gespeichert | Lokal |
|
||||||
|
| **Netzwerk** | GitHub → Server (langsam) | Lokal → Lokal |
|
||||||
|
| **ARM-Builds** | Extra Kosten | M4 native |
|
||||||
|
|
||||||
|
#### Wie würde es integriert?
|
||||||
|
|
||||||
|
**GitHub Actions Runner:**
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
github-runner:
|
||||||
|
image: myoung34/github-runner:latest
|
||||||
|
container_name: manacore-github-runner
|
||||||
|
environment:
|
||||||
|
REPO_URL: https://github.com/your-org/manacore-monorepo
|
||||||
|
RUNNER_TOKEN: ${GITHUB_RUNNER_TOKEN}
|
||||||
|
RUNNER_NAME: macmini-runner
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 8. Container Registry
|
||||||
|
|
||||||
|
#### Was ist das?
|
||||||
|
|
||||||
|
Eine **Container Registry** speichert Docker Images. Statt von Docker Hub zu pullen, hostest du deine eigenen Images.
|
||||||
|
|
||||||
|
#### Warum könnte man das brauchen?
|
||||||
|
|
||||||
|
- **Unabhängigkeit:** Keine Rate-Limits von Docker Hub
|
||||||
|
- **Geschwindigkeit:** Images lokal verfügbar
|
||||||
|
- **Privatsphäre:** Eigene Images nicht öffentlich
|
||||||
|
- **Kontrolle:** Welche Images wo deployed werden
|
||||||
|
|
||||||
|
#### Wie würde es integriert?
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
registry:
|
||||||
|
image: registry:2
|
||||||
|
container_name: manacore-registry
|
||||||
|
ports:
|
||||||
|
- "5000:5000"
|
||||||
|
volumes:
|
||||||
|
- registry_data:/var/lib/registry
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 9. Speech-to-Text (Whisper)
|
||||||
|
|
||||||
|
#### Was ist das?
|
||||||
|
|
||||||
|
**Whisper** ist OpenAI's Speech-to-Text Modell, das Audio in Text umwandelt. Es kann lokal laufen (whisper.cpp).
|
||||||
|
|
||||||
|
#### Warum könnte man das brauchen?
|
||||||
|
|
||||||
|
- **Matrix Clock Bot:** Sprachnachrichten → Zeiterfassung
|
||||||
|
- **Chat:** Voice Messages transkribieren
|
||||||
|
- **Meetings:** Aufnahmen transkribieren
|
||||||
|
- **Privacy:** Daten bleiben lokal
|
||||||
|
|
||||||
|
#### Wie würde es integriert?
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
whisper:
|
||||||
|
image: onerahmet/openai-whisper-asr-webservice:latest
|
||||||
|
container_name: manacore-whisper
|
||||||
|
ports:
|
||||||
|
- "9000:9000"
|
||||||
|
environment:
|
||||||
|
ASR_MODEL: small
|
||||||
|
ASR_ENGINE: faster_whisper
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
reservations:
|
||||||
|
devices:
|
||||||
|
- driver: nvidia
|
||||||
|
count: all
|
||||||
|
capabilities: [gpu]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Oder nativ auf Mac (Apple Silicon optimiert):**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
brew install whisper-cpp
|
||||||
|
whisper-cpp --model small.en audio.wav
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Noch nicht deployed (bereits entwickelt)
|
||||||
|
|
||||||
|
Diese Apps existieren bereits im Monorepo, sind aber noch nicht auf dem Server:
|
||||||
|
|
||||||
|
| App | Beschreibung | Status | Priorität |
|
||||||
|
|-----|--------------|--------|-----------|
|
||||||
|
| **Zitare** | Tägliche Inspirations-Zitate | Backend + Web fertig | Hoch |
|
||||||
|
| **Picture** | AI-Bildgenerierung | Braucht GPU/API | Mittel |
|
||||||
|
| **ManaDeck** | Kartenspiel/Deckbuilding | Backend + Web fertig | Niedrig |
|
||||||
|
| **Planta** | Pflanzenpflege-Tracker | In Entwicklung | Niedrig |
|
||||||
|
|
||||||
|
### Telegram Bots (nicht deployed)
|
||||||
|
|
||||||
|
| Bot | Beschreibung | Code vorhanden |
|
||||||
|
|-----|--------------|---------------|
|
||||||
|
| `telegram-todo-bot` | Todo-Management via Telegram | ✓ |
|
||||||
|
| `telegram-nutriphi-bot` | Ernährung loggen via Telegram | ✓ |
|
||||||
|
| `telegram-zitare-bot` | Tägliche Zitate via Telegram | ✓ |
|
||||||
|
| `telegram-project-doc-bot` | Projekt-Dokumentation | ✓ |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Priorisierte Roadmap
|
||||||
|
|
||||||
|
### Phase 1: Kritisch (Diese Woche)
|
||||||
|
|
||||||
|
```
|
||||||
|
1. ✅ Backup-Lösung einrichten
|
||||||
|
└── PostgreSQL + MinIO → Hetzner Storage Box
|
||||||
|
└── Täglich 3:00 Uhr
|
||||||
|
└── 7 Tage Daily, 4 Wochen Weekly, 12 Monate Monthly
|
||||||
|
|
||||||
|
2. ✅ Loki + Promtail
|
||||||
|
└── Alle Container-Logs zentral
|
||||||
|
└── Grafana-Integration
|
||||||
|
└── 30 Tage Retention
|
||||||
|
```
|
||||||
|
|
||||||
|
### Phase 2: Wichtig (Nächste 2 Wochen)
|
||||||
|
|
||||||
|
```
|
||||||
|
3. 📊 Uptime Kuma (extern)
|
||||||
|
└── Auf separatem VPS
|
||||||
|
└── Alle öffentlichen URLs überwachen
|
||||||
|
└── Telegram-Benachrichtigung
|
||||||
|
|
||||||
|
4. 🚀 Zitare deployen
|
||||||
|
└── Bereits entwickelt
|
||||||
|
└── Backend + Web Container hinzufügen
|
||||||
|
└── Cloudflare Tunnel Route
|
||||||
|
```
|
||||||
|
|
||||||
|
### Phase 3: Empfohlen (Nächster Monat)
|
||||||
|
|
||||||
|
```
|
||||||
|
5. 🔐 Secrets Management
|
||||||
|
└── Infisical oder Vault
|
||||||
|
└── Alle .env migrieren
|
||||||
|
└── Rotation einrichten
|
||||||
|
|
||||||
|
6. 🤖 Weitere Telegram Bots
|
||||||
|
└── todo-bot
|
||||||
|
└── zitare-bot
|
||||||
|
└── nutriphi-bot
|
||||||
|
```
|
||||||
|
|
||||||
|
### Phase 4: Optional (Backlog)
|
||||||
|
|
||||||
|
```
|
||||||
|
7. 🎙️ Whisper STT
|
||||||
|
└── Für Matrix Clock Bot
|
||||||
|
└── Voice → Zeiterfassung
|
||||||
|
|
||||||
|
8. 🏗️ CI/CD Runner
|
||||||
|
└── Wenn GitHub Actions Limit erreicht
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Zusammenfassung
|
||||||
|
|
||||||
|
| Service | Kategorie | Aufwand | Nutzen | Empfehlung |
|
||||||
|
|---------|-----------|---------|--------|------------|
|
||||||
|
| Backup (restic) | Kritisch | 2h | Datensicherheit | **Sofort** |
|
||||||
|
| Loki + Promtail | Kritisch | 1h | Debugging | **Sofort** |
|
||||||
|
| Uptime Kuma | Wichtig | 30min | Externe Überwachung | Diese Woche |
|
||||||
|
| Zitare | Wichtig | 1h | Bereits entwickelt | Diese Woche |
|
||||||
|
| Traefik/Caddy | Empfohlen | 2h | Einheitliches Routing | Wenn Zeit |
|
||||||
|
| Vault/Infisical | Empfohlen | 4h | Security | Wenn Zeit |
|
||||||
|
| Kong | Optional | 4h | API Management | Bei Bedarf |
|
||||||
|
| Whisper | Optional | 1h | Voice Features | Bei Bedarf |
|
||||||
|
| CI Runner | Optional | 2h | Build-Performance | Bei Bedarf |
|
||||||
|
|
||||||
|
Die wichtigste Erkenntnis: **Backups sind nicht optional.** Ohne automatisierte Backups ist es nur eine Frage der Zeit, bis Daten verloren gehen.
|
||||||
Loading…
Add table
Add a link
Reference in a new issue