spawner/backlog/plan-rallly.md
2026-02-08 14:47:57 +01:00

18 KiB

Rallly User-Template Integration (Single-Container mit SQLite)

Übersicht

Ziel: Rallly als neues User-Template hinzufügen, kompatibel mit dem aktuellen Single-Container-System.

Ansatz: Rallly-Container mit SQLite-Datenbank (statt PostgreSQL aus dem Original-Compose-File).

Use-Case:

  1. Angemeldeter Spawner-User erstellt Rallly-Container
  2. Spawner-User richtet Rallly ein (wird Rallly-Admin beim ersten Setup)
  3. Öffentlicher Zugriff - jeder mit URL kann Rallly nutzen (OHNE Spawner-Login)
  4. Rallly-eigene Authentifizierung - Rallly hat eigenes User-Management

Vorteile:

  • Keine Architektur-Änderungen am Spawner-System
  • Passt ins bestehende Template-System
  • Automatisches Build via install.sh
  • Traefik-Routing funktioniert sofort (öffentlich zugänglich)
  • Keine Service-Dependencies
  • Rallly verwaltet eigene Benutzer

Zugriffs-Model & Authentifizierung

Wie funktioniert der öffentliche Zugriff?

Container-URL-Format:

https://coder.domain.com/{user-slug}-template-rallly

Zugriffskontrolle:

  1. Spawner-Ebene (Container erstellen):

    • Nur angemeldete Spawner-User können Container erstellen
    • User muss JWT-Token haben
  2. Traefik-Routing (Container aufrufen):

    • KEINE Authentifizierung - öffentlich zugänglich
    • Jeder mit URL kann zugreifen
    • Traefik routet direkt zum Container
  3. Rallly-Ebene (App-Nutzung):

    • Rallly-eigene Authentifizierung (optional)
    • Spawner-User wird beim ersten Setup zu Rallly-Admin
    • Rallly kann öffentlich oder mit Passwort genutzt werden

Rallly Setup-Flow

Beim ersten Container-Start:

  1. User öffnet: https://coder.domain.com/{slug}-template-rallly

  2. Rallly zeigt Setup-Wizard:

    • Admin-Account erstellen (Spawner-User Email)
    • Passwort setzen
    • Optionale Einstellungen
  3. Nach Setup:

    • Rallly-Admin kann Events erstellen
    • Events können öffentlich geteilt werden (URL)
    • Teilnehmer brauchen KEINEN Rallly-Account (je nach Settings)

Environment-Variablen für öffentlichen Zugriff

Im Dockerfile setzen:

# Öffentlicher Zugriff erlauben (keine Registrierung erforderlich für Teilnehmer)
ENV NEXT_PUBLIC_ENABLE_SELF_REGISTRATION=false

# Base URL für Rallly (für Link-Generierung)
ENV NEXT_PUBLIC_BASE_URL="https://coder.domain.com/{slug}-template-rallly"

# Session-Secret (wird pro Container generiert)
ENV SECRET_PASSWORD=$(openssl rand -base64 32)

Wichtig: Der Spawner-User richtet Rallly nur EINMAL ein. Danach ist Rallly unabhängig nutzbar.


Phase 1: Rallly Dockerfile erstellen

Dateien erstellen

Verzeichnis: user-template-rallly/

1.1 Dockerfile

Datei: C:\Users\Micro\OneDrive\Dokumente\spawner\user-template-rallly\Dockerfile

FROM lukevella/rallly:latest

# Setze Environment für SQLite (statt PostgreSQL)
ENV DATABASE_URL="file:/data/rallly.db"

# Session-Secret generieren (wird pro Build neu generiert)
# In Production sollte das pro Container-Instance individuell sein
ENV SECRET_PASSWORD="change-this-in-production"

# Öffentlicher Zugriff: Teilnehmer brauchen keinen Account
ENV NEXT_PUBLIC_ENABLE_SELF_REGISTRATION=false

# Support Email (optional, für Rallly-Footer)
ENV SUPPORT_EMAIL=""

# Erstelle Datenverzeichnis
RUN mkdir -p /data && chown -R node:node /data

# Volume für SQLite-Datenbank
VOLUME ["/data"]

# Port 3000 (Standard Rallly)
EXPOSE 3000

# Start Command (nutzt Original-Entrypoint)
CMD ["npm", "start"]

