taskmanager/README.Docker.md

8.0 KiB

Betrieb und Upgrade

Lokale Vorführung und Betriebsprüfungen

Eine vollständig getrennte Testinstanz mit Produktionsimages lässt sich über scripts/start-demo.ps1 starten; Zugang und Bedienung siehe TESTBETRIEB.md. Für den öffentlichen Betrieb die Demo-Konfiguration nicht übernehmen.

/api/health prüft die Datenbankverbindung. Der Web-Container besitzt einen Healthcheck, der Worker meldet erfolgreiche Durchläufe über einen lokalen Heartbeat. unhealthy muss vom Monitoring alarmiert werden; dieser Status allein löst keinen Docker-Neustart aus. Der Web-Container verwendet ein schreibgeschütztes Root-Dateisystem, ein privates Upload-Volume, ein begrenztes temporäres Dateisystem und keine Linux-Capabilities. Web- und operations-Container verwenden UID 1001.

scripts/backup.ps1 erstellt bei kurz angehaltenen App-/Worker-Diensten einen PostgreSQL-Dump und ein Upload-Archiv einschließlich Prüfsummen. Vorher laufende Dienste werden auch im Fehlerfall wieder gestartet. Backups und Secrets extern verschlüsselt aufbewahren. Wiederherstellung zunächst in einer separaten Datenbank und einem separaten Volume mit pg_restore --exit-on-error und tar üben, Dateiinhalte und Objektanzahlen prüfen. Niemals probeweise die laufende Produktionsdatenbank überschreiben.

Ein HTTPS-/Proxy-Beispiel mit Login-Ratenlimit, Upload-Sperre und unterdrückten Kalenderlink-Logs liegt in deploy/nginx.conf.example. Domain und Zertifikatspfade müssen angepasst werden. Aktuelle Sicherheitsgrenzen stehen in SECURITY.md.

Produktion mit Docker

  1. .env anhand .env.example erstellen. DATABASE_URL muss im Compose-Netz auf db:5432 zeigen, beispielsweise postgresql://taskmanager:<URL-kodiertes-Passwort>@db:5432/taskmanager. POSTGRES_PASSWORD zusätzlich in .env setzen. Keine Zugangsdaten committen.
  2. NEXTAUTH_URL auf die tatsächliche HTTPS-Adresse setzen; NEXTAUTH_SECRET zufällig generieren. Hinter dem Reverse Proxy HTTPS erzwingen, Upload-Requestlimit z.B. 11 MB setzen und /uploads/ auch dort sperren. TRUST_PROXY nur aktivieren, wenn der Proxy x-real-ip selbst setzt.
  3. docker compose build und docker compose up -d db.
  4. docker compose run --rm migrate führt Schema- und RBAC-Datenmigration aus.
  5. Bei Neuinstallation einmalig docker compose run --rm migrate npm run prisma:seed mit gesetzten Bootstrap-Werten ausführen. Anschließend Bootstrap-Werte entfernen.
  6. docker compose up -d app worker. Genau eine Worker-Instanz betreiben. App-Port ist nur an 127.0.0.1 gebunden; öffentliche Auslieferung über HTTPS-Proxy.

Der Web-Container läuft als UID/GID 1001. Anhänge liegen auf einem privaten Volume /app/private-uploads, nicht unter public. Das Runtime-Image enthält die Next.js-Standalone-Ausgabe; Migrations- und Worker-Werkzeuge befinden sich im separaten operations-Target. Der Web-Start erzeugt keine Benutzer und führt kein Seed aus.

Upgrade einer vorhandenen Installation

  1. Wartungsfenster: alte App und Worker stoppen, PostgreSQL und das bisherige Upload-Volume sichern. Die Backups müssen zusammenpassen. Rückweg vor Beginn anhand eines Restores testen.
  2. Neues Image bauen. Schema-Migration und anschließend scripts/migrate-access.ts ausführen. Das Skript normalisiert E-Mails, bricht bei Kollisionen ab, legt die Bestandsgruppe an, ordnet vorhandene Rollen zu und macht alte JWTs ungültig. Mehrfache Ausführung ist idempotent.
  3. ADMIN wird Systemadministrator/GLOBAL. BEARBEITER wird Bearbeiter/ASSIGNED. PFLEGER wird Koordinator/GLOBAL plus Bearbeiter/ASSIGNED. VORGESETZTER wird Teamleitung/GLOBAL und erhält nicht automatisch Rechteverwaltung. Anschließend globale Altzuweisungen organisatorisch auf Gruppen eingrenzen.
  4. Altes Upload-Volume zusätzlich in den operations-Container einhängen, z.B. unter /legacy-uploads; neues privates Volume nach /app/private-uploads. LEGACY_UPLOAD_DIR und UPLOAD_DIR entsprechend setzen und npx tsx scripts/migrate-uploads.ts ausführen. Das Skript prüft die tatsächlichen Dateitypen, kopiert in privaten Speicher, aktualisiert DB-Pfade und entfernt erfolgreich migrierte Altdateien. Bei ungültigen/vermissten Dateien bricht es ab; diese Fälle vor dem Start bearbeiten. Nicht referenzierte Altdateien separat prüfen. Kein automatisches rekursives Löschen alter Verzeichnisse.
  5. Neue App starten. Sicherstellen, dass der Proxy alte /uploads/-Links nicht selbst statisch bedient. Stichprobe: erneuter Login, eigene/fremde Aufgaben, Download nach Rollenentzug, Änderungskonflikt und Archivwiederherstellung.

