Skip to content

Infrastruktur-Referenz

Übersicht

┌─────────────────────────────────────────────────────────┐
│  Prilog Platform                                         │
│                                                          │
│  ┌──────────────┐  ┌──────────────┐  ┌───────────────┐ │
│  │ Backend-API  │  │  Web-Client  │  │    Portal     │ │
│  │ (Fastify)    │  │  (React/Vite)│  │  (Next.js)    │ │
│  └──────┬───────┘  └──────────────┘  └───────────────┘ │
│         │                                                │
│  ┌──────┴───────┐  ┌──────────────┐  ┌───────────────┐ │
│  │ PostgreSQL   │  │    Redis     │  │  S3 Storage   │ │
│  │ (Datenbank)  │  │ (Cache/PubSub)│ │ (Dateien)     │ │
│  └──────────────┘  └──────────────┘  └───────────────┘ │
└─────────────────────────────────────────────────────────┘

Externe Dienste

DienstAnbieterZweck
PostgreSQLHetzner (Prod), Docker (Dev)Datenbank für alle Prilog-Daten
RedisHetzner (Prod), Docker (Dev)Cache, Event-Bus Pub/Sub, Agent-Registry, JWT-Blacklist
S3 Object StorageHetzner (Prod), MinIO (Dev)Dateiablage, Store-Artefakte
StripeStripe.comZahlungen, Subscriptions, Modul-Billing, Developer-Auszahlungen
DNSBunny.netDNS-Verwaltung für *.prilog.chat und *.prilog.team
Cloud ServerHetzner CloudKundenserver (Synapse + Matrix)
TailscaleTailscale.comVPN-Tunnel zu Kundenservern
E-MailMailPace / SendGridTransaktions-E-Mails

S3 Object Storage

Wie es funktioniert

Der Code spricht reines S3-Protokoll über @aws-sdk/client-s3. Es ist kein Vendor-Lock-in — jeder S3-kompatibler Dienst funktioniert.

Umgebungen

UmgebungBackendEndpointKonfiguration
Lokal (Dev)MinIOhttp://localhost:9000docker-compose.dev.yml in prilog-infra
ProduktionHetzner Object Storagehttps://fsn1.your-objectstorage.comEnv-Vars auf dem Server
AlternativAWS S3, Backblaze B2, Cloudflare R2Jeweiliger EndpointEnv-Vars anpassen

Env-Variablen

bash
S3_ENDPOINT=http://localhost:9000          # MinIO lokal
S3_REGION=eu-central-1                     # Standard
S3_BUCKET=prilog-files                     # Bucket-Name
S3_ACCESS_KEY_ID=prilog-dev                # MinIO User (Dev)
S3_SECRET_ACCESS_KEY=prilog-dev-secret     # MinIO Passwort (Dev)

Bucket-Struktur

prilog-files/
├── spaces/{spaceId}/{folderId}/{uuid}-{filename}     ← Projekt-Modul Dateien
└── store/modules/{moduleId}/{version}/{filename}      ← Store-Artefakte

MinIO lokal starten

bash
cd prilog-infra
docker compose -f docker-compose.dev.yml up -d

MinIO Console: http://localhost:9001 (User: prilog-dev, Passwort: prilog-dev-secret)

S3-Anbieter wechseln

Um den S3-Anbieter zu wechseln, reicht es die 5 Env-Vars anzupassen. Kein Code muss geändert werden. Der forcePathStyle: true Parameter im S3-Client sorgt für Kompatibilität mit allen S3-Clones.

PostgreSQL

Lokal

bash
cd prilog-infra
docker compose -f docker-compose.dev.yml up -d
DATABASE_URL=postgresql://prilog:prilog-dev-password@localhost:5432/prilog

Migrationen

bash
cd prilog-backend-api

# Neue Migration erstellen (braucht laufende DB)
npx prisma migrate dev --name beschreibung

# Migrationen deployen
npx prisma migrate deploy

# Prisma Client neu generieren (nach Schema-Änderungen)
npx prisma generate

Aktuelle Tabellen (Modul-Architektur)

TabelleZweck
module_registrationsZentrale Modul-Registry
tenant_module_installationsInstallation pro Tenant (Lifecycle)
module_eventsEvent-Bus Persistenz
module_configsKey-Value Konfiguration
module_usage_eventsBilling-Tracking
developer_accountsStore-Entwickler
store_submissionsEinreichungs-Pipeline
store_ratingsModul-Bewertungen
cron_job_runsCron-Job Tracking

Redis

Lokal

bash
cd prilog-infra
docker compose -f docker-compose.dev.yml up -d
REDIS_URL=redis://localhost:6379

Verwendung

FeatureRedis-Keys
Event-Busprilog:events:{tenantId} (Pub/Sub Channel)
Modul-Cacheprilog:mod:{moduleId}:{tenantId}:{key}
Modul-Metrikenprilog:mod:metrics:{moduleId}:durations, :errors, :total
Performance-Violationsprilog:mod:violations:{moduleId}:{type}
Agent-Registryagent:{orderId}:meta, :metrics, :modules
JWT-BlacklistVia jwt-blacklist.service.ts

