User model now provides container_id and container_port as properties that
work with the new UserContainer relationship. This allows legacy code in
api.py to continue working without modifications. The properties automatically:
- Read from the primary (first) container
- Create a primary container on first write
- Maintain backwards compatibility with single-container API
- Add rotating file handler to app.py for logging to /app/logs/spawner.log
- Configure max 10MB per file with 5 backup files
- Update admin_api.py debug endpoint to read from Flask log file
- Implement clear-logs functionality to truncate log file
- Update documentation with Flask log file details
- Creates log directory automatically if missing
- Updated clear-logs to inform that docker logs cannot be deleted
- Updated documentation to reflect docker-based log reading
- No log file needed anymore"
- Move template loading after class definition to avoid NameError
- Initialize TEMPLATE_IMAGES, TEMPLATES_CONFIG, and CONTAINER_TEMPLATES after Config class
- Use simple loop instead of calling static methods during class init
- Prevents 'Config is not defined' errors during import
This fixes the circular dependency issue where _build_container_templates()
was trying to reference Config.TEMPLATE_IMAGES while the class was still
being defined.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- Fix USER_TEMPLATE_IMAGES quoting in .env.example (prevent bash metacharacter issues)
- Add all SMTP configuration variables to docker-compose environment
- Add EMAIL service variables (FRONTEND_URL, MAGIC_LINK_EXPIRY, RATE_LIMIT)
- Add JWT and resource limit variables
- Improve environment variable organization with comments
SMTP variables were defined in .env but not passed to container, causing
email service configuration issues.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
The install.sh script was only building user-template-next when
USER_TEMPLATE_IMAGE=user-template-next:latest was set in .env, which
was an old single-container configuration.
Changes:
- Remove dependency on USER_TEMPLATE_IMAGE for building user-template-next
- Always build user-template-next when directory exists
- Add user-template-next to TOTAL_BUILDS count automatically
- Change user-template-next build from optional warning to required
- Update build output to clearly show multi-container template building
- Update final installation summary to show template configuration
This ensures both dev and prod templates are always built for the
Multi-Container MVP, regardless of legacy .env settings.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Add step-by-step deployment instructions covering:
- Phase 1: Preparation (clean slate, build templates, configure env)
- Phase 2: Start services (docker-compose up, health checks)
- Phase 3: First registration (test user creation)
- Phase 4: Test both containers (dev and prod)
Includes:
- Verification checklist for backend, frontend, docker, traefik
- Detailed troubleshooting guide for common issues
- Monitoring and status commands
- Security checklist for production
- Performance scaling recommendations
- Next phase features for enhancement
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Add full support for 2 container types (development and production):
Backend Changes:
- New UserContainer model with unique constraint on (user_id, container_type)
- Removed single-container fields from User model (container_id, container_port)
- Added CONTAINER_TEMPLATES config with dev and prod templates
- Implemented spawn_multi_container() method in ContainerManager
- Added 2 new API endpoints:
* GET /api/user/containers - list all containers with status
* POST /api/container/launch/<type> - on-demand container creation
- Multi-container container names and Traefik routing with type suffix
Frontend Changes:
- New Container, ContainersResponse, LaunchResponse types
- Implemented getUserContainers() and launchContainer() API functions
- Completely redesigned dashboard with 2 container cards
- Status display with icons for each container type
- "Create & Open" and "Open Service" buttons based on container status
- Responsive grid layout
Templates:
- user-template-next already configured with Tailwind CSS and Shadcn/UI
Documentation:
- Added IMPLEMENTATION_SUMMARY.md with complete feature list
- Added TEST_VERIFICATION.md with detailed testing guide
- Updated .env.example with USER_TEMPLATE_IMAGE_DEV/PROD variables
This MVP allows each user to manage 2 distinct containers with:
- On-demand lazy creation
- Status tracking per container
- Unique URLs: /{slug}-dev and /{slug}-prod
- Proper Traefik routing with StripPrefix middleware
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- Use npm ci only if package-lock.json exists
- Falls back to npm install if not present
- Allows flexible package installation without strict lockfile requirement
Changes:
- If container exists but is not running: restart it
- If container_id exists but container was deleted: spawn new container
- If no container_id at all: spawn new container
- Adds detailed logging for container lifecycle
This ensures users always have a working container after login, even if the old one was deleted or didn't exist yet.
- Extract VerifySignupContent and VerifyLoginContent components
- Wrap components in Suspense boundary to avoid static generation errors
- Add loading spinner fallback during hydration
- Fixes 'useSearchParams() should be wrapped in a suspense boundary' error in Next.js 14
- Update formatDate() to accept string | null | undefined
- Fixes TypeScript error for optional last_used field in AdminUser
- Returns '-' if date is not available (null or undefined)
- Fix /dashboard route to use current_user.slug for service_url
- Fix /container/restart route to pass current_user.slug to spawn_container()
- Ensures legacy Flask-Login routes work with passwordless authentication
- Replace u.username with u.slug in search filter
- Replace user display names from username to email (primary identifier in passwordless auth)
- Update avatar fallbacks to use email initials
- Update handleDeleteUser parameter from username to userEmail
- Align admin page with new user identification scheme
- Remove handleResetPassword function (no longer needed with Magic Links)
- Change password reset button to send Magic Link instead
- Update button icon from KeyRound to Mail
- Update button tooltip to reflect new Magic Link flow
- Remove unused KeyRound import
Changes:
- install.sh: user-template-next is now only built if USER_TEMPLATE_IMAGE=user-template-next:latest is set in .env
* Defaults to user-service-template (nginx) to save 4-5 minutes per install
* Dynamic build step counting based on configured templates
* Shows helpful message when template is skipped
* Build numbering adapts automatically ([1/3] vs [1/4])
- user-template-next/Dockerfile: Optimize build performance
* Pin Node version to 20.11-alpine for reproducibility
* Use npm ci instead of npm install for faster, reproducible builds
* Separate package.json copy for better layer caching
* Add --prefer-offline and --no-audit flags to npm ci
* Clean npm cache to reduce image size
* Add clear comments for multi-stage build steps
Impact:
- Default installations: 2-3 minutes faster
- Reduced build time for Next.js template (when enabled) via layer caching
- Better reproducibility and predictable builds
- Added curl installation in Debian slim runner stage
- curl is required for healthcheck in docker-compose.yml
- curl is pre-installed in node:20-slim base image was incorrect assumption
- Healthcheck uses: curl -f http://localhost:3000/
- Cleaned up apt cache to keep image size minimal
- Switched from wget to curl for frontend healthcheck
- wget is not installed in node:20-slim (Debian-based)
- curl is pre-installed and compatible with Debian slim images
- Consistent with spawner API healthcheck (also uses curl)
- Changed FROM node:20-alpine to node:20-slim for both builder and runner stages
- Alpine (musl) is incompatible with Next.js SWC binary (glibc)
- Debian slim provides 80% smaller image compared to full node:20 (~180MB vs ~900MB)
- Fully compatible with Next.js and SWC without any patches
- Better performance and stability on Synology NAS
- All build logs now written to spawner-install.log
- Added clear section headers for each build
- Replaced separate temp log files with single log file
- Added log file path hint at end of installation
- FRONTEND_URL now generates correct URL from BASE_DOMAIN and SPAWNER_SUBDOMAIN
- Fixed German umlaut in email button: 'bestaetigen' → 'bestätigen'
- Added 'verified=true' parameter to backend redirect for hybrid approach
- Frontend now checks 'verified' parameter and shows error if not set
- Removed unused token logic from verify-success page (backend handles verification)
- Added warning UI for unverified emails with resend link
- Added Suspense boundary to verify-success/page.tsx
- Added Suspense boundary to verify-error/page.tsx
- Fixes build error: useSearchParams() should be wrapped in a suspense boundary
- Added Loader2 fallback UI for both pages
- CHANGELOG.md: Add v0.3.0 with admin dashboard, email verification,
user states, and all new features
- install/README.md: Add SMTP configuration variables
- README.md: Update version to 0.3.0
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>