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:
- Angemeldeter Spawner-User erstellt Rallly-Container
- Spawner-User richtet Rallly ein (wird Rallly-Admin beim ersten Setup)
- Öffentlicher Zugriff - jeder mit URL kann Rallly nutzen (OHNE Spawner-Login)
- 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:
-
Spawner-Ebene (Container erstellen):
- ✅ Nur angemeldete Spawner-User können Container erstellen
- ✅ User muss JWT-Token haben
-
Traefik-Routing (Container aufrufen):
- ✅ KEINE Authentifizierung - öffentlich zugänglich
- ✅ Jeder mit URL kann zugreifen
- ✅ Traefik routet direkt zum Container
-
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:
-
User öffnet:
https://coder.domain.com/{slug}-template-rallly -
Rallly zeigt Setup-Wizard:
- Admin-Account erstellen (Spawner-User Email)
- Passwort setzen
- Optionale Einstellungen
-
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
/datapersistiert 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:
- Liest
USER_TEMPLATE_IMAGESaus.env - Extrahiert Template-Namen (z.B.
user-template-rallly) - Baut Docker Image:
docker build -t user-template-rallly:latest ./user-template-rallly - 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/Dockerfileuser-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
- Admin-Dashboard öffnen:
https://coder.domain.com/admin - Prüfe: Wird "Rallly Scheduler" als Template angezeigt?
- Falls nicht: Server-Logs prüfen (
docker logs spawner)
- Falls nicht: Server-Logs prüfen (
5.2 User-Dashboard Test
- User-Dashboard öffnen:
https://coder.domain.com/dashboard - Container-Grid prüfen:
- Sollte "Rallly Scheduler" als Option zeigen
- Description: "Termin-Abstimmung und Planung mit Rallly"
5.3 Container Launch
- Klicke: "Erstellen & Öffnen" bei Rallly
- Erwartetes Verhalten:
- Container wird erstellt (
user-{slug}-template-rallly-{id}) - Traefik-Route wird konfiguriert
- Browser öffnet:
https://coder.domain.com/{slug}-template-rallly
- Container wird erstellt (
5.4 Rallly Setup (Spawner-User als Admin)
Erster Besuch (als Spawner-User):
- Öffne:
https://coder.domain.com/{slug}-template-rallly - Rallly zeigt Setup-Wizard
- Erstelle Admin-Account:
- Email: Spawner-User Email
- Name: Spawner-User Name
- Passwort: Wählen
- Setup abschließen
- SQLite-Datenbank wird erstellt:
/data/rallly.db
Rallly ist jetzt eingerichtet!
5.5 Öffentlichen Zugriff testen
Test 1: Event erstellen (als Admin)
- Login als Rallly-Admin
- Erstelle neues Event: "Team Meeting"
- Event-URL wird generiert:
https://coder.domain.com/{slug}-template-rallly/p/{event-id} - Kopiere URL
Test 2: Event öffnen (öffentlich, OHNE Login)
- Öffne Incognito/Private Browser (kein Spawner-Login!)
- Navigiere zu Event-URL:
https://coder.domain.com/{slug}-template-rallly/p/{event-id} - 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
- Teile Event-URL mit jemandem der KEINEN Spawner-Account hat
- Person öffnet URL
- 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:
- Erstelle einen zentralen PostgreSQL-Container
- Jeder User bekommt eigene Database + Credentials
- Rallly-Container bekommt
DATABASE_URLper Environment
Aufwand: ~2-3 Stunden Vorteil: Bessere Performance, Multi-User-Ready
Option B: Externe PostgreSQL-Anbindung
Falls bereits PostgreSQL-Server existiert:
- Rallly-Dockerfile: Entferne SQLite-Config
DATABASE_URLper Environment injizieren- Credentials per User generieren
Aufwand: ~1 Stunde Vorteil: Professionelle DB-Infrastruktur
Zusammenfassung
Was implementiert wird:
- ✅ Neues User-Template:
user-template-rallly - ✅ Rallly mit SQLite-Datenbank (Single-Container)
- ✅ Automatisches Build via
install.sh - ✅ Integration ins Dashboard (templates.json)
- ✅ 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:
- Erstelle
user-template-rallly/Dockerfile - Aktualisiere
templates.jsonund.env.example - Build Image mit
install.sh - Test Container lokal
- Commit + Push
- 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:
- Request:
https://coder.domain.com/{slug}-template-rallly/p/{event-id} - Traefik prüft: Host + PathPrefix Match?
- ✅ Route zu Container (Port 3000)
- ✅ KEINE Authentifizierung auf Traefik-Ebene
- 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/Dockerfileerstellttemplates.jsonerweitert (type: template-rallly).env.exampleaktualisiert- Image gebaut (
docker images | grep rallly) - Lokaler Container-Test erfolgreich
- Code committed & pushed
- Server
.envaktualisiert install.shauf 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