Eviworx
Docs

Architektur-Übersicht

Eviworx besteht aus 12 Containern mit jeweils eigener Aufgabe. Backend und Worker lassen sich mehrfach betreiben; Details unter Multi-Instance Setup.

Container-Übersicht

Container Technologie Funktion Ports
traefik Traefik v3 API-Gateway, TLS-Termination, Routing, Rate-Limiting 80, 443
frontend React 19+ + NGINX Single Page Application (SPA) 80
backend Node.js + Express REST API & Geschäftslogik 3000
job-worker Node.js + BullMQ CronJobs & geplante Aufgaben (28 Action-Types) 3001
email-worker Node.js + BullMQ E-Mail-Queue-Processing (IMAP/SMTP, Graph API) 3005
notification-worker Node.js + BullMQ Multi-Channel-Notifications (Teams Bot Framework, Webex), Attachment-Support, Quiet Hours 3006
workflow-engine Node.js Business-Process-Management (8 Node-Typen) 3003
av-worker Node.js Virus-Scan-Orchestrator (Zero-Trust) 3007
report-generator Node.js + BullMQ Custom Reports, CSV/PDF-Export (Read-Only DB) 3004
db PostgreSQL 17 Primäre Datenbank (150+ Modelle) 5432
redis Redis 8 Cache, Job-Queue & Distributed Locks 6379
clamav ClamAV Virus-Scanner-Daemon 3310