Wichtige Environment-Variablen:

Variable Wert Beschreibung
DATABASE_URL file:/data/rallly.db SQLite-Datenbank statt PostgreSQL
SECRET_PASSWORD Auto-generiert Session-Verschlüsselung (sollte pro Container unique sein)
NEXT_PUBLIC_ENABLE_SELF_REGISTRATION false Nur Admin kann Accounts erstellen (Event-Teilnehmer brauchen keinen Account)
SUPPORT_EMAIL leer Optional: Support-Email im Footer

Hinweis SECRET_PASSWORD: Idealerweise sollte SECRET_PASSWORD pro Container unique sein. Das kann später in container_manager.py beim Spawn injiziert werden:

# In container_manager.py (optional)
import secrets
environment = {
    'SECRET_PASSWORD': secrets.token_urlsafe(32)
}

Hinweise:

  • Rallly unterstützt SQLite nativ (Prisma ORM)
  • DATABASE_URL="file:/data/rallly.db" aktiviert SQLite
  • Volume /data persistiert Daten
  • Port 3000 wird von Traefik geroutet

1.2 .dockerignore (optional)

Datei: C:\Users\Micro\OneDrive\Dokumente\spawner\user-template-rallly\.dockerignore

node_modules
.git
.env
*.log

Phase 2: Template-Konfiguration

2.1 templates.json erweitern

Datei: C:\Users\Micro\OneDrive\Dokumente\spawner\templates.json

Änderung: Füge neuen Eintrag hinzu:

{
  "templates": [
    {
      "type": "template-01",
      "image": "user-template-01:latest",
      "display_name": "Nginx Basic",
      "description": "Einfacher Nginx-Server mit statischen Dateien"
    },
    {
      "type": "template-02",
      "image": "user-template-02:latest",
      "display_name": "Nginx Advanced",
      "description": "Erweiterter Nginx-Server mit Custom-Config"
    },
    {
      "type": "template-next",
      "image": "user-template-next:latest",
      "display_name": "Next.js App",
      "description": "Next.js Production Build mit Shadcn UI"
    },
    {
      "type": "template-rallly",
      "image": "user-template-rallly:latest",
      "display_name": "Rallly Scheduler",
      "description": "Termin-Abstimmung und Planung mit Rallly"
    }
  ]
}

2.2 .env aktualisieren

Datei: C:\Users\Micro\OneDrive\Dokumente\spawner\.env

Änderung: Erweitere USER_TEMPLATE_IMAGES:

# ALT:
USER_TEMPLATE_IMAGES="user-template-01:latest;user-template-02:latest;user-template-next:latest"

# NEU:
USER_TEMPLATE_IMAGES="user-template-01:latest;user-template-02:latest;user-template-next:latest;user-template-rallly:latest"

Wichtig: Semikolon-getrennte Liste ohne Leerzeichen!

2.3 .env.example aktualisieren (Dokumentation)

Datei: C:\Users\Micro\OneDrive\Dokumente\spawner\.env.example

Änderung: Gleiche Anpassung wie in .env:

USER_TEMPLATE_IMAGES="user-template-01:latest;user-template-02:latest;user-template-next:latest;user-template-rallly:latest"

Phase 3: Image bauen

3.1 Automatischer Build mit install.sh

Das install.sh Script erkennt automatisch neue Templates aus USER_TEMPLATE_IMAGES.

Kommando (lokal testen):

cd C:\Users\Micro\OneDrive\Dokumente\spawner

# Build nur Rallly-Template
docker build -t user-template-rallly:latest ./user-template-rallly

# ODER: Alle Templates neu bauen
bash install.sh

Was install.sh macht:

  1. Liest USER_TEMPLATE_IMAGES aus .env
  2. Extrahiert Template-Namen (z.B. user-template-rallly)
  3. Baut Docker Image: docker build -t user-template-rallly:latest ./user-template-rallly
  4. Zeigt Warnings wenn Verzeichnis fehlt

3.2 Verification nach Build

# Image prüfen
docker images | grep rallly
# Sollte zeigen: user-template-rallly:latest

# Container-Test (optional)
docker run -d --name test-rallly -p 3000:3000 user-template-rallly:latest
docker logs -f test-rallly

# Öffne Browser: http://localhost:3000
# Sollte: Rallly-Setup-Page zeigen

