nginx was failing to start because:
- User directive needs root privileges (not applicable as coder user)
- Cannot write to /var/log/nginx/ (permission denied)
Solution:
- Use daemon off; in nginx config
- Redirect logs to /tmp instead of /var/log/nginx/
- Write complete nginx.conf with all required directives
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
code-server cannot handle being served under a subpath with Traefik StripPrefix.
Added nginx as reverse proxy that listens on 8080 and proxies to code-server
on 8081. This preserves all URLs and asset paths correctly.
- nginx listens on 0.0.0.0:8080 (external)
- code-server listens on 127.0.0.1:8081 (internal)
- Entrypoint starts nginx + socat + code-server
This fixes 404 errors on workbench.css and asset loading.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
code-server 4.111.0 does not support --base-path option.
Traefik StripPrefix middleware handles path removal instead.
This fixes the 'Unknown option --base-path' crash loop.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
The spawner_token cookie must be available for all user containers
running under subpaths (e.g., /e220dd278a12-template-dictionary/).
Added domain parameter to set_cookie() to make the JWT available
for all subdomains of BASE_DOMAIN.
This fixes the 401 'no token' error when accessing container APIs.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
After spawning a new container, wait until it's fully started and services
are ready before returning to the frontend. This prevents race conditions
where the frontend opens the container URL before the service is ready.
Solution: Wait loop (max 30s) for container.status == 'running',
then additional 2s for service startup (code-server, PlatformIO, etc).
This fixes the 404 error when opening a freshly spawned container.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
code-server needs to know its base path for correct asset loading.
The Traefik StripPrefix middleware removes the path before requests
reach the container, so assets were loading from wrong URLs.
Solution:
- Entrypoint script reads BASE_PATH env var and passes to code-server
- container_manager.py sets BASE_PATH=/{slug_with_suffix} for vcoder
- code-server now loads assets from correct relative paths
This fixes 404 errors on workbench.css, nls.messages.js, etc.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Changed from pinned versions (==) to flexible constraints (>=) to avoid
pip install conflicts on different systems/architectures.
This resolves docker build failures on Synology NAS with stricter pip resolver.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Integrates PlatformIO-based IDE for embedded systems development:
- user-template-vcoder/Dockerfile: code-server + PlatformIO + cpptools
- Persistent Volumes: Workspace + PlatformIO cache per user
- Auto Volume-Mount in container_manager.py for vcoder containers
- Updated templates.json with vcoder template metadata
- Updated .env.example with vcoder in USER_TEMPLATE_IMAGES
- Comprehensive documentation: docs/templates/VCODER_TEMPLATE.md
Users can now create isolated IDE containers with:
✓ code-server Web IDE (--auth=none, Spawner JWT protection)
✓ PlatformIO for ESP8266/Wemos development
✓ C/C++ IntelliSense (cpptools + clangd extensions)
✓ Persistent workspace and toolchain cache
Build time: 5-10 min (Extensions downloaded from GitHub)
Default resources: 512MB RAM, 0.5 CPU (configurable)
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- API calls were using absolute paths (/api/words) but container runs under path prefix
- Added apiBase variable to extract current pathname
- All fetch calls now use relative paths: ${apiBase}/api/words
- Fixes 404 errors when accessing Dictionary template through Traefik
- Before spawning new container with same user_id and container_type, delete all old containers with same config
- This prevents 'Router defined multiple times with different configurations' error from Traefik
- Implements solution B: Old containers are now automatically cleaned up
- Prevents 404 errors caused by Traefik routing conflicts
- Improved exception handling in /api/container/launch/<container_type>
- Check if start_container() returns False and recreate container if failed
- Check if get_container_status() returns 'not_found' and recreate container
- Previously, start_container() returning False was silently ignored
- Now automatically spawns new container from template if old one is missing
- Better logging for container state transitions
- Health Check uses 'import requests' but module was missing
- This caused container to be marked as unhealthy
- Added requests==2.31.0 to requirements.txt
- Frontend API now accepts container_ids parameter
- handleConfirmBulkDelete passes selected container IDs to API
- Backend filters containers by ID instead of deleting all
SQLAlchemy konnte nicht bestimmen welcher FK gemeint ist, da UserContainer
zwei FKs zu User hat (user_id und blocked_by).
Fehler: 'Could not determine join condition between parent/child tables
on relationship User.containers - there are multiple foreign key paths'
Lösung: foreign_keys=[user_id] explizit angeben.
**PHASE_7_SUMMARY.md**
High-level overview des gesamten Phase 7 Implementation
- Was wurde implementiert
- Deliverables Übersicht
- Security Features
- Code Statistics
- Tested Features
- Deployment Readiness
- User Experience Impact
- Integration mit bestehenden Features
- Checklisten für Production
- Support & Maintenance Guide
**Zielgruppe:** Project Manager, Tech Lead, DevOps
**Länge:** ~400 Zeilen
**Format:** Markdown mit Tables und Checklisten
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
**Neue Features:**
1. Container-Level Blocking: Admin kann einzelne Container blockieren/entsperren
2. User-Block Cascading: Wenn User gesperrt wird, werden automatisch alle seine Container blockiert
3. Launch-Protection: Blockierte Container können vom User nicht gestartet werden
4. Container-Verwaltungs-Tab im Admin-Dashboard mit Block/Unblock UI
5. Blocked-Status auf User-Dashboard mit visueller Markierung (rot)
6. Bulk-Operations für Container (Block/Unblock)
**Backend-Änderungen (admin_api.py):**
- GET /api/admin/users: Liefert nun auch Container-Liste mit is_blocked Status
- POST /api/admin/containers/<id>/block: Blockiert einzelnen Container
- POST /api/admin/containers/<id>/unblock: Entsperrt einzelnen Container
- POST /api/admin/containers/bulk-block: Blockiert mehrere Container
- POST /api/admin/containers/bulk-unblock: Entsperrt mehrere Container
- POST /api/admin/users/<id>/block: Cascade-Blockade aller Container (Phase 7)
**Backend-Änderungen (api.py):**
- GET /api/user/containers: Liefert is_blocked und blocked_at Felder
- POST /api/container/launch/<type>: Launch-Protection prüft is_blocked Flag
**Database-Änderungen (models.py):**
- UserContainer: Füge is_blocked, blocked_at, blocked_by Spalten hinzu
- Relationships für Blocker-Admin
**Frontend-Änderungen:**
- Admin-Dashboard: Neuer "Container-Verwaltung" Tab mit Grid-View
- Admin-Dashboard: Block/Unblock Buttons pro Container
- Admin-Dashboard: Bulk-Operations für Container-Selection
- User-Dashboard: Blocked-Badge und Blocked-Beschreibung in Container-Cards
- User-Dashboard: Disabled Button wenn Container blockiert
- User-Dashboard: Toast-Benachrichtigung bei Launch-Protection
**Migration:**
- Neue Datei: migrate_container_blocking.py für Database-Setup
Verwendung: python migrate_container_blocking.py
**Sicherheit:**
- Blockierte Container werden mit stop_container() gestoppt
- Lazy-Init des ContainerManager für robuste Error-Handling
- Separate Admin-Endpoints mit @admin_required() Decorator
- Audit-Logging aller Block/Unblock-Operationen
**Testing-Punkte:**
- User-Block blockiert alle Container? ✓ Cascading
- Container-Block wird auf User-Dashboard angezeigt? ✓ is_blocked prüfen
- Launch-Protection funktioniert? ✓ 403 Error bei is_blocked
- Admin-Container-Tab funktioniert? ✓ Grid-View mit Search
- Bulk-Operations funktionieren? ✓ Multiple Selection + Confirm
Fixes: #0 (Phase 7 Implementation)
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- VERSION in install.sh wird jetzt aus Git-Tags gelesen
- Format: git describe --tags --always
- Beispiel: v0.2.0 → zeigt VERSION=0.2.0 im Script
- Fallback auf 'dev' wenn keine Tags vorhanden
Vorteil: Version wird automatisch aktualisiert, keine manuelle Änderung nötig
- Neue .env Variable: CONTAINER_CREATE_TIMEOUT=10 (Sekunden)
- Frontend: Automatische Retries bei fehlgeschlagener Verifizierung
- Max 5 Versuche mit 2 Sekunden Delay zwischen Versuchen
- Gesamtzeit begrenzt auf 10 Sekunden (CONTAINER_CREATE_TIMEOUT)
- Bessere Fehlermeldungen für Timeout-Situation
Behebt Problem dass Verifizierung multiple 400-Fehler zeigt bevor sie funktioniert.
Dies passiert weil Container beim Spawn noch nicht bereit ist.
Mit Retries warten wir jetzt automatisch bis Container ready ist (max 10 Sek).
- Ersetze stash/pull durch git reset --hard origin/main
- Verhindert 'local changes would be overwritten' Fehler
- Synology ändert automatisch Berechtigungsbits (100644 vs 100755)
- Diese sind KEINE echten Code-Änderungen, daher direkt Remote-Version nehmen
- install.sh läuft jetzt vollautomatisch ohne Fehler
- Neuer Endpoint: POST /api/admin/config/reload
- Nur für Admins zugänglich
- Lädt .env neu mit load_dotenv()
- Aktualisiert alle Config-Werte in Flask
- Loggt welche Werte sich geändert haben
- LÖST das Problem dass .env Änderungen sonst Neustart brauchten
Verwendung:
curl -X POST http://localhost:5000/api/admin/config/reload -H "Authorization: Bearer $JWT_TOKEN"
Statt:
docker-compose down && docker-compose up -d
- container_manager.py: Pre-Check vor containers.run() hinzufügen
- Prüfe ob Container bereits existiert (z.B. nach Fehler)
- Wenn running: Wiederverwenden statt zu erstellen
- Wenn stopped: Versuchen zu starten oder zu löschen
- Verhindert Docker 409 Conflict-Fehler
- api.py: Container-Spawn Fehlerbehandlung verbessern
- Container-Spawn ist optional beim Signup
- User wird trotzdem erstellt wenn Spawn fehlschlägt
- JWT wird immer returned (Status 200)
- docs/BUGFIX_CONTAINER_SPAWN.md: Dokumentation hinzufügen
- Erklär die Probleme, Fixes und Testing
CRITICAL FIX for container routing bug:
- Replace all spawn_container() calls with spawn_multi_container()
- spawn_container() was overwriting primary container ID with single ID
- This caused all containers to route to same container-id
- Now each container_type gets its own route:
- spawner.wieland.org/slug-template-01
- spawner.wieland.org/slug-template-02
- spawner.wieland.org/slug-template-next
- Affects: Signup, Login, Container Restart endpoints
- Fixes: #CONTAINER-ROUTING