3 separate Redis-Clients (verhindert Blocking bei Pub/Sub):

  • redis — Haupt-Client (get/set)
  • redisSub — Subscriber
  • redisPub — Publisher

Lokale Entwicklungsumgebung

Alles starten

bash
# 1. Infrastruktur (PostgreSQL, Redis, MinIO)
cd prilog-infra
docker compose -f docker-compose.dev.yml up -d

# 2. Backend-API
cd prilog-backend-api
cp .env.example .env  # Env-Vars anpassen
npx prisma migrate deploy
npx prisma generate
npm run dev

# 3. Web-Client
cd prilog-web-client
npm run dev

# 4. Portal
cd prilog-portal
npm run dev

# 5. Admin
cd prilog-admin
npm run dev

Ports

ServicePort
Backend-API3001
Web-Client5173
Portal3003
Admin3004 (oder 3000)
PostgreSQL5432
Redis6379
MinIO API9000
MinIO Console9001

Umgebungsvariablen (Backend-API)

Definiert in src/config/env.ts mit Zod-Validierung.

Pflicht

VariableBeschreibung
DATABASE_URLPostgreSQL Connection String
JWT_SECRETJWT-Signierung (min. 32 Zeichen)
BUNNY_API_KEYBunny.net DNS API Key
BUNNY_ZONE_ID_CHATBunny Zone für *.prilog.chat
BUNNY_ZONE_ID_TEAMBunny Zone für *.prilog.team
TAILSCALE_AUTH_KEYTailscale Auth Key
TAILSCALE_API_KEYTailscale API Key
HETZNER_API_TOKENHetzner Cloud API Token
ADMIN_PASSWORDAdmin-Dashboard Passwort (min. 8 Zeichen)

Optional

VariableDefaultBeschreibung
NODE_ENVdevelopmentdevelopment, production, test
PORT3001Server-Port
JWT_EXPIRES_IN24hToken-Gültigkeit
STRIPE_SECRET_KEYStripe API Key (Billing)
STRIPE_WEBHOOK_SECRETStripe Webhook Signierung
MAILPACE_API_KEYMailPace E-Mail-Versand
SENDGRID_API_KEYSendGrid E-Mail-Versand
EMAIL_FROMnoreply@prilog.chatAbsender-Adresse
MATRIX_CONNECTOR_SHARED_SECRETShared Secret für Matrix-Connector
WEBHOOK_SECRET(Default)Webhook-Signierung
S3_ENDPOINTS3-Endpoint (MinIO/Hetzner)
S3_REGIONeu-central-1S3-Region
S3_BUCKETprilog-filesS3-Bucket
S3_ACCESS_KEY_IDS3-Zugang
S3_SECRET_ACCESS_KEYS3-Secret
FRONTEND_URLhttps://www.prilog.chatMarketing-Website URL
ONBOARDING_URLhttps://onboarding.prilog.chatBestell-Wizard URL
PORTAL_URLhttps://portal.prilog.chatKunden-Portal URL

PWA & Service Worker

Der Web-Client ist als Progressive Web App installierbar — Nutzer koennen Prilog ueber "Zum Startbildschirm hinzufuegen" wie eine native App nutzen.

Technologie

  • vite-plugin-pwa (v1.2.0) mit Workbox generateSW
  • Manifest (manifest.webmanifest) mit Icons, Standalone-Display, Portrait-Orientation
  • Service Worker wird beim Build generiert (dist/sw.js)

Caching-Strategie

Request-TypStrategieDetails
Statische Assets (JS, CSS, Bilder, Fonts)Precache89 Dateien beim Install gecacht, versioniert per Content-Hash
Matrix Media (/_matrix/client/v1/media/*)CacheFirst7 Tage, max. 200 Eintraege. mxc-IDs sind immutable — sicher zu cachen
Matrix Sync/API (/_matrix/*)NetworkOnlyNie cachen — Sync-State muss immer live sein
Backend API (/api/*)NetworkOnlyNie cachen — verhindert 401-Fehler nach Token-Erneuerung
Navigation (index.html)NetworkFirstFrisch vom Server, Fallback auf Cache wenn offline. Denylist: /_matrix, /api

Auto-Update

Der Service Worker prueft alle 60 Sekunden auf neue Versionen (registration.update()). Wenn eine neue Version erkannt wird:

  1. Neuer SW wird im Hintergrund installiert
  2. skipWaiting + clientsClaim aktivieren ihn sofort
  3. onNeedRefresh ruft updateSW(true) → automatischer Tab-Reload
  4. Alte Caches werden via cleanupOutdatedCaches() aufgeraeumt

Kein Nutzer-Klick noetig — das Update passiert unsichtbar. Besonders wichtig fuer PWA-Standalone-Sessions auf Mobilgeraeten, die tagelang offen bleiben.

Historie

Der Service Worker war zeitweise deaktiviert (selfDestroying: true) weil eine fruehere Konfiguration API-Responses gecacht hatte. Nach Token-Erneuerung kamen alte 401-Responses aus dem Cache zurueck. Die Loesung: explizite NetworkOnly-Regeln fuer alle API- und Matrix-Requests. Seit 2026-04-27 ist der Service Worker wieder aktiv.