Files
MindSift/Doku/reverse-proxy.md
T
sandrodach 6343d62bab
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 59s
feat(realtime): implement SSE fallback, dual-transport hub & proxy resilience (resolves FLAW-03)
2026-10-26 16:55:11 +01:00

7.7 KiB

🛡️ Reverse-Proxy & WebServer-Konfigurationshandbuch

Dieses Dokument beschreibt die empfohlene Konfiguration von Reverse-Proxies und Ingress-Controllern für MindSift. MindSift nutzt eine hybride Realtime-Architektur bestehend aus bidirektionalen WebSockets und einem automatischen Server-Sent Events (SSE) Fallback, um selbst in restriktivsten Firmennetzwerken, hinter strikten Firewalls oder bei Deep-Packet-Inspection unterbrechungsfreie Live-Synchronisation zu gewährleisten.


⚡ Wichtige Anforderungen auf einen Blick

Protokoll Standard-Port Benötigte Header & Einstellungen Zweck
WebSockets 443 (WSS) / 80 (WS) Upgrade $http_upgrade
Connection "Upgrade"
proxy_read_timeout 3600s
Bidirektionale Yjs-CRDT-Synchronisation & Awareness
Server-Sent Events (SSE) 443 (HTTPS) / 80 (HTTP) X-Accel-Buffering: no
proxy_buffering off
proxy_cache off
Fallback bei blockiertem WebSocket-Upgrade
REST API & Uploads 443 (HTTPS) / 80 (HTTP) client_max_body_size 64M Notizen, Anhänge & CRDT-Zustandsblöcke

1. Nginx

Eine typische nginx.conf bzw. Site-Konfiguration unter /etc/nginx/sites-available/mindsift:

# Map für sauberes Connection-Handling bei WebSocket-Upgrades
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

server {
    listen 80;
    server_name mindsift.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name mindsift.example.com;

    ssl_certificate /etc/letsencrypt/live/mindsift.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/mindsift.example.com/privkey.pem;

    # Maximale Payload-Größe für Backups und große CRDT-Zustände
    client_max_body_size 64M;

    # MindSift Frontend & REST API
    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # 1. WebSocket Endpunkte (/api/v1/ws)
    location /api/v1/ws {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;

        # Upgrade-Header zwingend erforderlich
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # Verhindert vorzeitigen Verbindungsabbruch durch Proxy-Inaktivitäts-Timeout
        proxy_read_timeout 3600s;
        proxy_send_timeout 3600s;
    }

    # 2. Server-Sent Events Fallback (/api/v1/events)
    location /api/v1/events {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;

        # Pufferung zwingend deaktivieren für sofortiges Event-Streaming
        proxy_buffering off;
        proxy_cache off;
        proxy_set_header X-Accel-Buffering no;

        proxy_set_header Connection '';
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_read_timeout 86400s;
    }
}

2. Traefik (Docker Compose / Ingress)

Bei Verwendung von Traefik Version 2/3 müssen keine expliziten WebSocket-Upgrades deklariert werden, da Traefik diese transparent durchleitet. Für Server-Sent Events und Timeouts empfehlen sich Middleware-Definitionen:

version: '3.8'

services:
  mindsift:
    image: ghcr.io/sandrodach/mindsift:latest
    restart: unless-stopped
    environment:
      - PORT=8080
      - DB_PATH=/app/data/mindsift.db
    volumes:
      - ./data:/app/data
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.mindsift.rule=Host(`mindsift.example.com`)"
      - "traefik.http.routers.mindsift.entrypoints=websecure"
      - "traefik.http.routers.mindsift.tls.certresolver=letsencrypt"
      - "traefik.http.services.mindsift.loadbalancer.server.port=8080"

      # Verhindert Pufferung und hält persistente SSE-Streams am Leben
      - "traefik.http.middlewares.mindsift-buffering.buffering.maxRequestBodyBytes=67108864"
      - "traefik.http.routers.mindsift.middlewares=mindsift-buffering"