Nach Migration nicht einfach die alte Anwendung weiterbetreiben: deren Rechteprüfungen und öffentliche Uploadpfade sind unsicher. Rollback erfordert Wiederherstellung des zusammengehörigen DB-/Datei-Backups und eine Entscheidung über währenddessen entstandene Daten.

E-Mail, OIDC und Webhooks

  • SMTP_URL und MAIL_FROM aktivieren Einladung, Reset und Erinnerungen. Passwortlinks sind eine Stunde gültig und einmal verwendbar. Tokens stehen im URL-Fragment und nicht im HTTP-Zugriffslog.
  • OIDC_ISSUER, OIDC_CLIENT_ID und OIDC_CLIENT_SECRET setzen. Callback: /api/auth/callback/oidc. Benutzer werden nicht automatisch per E-Mail verknüpft; den exakten Provider-Subject in der Benutzerverwaltung hinterlegen. Bei verknüpften Konten ist die lokale Passwortanmeldung gesperrt. MFA beim Identity Provider erzwingen; optional OIDC_REQUIRED_ACR setzen, dann wird der zurückgelieferte ACR-Wert geprüft. Echte Provider-Anmeldung erfordert Konfiguration und Abnahme am Zielsystem.
  • WEBHOOK_ALLOWED_HOSTS enthält ausschließlich exakte freigegebene öffentliche HTTPS-Hosts. Der Worker lehnt private IPs und Redirects ab. Payload enthält Ereignis-ID, Aktion, Objekt-ID und Zeitpunkt, keine Geheimnisse oder vollständigen Aufgabeninhalte. Signatur: HMAC-SHA256 über <timestamp>.<body>, Header X-Taskmanager-Timestamp und X-Taskmanager-Signature. Empfänger müssen Timestamp und Ereignis-ID gegen Replay/Duplikate prüfen.
  • Kalenderlinks sind widerrufbare Geheimnisse mit 90 Tagen Laufzeit. /api/calendar/* im Reverse-Proxy-Log redigieren, Links nicht weitergeben. Alternativ lesenden API-Token im Authorization-Header verwenden.

Worker und Aufbewahrung

Der Worker läuft im Minutenabstand: Erinnerungen, Eskalationen, Wiederholungsaufgaben, E-Mail, Dateibereinigung, Webhookzustellung und Ablaufbereinigung. Wiederholungsaufgaben werden je Ausgangsaufgabe genau einmal angelegt. Reminder werden je Aufgabe/Version/Benutzer/Tag dedupliziert. E-Mail/Webhooks haben At-least-once-Semantik; ein Prozessabsturz nach Versand kann Duplikate erzeugen. Webhooks erhalten höchstens fünf Versuche. Monitoring muss Worker-Ausfälle und fehlgeschlagene Zustellungen erfassen.

ARCHIVE_RETENTION_DAYS=0 bewahrt Archive unbegrenzt. Erst ein ausdrücklich gesetzter Wert ab 30 aktiviert endgültige automatische Löschung archivierter, erledigter Aufgaben. Die Dateibereinigung arbeitet über wiederholbare Cleanup-Jobs. Audit-Ereignisse werden dadurch nicht gelöscht.

Datenbank, private Anhänge und die verwendeten Secrets regelmäßig sichern; Restore testen. Das Audit-Log ist anwendungsseitig nur lesbar, aber kein manipulationssicheres externes Archiv. Malware-Scanning und externe Log-/Backup-Dienste sind Infrastrukturentscheidungen und nicht automatisch aktiviert.

Grenzen und Abnahme

CSV/XLSX-Import: maximal 100 Zeilen/100 KB, eine Tabelle, keine Excel-Formeln. Batchaktionen verarbeiten maximal 50 Aufgaben und melden Teilerfolge pro Aufgabe; bereits erfolgreiche Zeilen werden nicht zurückgerollt. Export: maximal 5000 Aufgaben. Kommentare im Detail: letzte 100 (weitere Seiten über API); Audit im Detail: letzte 50. Berichte mitteln maximal die letzten 1000 abgeschlossenen Aufgaben. Diese Grenzen sind keine Berechtigungsgrenzen.

Die PWA bleibt online: vertrauliche Aufgaben werden nicht als Offline-Kopie im Service Worker gespeichert. Native lokale MFA ist nicht implementiert; MFA erfolgt über den optionalen OIDC-Provider. Produktive SMTP-/OIDC-/Webhook-Zustellung und Last-/Backup-Tests müssen mit der Zielinfrastruktur abgenommen werden.