# Cleanup
docker stop test-rallly && docker rm test-rallly

Phase 4: Spawner-System Deployment

4.1 Code committen

Neue Dateien:

  • user-template-rallly/Dockerfile
  • user-template-rallly/.dockerignore (optional)

Geänderte Dateien:

  • templates.json
  • .env (Server)
  • .env.example (Dokumentation)

Commit:

cd C:\Users\Micro\OneDrive\Dokumente\spawner

git add user-template-rallly/ templates.json .env.example
git commit -m "feat: Add Rallly user-template with SQLite

- Rallly Scheduler als neues User-Template
- Single-Container mit SQLite-Datenbank (statt PostgreSQL)
- Volume /data für Datenpersistenz
- Port 3000 exponiert für Traefik-Routing
- Templates.json und .env.example aktualisiert"

git push origin main

4.2 Server Deployment

Auf dem Synology NAS / Server:

cd /volume1/docker/spawner

# Code pullen
git pull origin main

# .env aktualisieren (USER_TEMPLATE_IMAGES erweitern)
nano .env
# Füge hinzu: ;user-template-rallly:latest

# install.sh ausführen (baut neue Templates)
bash install.sh

# Spawner neu starten (lädt neue templates.json)
docker-compose up -d --build spawner

Wichtig: install.sh baut automatisch alle Templates aus USER_TEMPLATE_IMAGES.


Phase 5: Testing & Verification

5.1 Frontend-Check

  1. Admin-Dashboard öffnen: https://coder.domain.com/admin
  2. Prüfe: Wird "Rallly Scheduler" als Template angezeigt?
    • Falls nicht: Server-Logs prüfen (docker logs spawner)

5.2 User-Dashboard Test

  1. User-Dashboard öffnen: https://coder.domain.com/dashboard
  2. Container-Grid prüfen:
    • Sollte "Rallly Scheduler" als Option zeigen
    • Description: "Termin-Abstimmung und Planung mit Rallly"

5.3 Container Launch

  1. Klicke: "Erstellen & Öffnen" bei Rallly
  2. Erwartetes Verhalten:
    • Container wird erstellt (user-{slug}-template-rallly-{id})
    • Traefik-Route wird konfiguriert
    • Browser öffnet: https://coder.domain.com/{slug}-template-rallly

5.4 Rallly Setup (Spawner-User als Admin)

Erster Besuch (als Spawner-User):

  1. Öffne: https://coder.domain.com/{slug}-template-rallly
  2. Rallly zeigt Setup-Wizard
  3. Erstelle Admin-Account:
    • Email: Spawner-User Email
    • Name: Spawner-User Name
    • Passwort: Wählen
  4. Setup abschließen
  5. SQLite-Datenbank wird erstellt: /data/rallly.db

Rallly ist jetzt eingerichtet!

5.5 Öffentlichen Zugriff testen

Test 1: Event erstellen (als Admin)

  1. Login als Rallly-Admin
  2. Erstelle neues Event: "Team Meeting"
  3. Event-URL wird generiert: https://coder.domain.com/{slug}-template-rallly/p/{event-id}
  4. Kopiere URL

Test 2: Event öffnen (öffentlich, OHNE Login)

  1. Öffne Incognito/Private Browser (kein Spawner-Login!)
  2. Navigiere zu Event-URL: https://coder.domain.com/{slug}-template-rallly/p/{event-id}
  3. Erwartetes Verhalten:
    • Event wird angezeigt
    • KEIN Spawner-Login erforderlich
    • KEIN Rallly-Login erforderlich
    • Teilnehmer kann Name eingeben und abstimmen

Test 3: Öffentliche Nutzung ohne Spawner-Account

  1. Teile Event-URL mit jemandem der KEINEN Spawner-Account hat
  2. Person öffnet URL
  3. Erwartetes Verhalten:
    • Event ist zugänglich
    • Teilnahme möglich
    • Kein Spawner-Redirect

Daten-Persistenz prüfen:

# Container stoppen
docker stop user-{slug}-template-rallly-{id}

# Container neu starten
docker start user-{slug}-template-rallly-{id}

# Sollte: Daten sind noch da (SQLite Volume)
# - Admin-Account vorhanden
# - Events vorhanden
# - Teilnehmer-Antworten erhalten