Architektur-Diagramm

                          User (Browser)
                               |
                               | HTTPS (443) / HTTP (80)
                               v
                    +---------------------+
                    |      TRAEFIK        |
                    |  (API Gateway v3)   |
                    |  TLS-Termination    |
                    |  Rate-Limiting      |
                    +---------------------+
                       |             |
          /_app/*      |             |  /api/*
          / (SPA)      |             |
                       v             v
            +-------------+   +-------------+
            |  FRONTEND   |   |   BACKEND   |
            | (React SPA) |   | (Express)   |
            |  NGINX :80  |   |   :3000     |
            +-------------+   +------+------+
                                     |
              +----------+-----------+----------+-----------+
              |          |           |          |           |
              v          v           v          v           v
         +--------+ +--------+ +--------+ +--------+ +----------+
         |  Job   | | Email  | | Notif. | |Workfl. | | Report   |
         | Worker | | Worker | | Worker | | Engine | | Generator|
         | :3001  | | :3005  | | :3006  | | :3003  | | :3004    |
         +--------+ +--------+ +--------+ +--------+ +----------+
              |          |           |          |           |
              v          v           v          v           v
         +--------+ +--------+                        +--------+
         |  AV    | | Redis  |                        |  DB    |
         | Worker | | :6379  |                        | :5432  |
         | :3007  | +--------+                        +--------+
         +---+----+
             |
             v
         +--------+
         | ClamAV |
         | :3310  |
         +--------+

Komponenten-Details

Traefik (API-Gateway)

  • Technologie: Traefik v3
  • Aufgabe: API-Gateway, TLS-Termination, Routing, Rate-Limiting, CSP-Header
  • Routing:
    • /api/* → Backend (:3000)
    • Interne Schnittstellen zwischen den Diensten sind von außen nicht erreichbar (Traefik sperrt sie)
    • Alles andere → Frontend (:80)
  • Health-Check: Ping Entrypoint
  • Datenbank-Zugriff: Keiner
  • Externer Reverse Proxy: forwardedHeaders.trustedIPs in traefik.yml + TRUSTED_PROXIES in .env konfigurieren (Details)

Frontend (React 19+ + NGINX)

  • Technologie: React 19.2.0, Vite, Tailwind CSS 4, shadcn/ui
  • Aufgabe: Single Page Application (SPA)
  • NGINX: Static-File-Serving, SPA-Routing; gehashte Build-Dateien liegen unter /_app/ (Cache-Regeln)
  • Kommunikation: REST API → Backend (Port 3000)

Backend (Node.js + Express)

  • Technologie: Node.js, Express, Prisma ORM, Zod Validation
  • Aufgabe: Zentrale Geschäftslogik & API
  • APIs:
    • REST API (Public) – Für Frontend & externe Clients
    • Internal API – Für Worker-Kommunikation (API-Key-geschützt)
  • Datenbank-Zugriff: Vollzugriff (Benutzer: helpdesk_user)

Job-Worker (CronJobs & Automation)

  • Technologie: Node.js, BullMQ
  • Aufgabe: Scheduled Jobs & Automation-Actions
  • Action-Types (28, Auswahl):
    • Webhook (HTTP-Aufrufe mit SSRF-Schutz)
    • Assign Agent/Group
    • Create/Update Ticket
    • Report Schedule Check (geplante Reports)
    • Asset Model Clustering
    • SLA Monitor
    • Attachment Cleanup, Retention Purge
    • Workload Sync
    • und weitere...
  • Datenbank-Zugriff: Eingeschränkt (nur CronJob-Tabellen)
  • Kommunikation: Internal API für alle Domain-Daten
  • Multi-Instance: Redis Distributed Locks

Email-Worker

  • Technologie: Node.js, BullMQ, Nodemailer
  • Aufgabe: E-Mail-Queue-Processing & IMAP-Polling
  • Eingehende E-Mails: IMAP-Polling / Graph API → Tickets erstellen
  • Ausgehende E-Mails: SMTP / Graph API Versand via Queue
  • Datenbank-Zugriff: Keiner (alles via Internal API)

Notification-Worker

  • Technologie: Node.js, BullMQ
  • Aufgabe: Multi-Channel-Notifications (Teams Bot Framework, Webex)
  • Kanäle:
    • Microsoft Teams (via Bot Framework)
    • Webex (via REST API)
    • E-Mail (delegiert an Email-Worker)
  • Features: Attachment-Support, Quiet Hours
  • Two-Tier-Routing: Backend → Notification-Worker → Channel-spezifischer Adapter
  • Datenbank-Zugriff: Keiner (alles via Internal API)

Workflow-Engine

  • Technologie: Node.js, BullMQ
  • Aufgabe: Business-Process-Management
  • Node-Typen (8):
    • Manual Task – Manuelle Aufgaben für User
    • Approval – Approval-Steps mit Auto-Approval
    • Automated Action – API-Calls, Webhooks
    • Notification – Benachrichtigungen versenden
    • Parallel Gateway – Mehrere Pfade parallel
    • Conditional Branch – If/Else-Verzweigung
    • Data Collection – Daten sammeln (Forms)
    • Timer Event – Delay oder Deadline
  • Datenbank-Zugriff: Keiner (alles via Internal API)
  • Multi-Instance: Redis Locks für Step-Processing

AV-Worker (Virus-Scan-Orchestrator)

  • Technologie: Node.js
  • Aufgabe: Koordiniert Virus-Scans (Zero-Trust)
  • Zero-Trust: Der AV-Worker hat keinen Zugriff auf die Dateien.
  • Ablauf:
    1. Backend legt File in /app/uploads
    2. AV-Worker übergibt ClamAV nur den Dateipfad (via TCP)
    3. ClamAV liest File vom eigenen Volume
    4. AV-Worker aktualisiert Status via Internal API
  • Quarantäne: Infizierte Dateien automatisch nach /app/quarantine (7 Tage Retention)

Report-Generator

  • Technologie: Node.js, BullMQ
  • Aufgabe: Custom Reports, CSV/PDF-Export
  • Datenbank-Zugriff: Read-Only (helpdesk_readonly)
  • Health-Check: GET /health/live (Port 3004)

PostgreSQL (Datenbank)

  • Version: PostgreSQL 17 Alpine
  • Datenmodell: 150+ Prisma-Modelle in ~50 Domains
  • Benutzer:
    • helpdesk_user – Vollzugriff (Backend)
    • helpdesk_jobworker – Eingeschränkt (nur CronJob-Tabellen)
    • helpdesk_readonly – Read-Only (Report-Generator)
  • Volumes: postgres_data (Persistente Daten)

Redis (Cache & Queue)

  • Version: Redis 8 Alpine
  • Authentifizierung: Passwortgeschützt (--requirepass)
  • Verwendung:
    • Cache: RBAC-Permissions, Session-Cache, Audit-Chain-Fallback
    • Job-Queue: BullMQ für alle Worker (Email, Notification, Jobs)
    • Distributed Locks: Koordination zwischen Instanzen
  • Persistenz: AOF (Append-Only-File) – Queue-Daten bleiben bei einem Neustart erhalten

ClamAV (Virus-Scanner)

  • Version: ClamAV 1.5 (offizielles Image)
  • Aufgabe: Virus-Scanning-Daemon
  • Signature-Updates: 24x/Tag – stündlich (Freshclam, FRESHCLAM_CHECKS=24)
  • Volume-Zugriff: /app/uploads (read-only)
  • Ressourcen: 2 GB RAM Limit, 2 CPUs

Kommunikationsflüsse

1. User-Request (via Traefik)

User → Traefik (HTTPS :443) → Frontend (React SPA) OR Backend (REST API) → PostgreSQL
                                                                    ↓
                                                                Redis (Cache)

2. Worker-Kommunikation (Zero-Database-Access)

Worker → Backend (Internal API) → PostgreSQL
   ↓
Redis (Job Queue + Locks)

Wichtig: Die Worker Email, Notification, Workflow und AV haben keinen direkten Datenbank-Zugriff; sie rufen alle Daten über die Internal API ab. Der Job-Worker hat eingeschränkten DB-Zugriff (nur CronJob-Tabellen), der Report-Generator nur lesenden (helpdesk_readonly).

3. Notification-Flow (Two-Tier-Routing)

Backend → Redis (notification:enqueue Queue)
            ↓
Notification-Worker → fetches User/Template via Internal API
            ↓
  +---------+---------+
  v         v         v
Email    Teams     Webex
Worker   Bot       API
         Framework

4. Virus-Scan-Flow (Zero-Trust)

Backend → Uploads file to /app/uploads → Creates DB entry (status: PENDING)
            ↓
AV-Worker (polling every 10s) → Fetches pending files via Internal API
            ↓
AV-Worker sends ONLY file path (NOT content!) to ClamAV via TCP
            ↓
ClamAV reads file from shared volume /app/uploads (read-only)
            ↓
ClamAV returns: CLEAN / INFECTED
            ↓
AV-Worker updates status via Internal API
            ↓
If INFECTED: Backend moves file to /app/quarantine

Security-Architektur

Principle of Least Privilege

Container Datenbank-Zugriff Begründung
Traefik None Kein DB-Zugriff; sperrt interne Schnittstellen nach außen
Backend Full (helpdesk_user) Zentrale Geschäftslogik benötigt vollen Zugriff
Job-Worker Restricted (helpdesk_jobworker) Nur CronJob-Tabellen (CronJob, JobExecution, WorkerInstance)
Report-Generator Read-Only (helpdesk_readonly) Nur lesender Zugriff für Reports/Analytics
Email-Worker None Daten via Internal API – kein DB-Zugriff nötig
Notification-Worker None Daten via Internal API
Workflow-Engine None Daten via Internal API
AV-Worker None Daten via Internal API – Zero-Trust

Network-Isolation

  • Alle Container im gleichen Docker-Netzwerk (isolated)
  • Nur Traefik exposed (Ports 80/443)
  • Backend/Worker/Frontend nicht direkt erreichbar von außen
  • Inter-Container-Kommunikation via DNS (z.B. http://backend:3000)

Multi-Instance Setup (High Availability)

Eviworx ist für Active-Active-Deployments konzipiert. Mehrere Instanzen können parallel laufen.

Distributed Locks (Redis-basiert)

  • Job-Worker: Lock pro CronJob (nur eine Instanz führt Job aus)
  • Workflow-Engine: Lock pro Workflow-Step
  • Implementierung: Redlock-Algorithm

Worker-Heartbeat-Monitoring

  • Jede Worker-Instanz trägt sich per Heartbeat in die Redis-Health-Registry ein
  • Heartbeat alle 15 Sekunden, der Eintrag verfällt nach 30 Sekunden
  • Instanzen ohne Heartbeat gelten als offline; ihre Ausführungs-Historie bleibt sichtbar
  • Stuck Jobs werden neu verteilt (Recovery-Logik)

Load-Balancing

  • Traefik: Zentraler Load-Balancer & API-Gateway
  • Backend: Mehrere Instanzen hinter Traefik
  • Worker: Automatisch via BullMQ (Pull-based)

Datenfluss-Beispiele

Beispiel 1: Ticket erstellen

1. User fills out ticket form (Frontend)
2. Frontend → POST /api/tickets (via Traefik → Backend)
3. Backend:
   - Validates input (Zod schema)
   - Checks permissions (RBAC)
   - Creates ticket in PostgreSQL
   - Creates audit-chain event
   - Enqueues notification (Redis)
4. Notification-Worker (async):
   - Fetches User/Template via Internal API
   - Sends email/Teams/Webex
5. Frontend receives response (201 Created)

Beispiel 2: Scheduled Job (CronJob)

1. CronJob defined: "Every day at 9am: Generate Report"
2. Job-Worker (Scheduler):
   - Checks all jobs (via DB)
   - Finds job with cron expression "0 9 * * *"
   - Acquired Distributed Lock (Redis)
3. Job-Worker runs action:
   - Action: GenerateReport
   - Fetches report data via Internal API
   - Generates PDF
   - Stores in /app/uploads
   - Enqueues email notification
4. Email-Worker:
   - Sends report by email
5. Job-Worker updated execution status (SUCCESS)

Beispiel 3: Workflow-Ausführung

1. User starts workflow (e.g. "Onboarding Workflow")
2. Backend:
   - Creates workflow instance
   - Enqueues start event
3. Workflow-Engine:
   - Fetches Instance via Internal API
   - Processes step by step
   - Step 1: Manual Task → assignee notification
   - Step 2: Approval → waits for user input
   - Step 3: Automated Action → webhook call
   - Step 4: Notification → Teams message
4. On each step:
   - Acquired Lock (Redis)
   - Updates step status via Internal API
   - Release Lock
5. Workflow completed → status: COMPLETED

Volumes & Persistenz

Volume Verwendet von Zweck
postgres_data db Persistente Datenbankdaten
redis_data redis AOF-Persistenz für Job-Queue
uploads backend, clamav Hochgeladene Dateien (Attachments)
quarantine backend Infizierte Dateien (7 Tage Aufbewahrung)
clamav_data clamav Virus-Signaturen
sourcemaps frontend (rw), backend (ro) JS-Sourcemaps für Error-Tracking, die fünf neuesten Releases (Frontend schreibt, Backend liest)

Ressourcen-Anforderungen

Minimum (Development)

  • CPU: 4 Kerne
  • RAM: 8 GB
  • Speicher: 20 GB

Empfohlen (Production)

  • CPU: 8 Kerne
  • RAM: 16 GB
  • Speicher: 100 GB (abhängig von Attachments)

Pro-Container-Limits (Konfigurierbar)

Container CPU Limit Memory Limit
traefik1.0256 MB
frontend0.5256 MB
backend2.02 GB
db2.02 GB
redis1.01 GB
job-worker1.01 GB
email-worker1.0512 MB
notification-worker1.0512 MB
workflow-engine1.0512 MB
av-worker1.01.5 GB
report-generator1.01.5 GB
clamav2.02 GB

Monitoring & Observability

Health-Checks

  • Traefik: Ping Entrypoint (integrierter Health-Check)
  • Backend: GET /api/health/live (Liveness-Probe; die Bereitschaft prüft /api/health/ready)
  • Workflow-Engine:
    • GET /health/live (Liveness-Probe)
    • GET /health/ready (Readiness-Probe, prüft Redis)
  • Report-Generator: GET /health/live (Port 3004)
  • Job-Worker: Health-Endpoint (Port 3001)
  • Email-Worker: Health-Endpoint (Port 3005)
  • Notification-Worker: Health-Endpoint (Port 3006)
  • AV-Worker: Health-Endpoint (Port 3007)

System-Status (Admin-UI + Health-API)

Der Live-Zustand des gesamten Stacks ist im Admin-Bereich unter Admin-Center → System → System-Status sichtbar (Route /admin/system-status). Der Tab zeigt jeden Dienst als aufklappbare Zeile mit seinen Instanzen — je Instanz Status, Version, Laufzeit, Zeitpunkt des letzten Heartbeats, Speicherverbrauch, Port und die Einzelprüfungen (Datenbank, Redis) samt Antwortzeit. Suche und Status-Filter grenzen die Liste ein. Beeinträchtigte Einheiten — etwa ein Postfach ohne Abrufversuch oder ein Cron-Job im Fehlerzustand — stehen in einer eigenen Tabelle, Infrastruktur und Krypto-Konfiguration (z.B. FIPS-Modus) in einer Detailkarte. Datengrundlage ist die Health-API des Backends:

Endpoint Auth Zweck
GET /api/healthKeineBasis-Check (200 healthy / 503 unhealthy) — für Monitoring-Systeme
GET /api/health/liveKeineLiveness-Probe (Prozess läuft)
GET /api/health/readyKeineReadiness-Probe (DB + Redis erreichbar)
GET /api/health/servicessettings.editGeneral (nur angemeldete Benutzer)Status je Dienst und Instanz (Version, Laufzeit, Speicherverbrauch, Port, Einzelprüfungen), beeinträchtigte Einheiten sowie Infrastruktur- und Krypto-Konfiguration; Datenquelle des Tabs System-Status.

Hinweis: Die Service-Health stammt aus einer Redis-Registry: jede Instanz trägt sich alle 15 Sekunden mit einem Heartbeat ein, der Eintrag verfällt nach 30 Sekunden. Ein Dienst ohne Heartbeat erscheint als offline. /api/health/services erfordert settings.editGeneral und ist angemeldeten Benutzern vorbehalten — über einen API-Schlüssel sind Infrastruktur-Topologie, Ports, Instanz-IDs und Krypto-Konfiguration nicht abrufbar.

Structured Logging (JSON)

Alle Eviworx-eigenen Container (Backend, Job-Worker, Email-Worker, Notification-Worker, Workflow-Engine, AV-Worker, Report-Generator) loggen im strukturierten JSON-Format via Pino. Externe Container (Redis, PostgreSQL, ClamAV) verwenden ihr natives Log-Format.

  • Log-Library: Pino v10 (alle eigenen Container)
  • Felder pro Log-Eintrag:
    • level, time, service, msg – Standard-Felder
    • traceId, spanId – Distributed Tracing (OpenTelemetry-kompatibel)
    • correlationId, requestId – Request-Korrelation über Container-Grenzen
    • sourceService – Zeigt welcher Service den Request ausgelöst hat (z.B. av-worker, traefik)
  • Integration: Direkt kompatibel mit Elasticsearch/ELK, Loki, Datadog, Splunk und anderen JSON-Log-Aggregatoren
  • Traefik Access-Logs: Ebenfalls im JSON-Format mit X-Request-ID und User-Agent
  • Rotation: max. 10 MB pro Datei, 3 Dateien (ClamAV, AV-Worker)
  • Zugriff: docker compose logs -f [service-name]
// Beispiel: Backend HTTP-Request Log{
  "level": 30,
  "time": 1773740483502,
  "service": "backend",
  "traceId": "c5d1c321ad743f0abd05d55967adf67d",
  "spanId": "3fcb07029f32d740",
  "correlationId": "c5d1c321ad743f0abd05d55967adf67d",
  "requestId": "b36f4176-0e5b-42d7-8e17-772c0929e4d8",
  "sourceService": "traefik",
  "method": "GET",
  "url": "/api/health/live",
  "status": 200,
  "durationMs": 1,
  "msg": "HTTP request"
}
🔐
Security by Design
  • ✓ Principle of Least Privilege (DB-Zugriff)
  • ✓ Zero-Trust-Virenscan (AV-Worker ohne Dateizugriff)
  • ✓ Network-Isolation (Docker-Netzwerk)
  • ✓ SHA-256-verkettetes Audit-Log (Manipulationen werden erkennbar)
  • ✓ Automatisches PII-Scrubbing in Audit-Logs
  • ✓ SSRF-Protection (IP-Range + DNS-Blocking)
  • ✓ Gehärtete Container (schreibgeschützte Dateisysteme, reduzierte Linux-Capabilities)
  • ✓ FIPS 140-2 kompatible Algorithmen (PBKDF2-SHA512, AES-256-GCM)
  • ✓ MFA/TOTP Authentifizierung
  • ✓ Redis Passwort-Authentifizierung
  • ✓ Traefik API-Gateway (Rate-Limiting, CSP)
Nächste Schritte
Container-Architektur →

Details zu jedem Container

API-Referenz →

API-Module mit Endpoints & Beispielen

Sicherheitsarchitektur →

Zero-Trust, Audit-Chain, RBAC

Skalierung & HA →

Multi-Instance Setup