3. Caddy Server (Caddyfile)

Caddy unterstützt WebSockets und HTTP/2 Server-Sent Events von Haus aus vollständig ("out-of-the-box"):

mindsift.example.com {
    encode gzip zstd

    # Notizen, CRDT & Event-Stream ohne Pufferung weiterleiten
    reverse_proxy 127.0.0.1:8080 {
        # Streaming für SSE optimieren
        flush_interval -1
    }
}

4. Cloudflare Proxy (Orange Cloud)

Wird MindSift hinter dem Cloudflare CDN betrieben:

  1. WebSockets aktivieren:
    • Navigiere in das Cloudflare Dashboard: Network > WebSockets > Schalter auf ON stellen.
  2. Cloudflare Rocket Loader / Auto Minify:
    • Deaktiviere "Rocket Loader" für MindSift, da asynchrone Skripteingriffe die Yjs-CRDT-Initialisierung stören können.
  3. Cloudflare WAF / Bot Fight Mode:
    • Stelle sicher, dass GET /api/v1/events und GET /api/v1/ws* nicht von "Challenge"-Seiten blockiert werden.
  4. SSE-Unterstützung:
    • Cloudflare unterstützt Server-Sent Events nativ über HTTP/2 und HTTP/3. Dank der vom MindSift-Backend gesetzten Header X-Accel-Buffering: no und Cache-Control: no-cache streamt Cloudflare Echtzeit-Events verzögerungsfrei an die Clients.

5. Apache 2.4 (mod_proxy_wstunnel)

Unter Debian/Ubuntu:

sudo a2enmod proxy proxy_http proxy_wstunnel headers
sudo systemctl restart apache2

VirtualHost-Konfiguration (/etc/apache2/sites-available/mindsift.conf):

<VirtualHost *:443>
    ServerName mindsift.example.com
    SSLEngine on
    SSLCertificateFile /etc/letsencrypt/live/mindsift.example.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/mindsift.example.com/privkey.pem

    # 1. WebSocket Tunneling
    RewriteEngine On
    RewriteCond %{HTTP:Upgrade} =websocket [NC]
    RewriteRule /(.*)           ws://127.0.0.1:8080/$1 [P,L]
    RewriteCond %{HTTP:Upgrade} !=websocket [NC]
    RewriteRule /(.*)           http://127.0.0.1:8080/$1 [P,L]

    # 2. SSE Response Flushing
    <Location "/api/v1/events">
        ProxyPass "http://127.0.0.1:8080/api/v1/events" flushpackets=on
        ProxyPassReverse "http://127.0.0.1:8080/api/v1/events"
    </Location>

    ProxyPass / http://127.0.0.1:8080/
    ProxyPassReverse / http://127.0.0.1:8080/
</VirtualHost>

🔍 Diagnose & Verifikation

Mit den folgenden Befehlen lässt sich die Erreichbarkeit und Streaming-Funktion prüfen:

1. Server-Sent Events Test (Standard-HTTPS)

curl -N -H "Accept: text/event-stream" -H "Authorization: Bearer <DEIN_TOKEN>" https://mindsift.example.com/api/v1/events

Erwartete Ausgabe:

: connected (transport: sse, id: sse_...)
data: {"event":"SSE_CONNECTED","payload":{"sseId":"sse_...","transport":"sse"},"timestamp":"..."}
: ping

2. WebSocket Handshake Test

curl -i -N \
  -H "Connection: Upgrade" \
  -H "Upgrade: websocket" \
  -H "Host: mindsift.example.com" \
  -H "Origin: https://mindsift.example.com" \
  -H "Sec-WebSocket-Key: SGVsbG8sIHdvcmxkIQ==" \
  -H "Sec-WebSocket-Version: 13" \
  https://mindsift.example.com/api/v1/ws?token=<DEIN_TOKEN>

Erwartete Antwort: 101 Switching Protocols


🧭 Verwandte Dokumente