5.5 Logs prüfen

# Rallly-Container-Logs
docker logs user-{slug}-template-rallly-{id}

# Sollte zeigen:
# - Prisma Migration erfolgreich
# - Server listening on port 3000
# - Keine Fehler

# Spawner-Logs
docker logs spawner | grep rallly

# Sollte zeigen:
# - Container erfolgreich erstellt
# - Traefik-Labels gesetzt

Kritische Dateien

Datei Status Beschreibung
user-template-rallly/Dockerfile NEU Rallly mit SQLite-Config
user-template-rallly/.dockerignore ⚠️ OPTIONAL Build-Optimierung
templates.json ✏️ ÄNDERN Rallly-Template-Metadaten
.env ✏️ ÄNDERN (Server) USER_TEMPLATE_IMAGES erweitern
.env.example ✏️ ÄNDERN Dokumentation

Häufige Probleme & Lösungen

Problem 1: Template erscheint nicht im Dashboard

Symptom: Rallly wird nicht in Container-Grid angezeigt.

Lösung:

# 1. Prüfe templates.json
cat templates.json | grep rallly
# Sollte Eintrag zeigen

# 2. Prüfe Config-Laden
docker logs spawner | grep "CONTAINER_TEMPLATES"

# 3. Spawner neu starten
docker-compose restart spawner

Problem 2: Container startet nicht

Symptom: "Container konnte nicht erstellt werden" Error.

Lösung:

# 1. Image prüfen
docker images | grep rallly
# Sollte: user-template-rallly:latest

# 2. Manueller Container-Test
docker run -d --name test-rallly \
  -e DATABASE_URL="file:/data/rallly.db" \
  -p 3000:3000 \
  user-template-rallly:latest

docker logs test-rallly
# Sollte: Keine Fehler

# 3. Traefik-Netzwerk prüfen
docker network ls | grep web
# Sollte existieren

Problem 3: SQLite-Daten gehen verloren

Symptom: Nach Container-Restart sind Daten weg.

Ursache: Volume nicht korrekt gemountet.

Lösung:

# Prüfe Volume
docker inspect user-{slug}-template-rallly-{id} | grep -A10 "Mounts"

# Sollte zeigen:
# - Source: /var/lib/docker/volumes/...
# - Destination: /data

# Falls nicht: container_manager.py anpassen
# Füge Volume-Mount hinzu in spawn_multi_container()

Fix in container_manager.py (falls nötig):

# Zeile ~200 in spawn_multi_container()
volumes = {
    f'rallly-data-{user_id}': {'bind': '/data', 'mode': 'rw'}
}

container = self._get_client().containers.run(
    image=image,
    volumes=volumes,  # NEU
    # ... rest of config
)

Problem 4: Port-Konflikt mit anderem Service

Symptom: Container startet aber ist nicht erreichbar.

Lösung:

# Prüfe Traefik-Labels
docker inspect user-{slug}-template-rallly-{id} | grep -A20 "Labels"

# Sollte zeigen:
# - traefik.http.routers.user{id}.rule = Host(...) && PathPrefix(...)
# - traefik.http.services.user{id}.loadbalancer.server.port = 3000

# Falls Port falsch: container_manager.py nutzt Port 8080 als Default
# Rallly braucht Port 3000

Fix (falls Port nicht 3000):

Rallly-Dockerfile anpassen:

# Am Ende des Dockerfile:
EXPOSE 3000

# ODER: Traefik-Port explizit setzen
ENV TRAEFIK_PORT=3000

Alternativen (falls SQLite nicht ausreicht)

Option A: Shared PostgreSQL (später)

Falls SQLite Performance-Probleme hat:

  1. Erstelle einen zentralen PostgreSQL-Container
  2. Jeder User bekommt eigene Database + Credentials
  3. Rallly-Container bekommt DATABASE_URL per Environment

Aufwand: ~2-3 Stunden Vorteil: Bessere Performance, Multi-User-Ready

Option B: Externe PostgreSQL-Anbindung

Falls bereits PostgreSQL-Server existiert:

  1. Rallly-Dockerfile: Entferne SQLite-Config
  2. DATABASE_URL per Environment injizieren
  3. Credentials per User generieren

Aufwand: ~1 Stunde Vorteil: Professionelle DB-Infrastruktur


