feat: add Docker deployment, web installer, and local test environment

- Multi-stage Dockerfiles for API (NestJS) and Web (Next.js standalone)
- docker-compose.prod.yml: full production stack (postgres, redis, keycloak,
  api, web) with optional Caddy/Let's Encrypt via --profile ssl
- docker-compose.local.yml: identical local test stack, all ports exposed
- docker/postgres/init.sql: auto-creates tos_app DB on first start
- Caddyfile: reverse proxy for app domain + auth subdomain
- install.sh: interactive installer (domain, SSL mode, secret generation)
- NestJS SetupModule: @Public() endpoints for /setup/status, /setup/admin,
  /setup/branding, /setup/complete with setup-token guard
- Web installer: 4-step flow (system check, admin creation, branding, complete)
  at /[locale]/setup/* with public middleware bypass
- i18n: installer namespace added to de.json and en.json
- CORS: x-setup-token header allowed in main.ts

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-23 21:17:34 +01:00
parent b1238b7bb8
commit 0e8d5aef85
31 changed files with 2158 additions and 4 deletions

View File

@@ -1073,5 +1073,63 @@
"saveError": "Fehler beim Speichern der Einstellungen",
"requiresRestart": "Aenderung erfordert einen Neustart des Backends",
"save": "Speichern"
},
"installer": {
"title": "tOS Einrichtung",
"setupComplete": "Einrichtung abgeschlossen",
"notAccessible": "Nach der Einrichtung ist dieser Bereich nicht mehr zugaenglich.",
"steps": {
"systemCheck": "Systempruefung",
"adminSetup": "Admin-Account",
"branding": "Branding",
"complete": "Abschluss"
},
"systemCheck": {
"title": "Systemueberpruefung",
"description": "Alle Dienste werden auf Erreichbarkeit geprueft.",
"api": "API-Server",
"database": "Datenbank",
"keycloak": "Authentifizierung",
"online": "Online",
"offline": "Nicht erreichbar",
"checking": "Wird geprueft...",
"continue": "Weiter zur Einrichtung",
"alreadyComplete": "Die Einrichtung wurde bereits abgeschlossen.",
"redirecting": "Du wirst zum Dashboard weitergeleitet..."
},
"adminSetup": {
"title": "Admin-Account erstellen",
"description": "Erstelle den ersten Administrator-Account fuer tOS.",
"firstName": "Vorname",
"lastName": "Nachname",
"email": "E-Mail-Adresse",
"password": "Passwort",
"passwordConfirm": "Passwort bestaetigen",
"passwordMismatch": "Passwoerter stimmen nicht ueberein",
"passwordTooShort": "Mindestens 8 Zeichen erforderlich",
"createAccount": "Account erstellen",
"creating": "Wird erstellt..."
},
"branding": {
"title": "Branding konfigurieren",
"description": "Passe tOS an dein Unternehmen an.",
"appName": "App-Name",
"appNamePlaceholder": "tOS",
"companyName": "Firmenname",
"companyNamePlaceholder": "Mein Unternehmen GmbH",
"logoUrl": "Logo-URL",
"logoUrlPlaceholder": "https://example.com/logo.png",
"logoPreview": "Logo-Vorschau",
"save": "Speichern & Weiter",
"saving": "Wird gespeichert...",
"skip": "Ueberspringen"
},
"complete": {
"title": "Einrichtung abgeschlossen!",
"description": "tOS wurde erfolgreich eingerichtet und ist bereit zur Nutzung.",
"completing": "Einrichtung wird abgeschlossen...",
"toDashboard": "Zum Dashboard",
"toLogin": "Zum Login"
}
}
}

View File

@@ -1073,5 +1073,63 @@
"saveError": "Failed to save settings",
"requiresRestart": "Change requires a backend restart",
"save": "Save"
},
"installer": {
"title": "tOS Setup",
"setupComplete": "Setup Complete",
"notAccessible": "After setup, this area will no longer be accessible.",
"steps": {
"systemCheck": "System Check",
"adminSetup": "Admin Account",
"branding": "Branding",
"complete": "Complete"
},
"systemCheck": {
"title": "System Check",
"description": "Checking all services for availability.",
"api": "API Server",
"database": "Database",
"keycloak": "Authentication",
"online": "Online",
"offline": "Unreachable",
"checking": "Checking...",
"continue": "Continue Setup",
"alreadyComplete": "Setup has already been completed.",
"redirecting": "Redirecting to dashboard..."
},
"adminSetup": {
"title": "Create Admin Account",
"description": "Create the first administrator account for tOS.",
"firstName": "First Name",
"lastName": "Last Name",
"email": "Email Address",
"password": "Password",
"passwordConfirm": "Confirm Password",
"passwordMismatch": "Passwords do not match",
"passwordTooShort": "Minimum 8 characters required",
"createAccount": "Create Account",
"creating": "Creating..."
},
"branding": {
"title": "Configure Branding",
"description": "Customize tOS for your company.",
"appName": "App Name",
"appNamePlaceholder": "tOS",
"companyName": "Company Name",
"companyNamePlaceholder": "My Company Inc.",
"logoUrl": "Logo URL",
"logoUrlPlaceholder": "https://example.com/logo.png",
"logoPreview": "Logo Preview",
"save": "Save & Continue",
"saving": "Saving...",
"skip": "Skip"
},
"complete": {
"title": "Setup Complete!",
"description": "tOS has been successfully set up and is ready to use.",
"completing": "Completing setup...",
"toDashboard": "Go to Dashboard",
"toLogin": "Go to Login"
}
}
}