Konfiguration
Simmetric Chat hat zwei Konfigurationsebenen: Umgebungsvariablen, die beim Prozessstart mit Zod validiert werden, und eine Laufzeit-Konfigurationsebene in der Datenbank, die Admins über die Benutzeroberfläche bearbeiten können, ohne einen Dienst neu zu s…
Simmetric Chat hat zwei Konfigurationsebenen: Umgebungsvariablen, die beim Prozessstart mit Zod validiert werden, und eine Laufzeit-Konfigurationsebene in der Datenbank, die Admins über die Benutzeroberfläche bearbeiten können, ohne einen Dienst neu zu starten.
- Umgebungsvariablen (Prozessstart) - mit Zod validiert in
packages/<pkg>/src/config/env.ts;process.exit(1)bei Ungültigkeit. - Laufzeit-Konfiguration (DB `SystemConfig`) - über die Admin-UI ohne Neustart bearbeitbar.
Auflösung:
ALWAYS_READONLY-Schlüssel (JWT_SECRET,DATABASE_URL,SERVER_PORT,COLLECTOR_PORT,SERVER_URL,COLLECTOR_URL,LICENSE_SECRET):ENV > Default, nicht über die UI bearbeitbar.- Alle anderen:
DB > ENV > Default, bearbeitbar viaPUT /api/system/settings.
Die drei Pakete lesen .env via path.resolve(__dirname, "../../.env") (unabhängig vom Arbeitsverzeichnis). Das Referenzdokument ist .env.example im Repo-Root.
Umgebungsvariablen - server
Schema: packages/server/src/config/env.ts. Standardwerte gezeigt; PFL = Pflicht.
Core / Infrastruktur
| Variable | Default | Pfl. | Beschreibung |
|---|---|---|---|
NODE_ENV | development | opt | development/production/test |
SERVER_PORT | 3000 | opt | Server-API-Port |
COLLECTOR_PORT | 3210 | opt | Collector-Port (für die Standard-URL) |
SERVER_URL | http://localhost:3000 | opt | Öffentliche Server-URL |
COLLECTOR_URL | http://localhost:3210 | opt | Collector-URL |
WIDGET_SERVICE_URL | http://localhost:3211 | opt | Widget-Dienst-URL (Push-Cache-Bust) |
WIDGET_API_KEY | — | opt | Geteiltes Widget-Push-Secret; fehlt es, ist Cache-Bust ein No-op (5 min TTL) |
DATABASE_URL | postgresql://simmetricchat:[email protected]:5432/simmetricchat | opt | PostgreSQL-URL |
JWT_SECRET | — | PFL | JWT-Secret |
ENCRYPTION_KEY | — | opt | Base64 von 32 Bytes für AES-256-GCM (data-at-rest). Nicht gesetzt → Fallback scryptSync(JWT_SECRET, salt) |
SESSION_EXPIRY | 86400000 (24h ms) | opt | JWT-Ablauf |
ALLOWED_ORIGINS | http://localhost:5173,127.0.0.1:5173,localhost:3000 | opt | Globale CORS-Allowlist (CSV). /api/internal/widget ausgenommen |
LOG_LEVEL | info | opt | debug/info/warn/error |
ALLOW_REGISTRATION | false | opt | Selbstregistrierungs-Schalter |
DISABLE_TELEMETRY | true | opt | Deaktiviert Telemetrie |
Bootstrap-Admin (Seed)
| Variable | Default | Beschreibung |
|---|---|---|
SEED_BOOTSTRAP_ADMIN | true | Auto-Seed des Admins beim ersten Start (custom transform: false/0/no/off/"" = deaktiviert) |
SEED_ADMIN_USERNAME | admin | Bootstrap-Admin-Benutzername |
SEED_ADMIN_PASSWORD | admin123 | Passwort (min 8); Konto mustChangePassword=true |
SEED_ADMIN_EMAIL | [email protected] | Bootstrap-Admin-E-Mail |
LLM
| Variable | Default | Beschreibung |
|---|---|---|
LLM_PROVIDER | ollama | openai/anthropic/ollama/openrouter |
LLM_MODEL | gemma4:latest | Standardmodell |
LLM_TEMPERATURE | 0.7 | 0–2 |
LLM_MAX_TOKENS | 4096 | Abschluss-Token-Obergrenze |
LLM_TIMEOUT | 0 | Axios-Timeout ms (0 = keiner, für langsame lokale LLMs) |
LLM_API_KEY / LLM_API_BASE_URL | — | Generische Overrides |
OPENAI_API_KEY / OPENAI_MODEL | — | OpenAI |
ANTHROPIC_API_KEY / ANTHROPIC_MODEL | — | Anthropic |
OLLAMA_BASE_URL | http://ollama:11434 | Ollama-Endpunkt |
OLLAMA_MODEL / OLLAMA_API_KEY | — | Ollama-Override |
OPENROUTER_API_KEY / OPENROUTER_BASE_URL / OPENROUTER_MODEL | https://openrouter.ai/api / — | OpenRouter |
Agent-Watchdog (Schleifen-/Stall-Verhinderung)
| Variable | Default | Beschreibung |
|---|---|---|
AGENT_WALLCLOCK_TIMEOUT_MS | 600000 (10 min) | Absolute Obergrenze für eine ReAct-Anfrage |
AGENT_MAX_TOTAL_TOKENS | 200000 | Prompt+Completion-Gesamt pro Anfrage |
AGENT_MAX_CONTEXT_BYTES | 500000 (500 KB) | Obergrenze der Kontext-Array-Größe |
AGENT_MAX_TOOL_OUTPUT_LENGTH | 5000 | Abschneidung der Ausgabe pro Skill |
AGENT_MAX_SKILL_EXECUTION_MS | 60000 | Timeout pro Skill |
AGENT_LOOP_DETECTION_WINDOW | 3 | Abbruch nach N identischen aufeinanderfolgenden tool+input |
CHAT_MAX_CONCURRENT_PER_USER | 5 | Chat-Gleichzeitigkeitslimit pro Benutzer |
Embedding / Vector DB / OCR / Synthesis
| Variable | Default | Beschreibung |
|---|---|---|
EMBEDDING_PROVIDER | local | local/openai/ollama |
EMBEDDING_MODEL | Xenova/all-MiniLM-L6-v2 | Embedding-Modell |
EMBEDDING_API_KEY | — | Embedding-API-Key |
VECTOR_DB_PROVIDER | lancedb | lancedb/qdrant |
VECTOR_DB_URL / VECTOR_DB_API_KEY | — | Für entferntes Qdrant |
OCR_MODEL | glm-ocr:latest | Vision-OCR-Modell (Format model:version) |
OCR_TIMEOUT | 600000 | Vision-OCR-Timeout |
SYNTHESIS_LLM_MODEL | gemma4:latest | Modell der Synthese-Pipeline |
PUPPETEER_EXECUTABLE_PATH | — | Chromium für PDF-Export von Archiven |
Lizenz, Push, E-Mail, Collector
| Variable | Default | Beschreibung |
|---|---|---|
LICENSE_KEY | — | Enterprise-Lizenz-JWT (HS256). Fehlt → Community |
LICENSE_SECRET | — | JWT-Verifikationsgeheimnis (empfohlen); Fallback auf LICENSE_KEY |
COLLECTOR_SECRET | — | PFL — geteiltes Geheimnis server↔collector |
VAPID_PUBLIC_KEY / VAPID_PRIVATE_KEY / VAPID_SUBJECT | — | Web Push; nicht gesetzt → ephemere Schlüssel in dev |
SMTP_HOST / SMTP_PORT / SMTP_USER / SMTP_PASS / SMTP_FROM | — | SMTP für Passwort-Reset + Backup-Fehlerbenachrichtigungen |
LEGACY_PREVIOUS_ENCRYPTION_KEYS | — | CSV base64 32 Byte für Schlüsselrotation |
Variablen in.env.example, aber als DB-Settings verwaltet (nicht inenvSchema):OCR_ENABLED,OCR_PRECHECK_CHARS,STORAGE_PATH(collector),RESET_PASSWORD_STRATEGY.
Umgebungsvariablen - collector
Schema: packages/collector/src/config/env.ts.
| Variable | Default | Pfl. | Beschreibung |
|---|---|---|---|
COLLECTOR_PORT | 3210 | opt | HTTP-Port |
COLLECTOR_URL | http://localhost:3210 | opt | Eigene URL |
SERVER_URL | http://localhost:3000 | opt | Server-URL (Callback) |
EMBEDDING_PROVIDER | local | opt | local/openai/ollama |
EMBEDDING_MODEL | — | opt | Embedding-Modell |
EMBEDDING_API_KEY | — | opt | API-Key |
VECTOR_DB_PROVIDER | lancedb | opt | lancedb/qdrant |
VECTOR_DB_URL / VECTOR_DB_API_KEY | — | opt | Qdrant |
OLLAMA_BASE_URL | http://ollama:11434 | opt | Ollama |
STORAGE_PATH | ./storage | opt | Dateisystem-Speicher |
COLLECTOR_SECRET | — | PFL | Muss mit dem Server übereinstimmen |
Umgebungsvariablen - widget
Schema: packages/widget/src/config/env.ts.
| Variable | Default | Pfl. | Beschreibung |
|---|---|---|---|
NODE_ENV | development | opt | Umgebung |
WIDGET_PORT | 3211 | opt | HTTP-Port |
SERVER_URL | http://localhost:3000 | opt | Server-URL |
WIDGET_API_KEY | — | PFL | Geteiltes Geheimnis widget↔server (muss übereinstimmen) |
LOG_LEVEL | info | opt | Log-Level |
Frontend: keineVITE_*-Variablen und keine.env-Datei. Das Frontend liest Branding/Konfiguration vom Server (GET /api/system/settings,GET /api/license/info).
Feature-Flags & Lizenz
Definiert in packages/shared/src/constants/license.ts (FEATURE_FLAGS + Defaults). Verifiziert in packages/server/src/services/licenseService.ts.
Wie man von Community zu Enterprise wechselt
- Setzen Sie
LICENSE_KEY(HS256-JWT) und, empfohlen,LICENSE_SECRET. jwt.verify→ Payload gegenlicensePayloadSchemavalidiert (tier,iss,sub,iat,exp,features).tier=enterprise→ startet vonENTERPRISE_FEATURE_DEFAULTS+ diefeatures-Overrides des JWT.- Abgelaufen/ungültig → Community-Fallback mit Warnung.
Graceful Degradation: getLicenseInfo() prüft den Ablauf zur Laufzeit; läuft Enterprise während der Nutzung ab, degradiert es ohne Neustart zu Community. requireFeature(flag) → HTTP 402, wenn deaktiviert; requireFeatureLimit(flag, model) → 402, wenn count >= limit (Enterprise = Infinity).
Immer-aktive Commodity-Flags: seit der EPA-02-Entfernung existieren die 8 Commodity-Flags nicht mehr in FEATURE_FLAGS - webhooks, push_notifications, web search, memory, lead_export, widget_analytics, auto_title, synthesis_rate_limit sind in Community immer aktiv (Commodity-Routen laufen ohne Gating). priority_support ist kein Flag: es ist ein kommerzieller/SLA-Vertrag (EPA-08). Es bleiben 11 Enterprise-Flags, darunter widget_credits_editing (Widget-Credits-Bearbeitung, Community false / Enterprise true) und custom_agents als numerisches Limit (Community 3, Enterprise Infinity).
Flag-Tabelle (11)
| Flag | Typ | Community | Enterprise | Was es gateet |
|---|---|---|---|---|
sso_enabled | bool | false | true | Enterprise-SSO |
audit_log_immutable | bool | false | true | Unveränderbarkeit des Audit-Logs |
white_label | bool | false | true | Branding BRANDING_* |
max_workspaces | num | 3 | Infinity | Workspace-Erstellung |
max_projects | num | 3 | Infinity | Projekterstellung |
custom_agents | num | 3 | Infinity | Custom-Agenten (Limit) |
widget_enabled | bool | false | true | Einbettbares Widget |
max_widgets | num | 1 | Infinity | Widget-Erstellung |
backup_enabled | bool | false | true | Backup-System |
max_backup_destinations | num | 1 | Infinity | Backup-Ziele |
widget_credits_editing | bool | false | true | Widget-Credits-Bearbeitung |
Laufzeit-Konfiguration (DB SystemConfig)
Bearbeitbar via GET/PUT /api/system/settings (bulk) und PUT /api/system/chat-retention (spezifisch, auditiert). Die Defaults leben in CONFIG_DEFAULTS (packages/shared/src/constants/permissions.ts).
Schlüsselgruppen: LLM (LLM_PROVIDER, LLM_MODEL, LLM_TEMPERATURE, ...), Embedding/Vector, Server-Ports/URLs, Auth (SESSION_EXPIRY), Branding (BRANDING_APP_NAME, BRANDING_PRIMARY_COLOR, BRANDING_APP_SUBTITLE, BRANDING_APP_ICON_URL - gated white_label), Feature (DISABLE_TELEMETRY, ALLOW_REGISTRATION, DLP_ENABLED), OCR (OCR_DEFAULT_MODEL, OCR_DEFAULT_MODE, OCR_DEFAULT_CUSTOM_INSTRUCTIONS, OCR_ENABLED, OCR_PRECHECK_CHARS), Synthesis (SYNTHESIS_LLM_PROVIDER_ID, SYNTHESIS_LLM_MODEL), Retention (upload_draft_retention_days, ALLOW_NON_ADMIN_UPLOAD, chat_message_retention_days).
PUT /api/system/settings gibt immer 200 mit { updated: [...], rejected: [...] } zurück (readonly-Schlüssel werden abgelehnt, während die anderen angewendet werden).
Chat-Nachrichtenaufbewahrung (Reaper)
Service: packages/server/src/services/chatMessageReaperJob.ts. DB-Knob: chat_message_retention_days.
- Pass 1 (Soft-Delete): Tombstones Nachrichten AKTIVER Chats jenseits von
retentionDays. No-op, wenn der Wertnull/""/<=0ist. - Pass 2 (Hard-Purge): Löscht tombstonierte Zeilen jenseits einer 7-Tage-Gnadenfrist (hardcodiert). Läuft immer, unabhängig von der Aufbewahrungskonfiguration (Anti-PII-Leak).
- Kadenz: 24h-
setInterval, erster Lauf um 03:00 Ortszeit.isRunning-Mutex. - Nur
PUT /api/system/chat-retention(auditiert,confirmDataLoss: true,retentionDays: integer|null, min 1); der Bulk-Settings-Endpunkt lehnt diesen Schlüssel ab.
Backup-Aufbewahrung
Pro Job (das retentionDays-Feld auf BackupJob, Standard 30). backupRetentionService.ts bereinigt Logs/Dateien jenseits von cutoffDate. Nicht global.
Verschlüsselungsschlüssel-Rotation
packages/server/src/services/encryptionService.ts (AES-256-GCM, 32-Byte-Schlüssel, 16-Byte-IV, Salt simmetric-chat-encryption-salt).
- Aktueller Schlüssel:
ENCRYPTION_KEY(base64 32 Bytes), wenn gesetzt; sonstscryptSync(JWT_SECRET, salt, 32). LEGACY_PREVIOUS_ENCRYPTION_KEYS(CSV base64 32 Bytes) → Entschlüsselungs-Schlüsselkette[current, ...previous, scryptLegacy?].encrypt()nutztchain[0]. Es gibt keinen automatischen Re-Encryption-Job: die Prozedur ist manuell decrypt-mit-alt → re-encrypt-mit-neu.
Cross-Link
- Settings-Endpunkte: 04 - API Reference
- Interne Funktionen: 05 - Feature Guide
- Deploy-Env-Vars: 09 - Deployment