Zusammenfassung

Was implementiert wird:

  1. Neues User-Template: user-template-rallly
  2. Rallly mit SQLite-Datenbank (Single-Container)
  3. Automatisches Build via install.sh
  4. Integration ins Dashboard (templates.json)
  5. Traefik-Routing (Port 3000)

Keine Breaking Changes:

  • Bestehende Templates unverändert
  • Keine Architektur-Änderungen
  • Keine DB-Migration erforderlich

Geschätzter Aufwand:

  • Dockerfile erstellen: 10 Minuten
  • Templates.json + .env: 5 Minuten
  • Build + Test: 15 Minuten
  • Deployment: 10 Minuten
  • Total: ~40 Minuten

Nächste Schritte nach Approval:

  1. Erstelle user-template-rallly/Dockerfile
  2. Aktualisiere templates.json und .env.example
  3. Build Image mit install.sh
  4. Test Container lokal
  5. Commit + Push
  6. Server-Deployment

Traefik-Routing & Öffentlicher Zugriff

Wie Traefik das Routing handhabt

Aktuelles System (container_manager.py):

# Traefik-Labels beim Container-Spawn
labels = {
    'traefik.enable': 'true',
    f'traefik.http.routers.user{user_id}.rule': f'Host(`{spawner_domain}`) && PathPrefix(`/{slug_with_suffix}`)',
    f'traefik.http.routers.user{user_id}.entrypoints': Config.TRAEFIK_ENTRYPOINT,
    f'traefik.http.services.user{user_id}.loadbalancer.server.port': '3000',  # Rallly-Port
    # WICHTIG: Kein Traefik-Auth-Middleware!
}

Routing-Flow:

  1. Request: https://coder.domain.com/{slug}-template-rallly/p/{event-id}
  2. Traefik prüft: Host + PathPrefix Match?
  3. Route zu Container (Port 3000)
  4. KEINE Authentifizierung auf Traefik-Ebene
  5. Container beantwortet Request

Wichtig: Das Spawner-System hat keine JWT-Auth für Container-Zugriffe. Nur für API-Endpoints!

Unterschied: API vs. Container

Endpoint Auth erforderlich? Beschreibung
/api/user/containers JWT Token Spawner API - Container-Liste abrufen
/api/container/launch JWT Token Spawner API - Container erstellen
/{slug}-template-rallly/* KEINE Auth User-Container - öffentlich via Traefik

Sicherheits-Überlegungen

Gut für Rallly:

  • Events sollen öffentlich teilbar sein
  • Teilnehmer brauchen keinen Spawner-Account
  • Rallly hat eigene Admin-Authentifizierung

Potentielle Bedenken:

  • ⚠️ Jeder mit URL kann Container nutzen (aber das ist gewollt!)
  • ⚠️ Rate-Limiting nur via Traefik (nicht per User)
  • ⚠️ Rallly-Admin sollte starkes Passwort setzen

Empfohlene Rallly-Settings (für Admin):

  • Admin-Passwort: Stark & unique
  • Self-Registration: Disabled (nur Admin erstellt Events)
  • Event-Visibility: Optional private Events

Verification Checklist

Setup & Deployment

  • user-template-rallly/Dockerfile erstellt
  • templates.json erweitert (type: template-rallly)
  • .env.example aktualisiert
  • Image gebaut (docker images | grep rallly)
  • Lokaler Container-Test erfolgreich
  • Code committed & pushed
  • Server .env aktualisiert
  • install.sh auf Server ausgeführt
  • Spawner neu gestartet

Funktionalität

  • Dashboard zeigt "Rallly Scheduler"
  • Container launch erfolgreich
  • Rallly erreichbar unter User-URL
  • Setup-Wizard erscheint beim ersten Start
  • Admin-Account erstellt (Spawner-User)
  • SQLite-Daten persistiert nach Restart

Öffentlicher Zugriff (WICHTIG!)

  • Event erstellt als Rallly-Admin
  • Event-URL generiert
  • Incognito-Browser: Event ohne Spawner-Login erreichbar
  • Incognito-Browser: Teilnahme ohne Rallly-Account möglich
  • Person OHNE Spawner-Account kann Event öffnen
  • Traefik routet korrekt (keine 401/403 Errors)
  • Teilnehmer-Antworten werden gespeichert