Retour à la documentation
Guide 03

Configuration

Simmetric Chat dispose de deux niveaux de configuration : des variables d'environnement validées avec Zod au démarrage du processus, et un niveau de configuration runtime stocké en base de données que les administrateurs peuvent modifier depuis l'interfa…

4 min de lecture

Simmetric Chat dispose de deux niveaux de configuration : des variables d'environnement validées avec Zod au démarrage du processus, et un niveau de configuration runtime stocké en base de données que les administrateurs peuvent modifier depuis l'interface sans redémarrer aucun service.

  1. Variables d'environnement (démarrage du processus) - validées avec Zod dans packages/<pkg>/src/config/env.ts ; process.exit(1) si invalides.
  2. Configuration runtime (DB `SystemConfig`) - modifiable depuis l'interface admin sans redémarrage.

Résolution :

  • Clés ALWAYS_READONLY (JWT_SECRET, DATABASE_URL, SERVER_PORT, COLLECTOR_PORT, SERVER_URL, COLLECTOR_URL, LICENSE_SECRET) : ENV > Default, non modifiables depuis l'interface.
  • Toutes les autres : DB > ENV > Default, modifiables via PUT /api/system/settings.

Les trois packages lisent .env via path.resolve(__dirname, "../../.env") (indépendant du répertoire courant). Le document de référence est .env.example à la racine du dépôt.

Variables d'environnement - server

Schéma : packages/server/src/config/env.ts. Valeurs par défaut affichées ; OBL = obligatoire.

Core / infra

VariableDefaultObl.Description
NODE_ENVdevelopmentoptdevelopment/production/test
SERVER_PORT3000optPort de l'API serveur
COLLECTOR_PORT3210optPort du collector (pour l'URL par défaut)
SERVER_URLhttp://localhost:3000optURL publique du serveur
COLLECTOR_URLhttp://localhost:3210optURL du collector
WIDGET_SERVICE_URLhttp://localhost:3211optURL du service widget (push cache-bust)
WIDGET_API_KEY—optSecret partagé du push widget ; absent → cache-bust no-op (TTL 5 min)
DATABASE_URLpostgresql://simmetricchat:[email protected]:5432/simmetricchatoptURL PostgreSQL
JWT_SECRET—OBLSecret JWT
ENCRYPTION_KEY—optBase64 de 32 octets pour AES-256-GCM (data-at-rest). Non défini → repli scryptSync(JWT_SECRET, salt)
SESSION_EXPIRY86400000 (24h ms)optExpiration JWT
ALLOWED_ORIGINShttp://localhost:5173,127.0.0.1:5173,localhost:3000optAllowlist CORS globale (CSV). /api/internal/widget exclu
LOG_LEVELinfooptdebug/info/warn/error
ALLOW_REGISTRATIONfalseoptInterrupteur d'auto-inscription
DISABLE_TELEMETRYtrueoptDésactive la télémétrie

Bootstrap admin (seed)

VariableDefaultDescription
SEED_BOOTSTRAP_ADMINtrueAuto-seed de l'admin au premier démarrage (transform custom : false/0/no/off/"" = désactivé)
SEED_ADMIN_USERNAMEadminNom d'utilisateur de l'admin bootstrap
SEED_ADMIN_PASSWORDadmin123Mot de passe (min 8) ; compte mustChangePassword=true
SEED_ADMIN_EMAIL[email protected]Email de l'admin bootstrap

LLM

VariableDefaultDescription
LLM_PROVIDERollamaopenai/anthropic/ollama/openrouter
LLM_MODELgemma4:latestModèle par défaut
LLM_TEMPERATURE0.70–2
LLM_MAX_TOKENS4096Plafond de tokens de complétion
LLM_TIMEOUT0Timeout Axios en ms (0 = aucun, pour les LLM locaux lents)
LLM_API_KEY / LLM_API_BASE_URL—Overrides génériques
OPENAI_API_KEY / OPENAI_MODEL—OpenAI
ANTHROPIC_API_KEY / ANTHROPIC_MODEL—Anthropic
OLLAMA_BASE_URLhttp://ollama:11434Point d'accès Ollama
OLLAMA_MODEL / OLLAMA_API_KEY—Override Ollama
OPENROUTER_API_KEY / OPENROUTER_BASE_URL / OPENROUTER_MODELhttps://openrouter.ai/api / —OpenRouter

Watchdog d'agent (prévention des boucles/stalls)

VariableDefaultDescription
AGENT_WALLCLOCK_TIMEOUT_MS600000 (10 min)Borne supérieure absolue pour une requête ReAct
AGENT_MAX_TOTAL_TOKENS200000Total prompt+completion par requête
AGENT_MAX_CONTEXT_BYTES500000 (500 Ko)Plafond de taille du tableau de contexte
AGENT_MAX_TOOL_OUTPUT_LENGTH5000Troncature de la sortie par skill
AGENT_MAX_SKILL_EXECUTION_MS60000Timeout par skill
AGENT_LOOP_DETECTION_WINDOW3Abandon après N tool+input identiques consécutifs
CHAT_MAX_CONCURRENT_PER_USER5Limite de concurrence des chats par utilisateur

Embedding / Vector DB / OCR / Synthesis

VariableDefaultDescription
EMBEDDING_PROVIDERlocallocal/openai/ollama
EMBEDDING_MODELXenova/all-MiniLM-L6-v2Modèle d'embedding
EMBEDDING_API_KEY—Clé API d'embedding
VECTOR_DB_PROVIDERlancedblancedb/qdrant
VECTOR_DB_URL / VECTOR_DB_API_KEY—Pour Qdrant distant
OCR_MODELglm-ocr:latestModèle vision OCR (format model:version)
OCR_TIMEOUT600000Timeout OCR vision
SYNTHESIS_LLM_MODELgemma4:latestModèle du pipeline de synthèse
PUPPETEER_EXECUTABLE_PATH—Chromium pour l'export PDF des archives

Licence, push, email, collector

VariableDefaultDescription
LICENSE_KEY—JWT de licence Enterprise (HS256). Absent → Community
LICENSE_SECRET—Secret de vérification JWT (recommandé) ; repli sur LICENSE_KEY
COLLECTOR_SECRET—OBL — secret partagé server↔collector
VAPID_PUBLIC_KEY / VAPID_PRIVATE_KEY / VAPID_SUBJECT—Web Push ; non défini → clés éphémères générées en dev
SMTP_HOST / SMTP_PORT / SMTP_USER / SMTP_PASS / SMTP_FROM—SMTP pour la réinitialisation de mot de passe + notifications d'échec de sauvegarde
LEGACY_PREVIOUS_ENCRYPTION_KEYS—CSV base64 32 octets pour la rotation des clés
Variables dans .env.example mais gérées comme settings DB (pas dans envSchema) : OCR_ENABLED, OCR_PRECHECK_CHARS, STORAGE_PATH (collector), RESET_PASSWORD_STRATEGY.

Variables d'environnement - collector

Schéma : packages/collector/src/config/env.ts.

VariableDefaultObl.Description
COLLECTOR_PORT3210optPort HTTP
COLLECTOR_URLhttp://localhost:3210optURL propre
SERVER_URLhttp://localhost:3000optURL du serveur (callback)
EMBEDDING_PROVIDERlocaloptlocal/openai/ollama
EMBEDDING_MODEL—optModèle d'embedding
EMBEDDING_API_KEY—optClé API
VECTOR_DB_PROVIDERlancedboptlancedb/qdrant
VECTOR_DB_URL / VECTOR_DB_API_KEY—optQdrant
OLLAMA_BASE_URLhttp://ollama:11434optOllama
STORAGE_PATH./storageoptStockage filesystem
COLLECTOR_SECRET—OBLDoit correspondre au serveur

Variables d'environnement - widget

Schéma : packages/widget/src/config/env.ts.

VariableDefaultObl.Description
NODE_ENVdevelopmentoptEnvironnement
WIDGET_PORT3211optPort HTTP
SERVER_URLhttp://localhost:3000optURL du serveur
WIDGET_API_KEY—OBLSecret partagé widget↔server (doit correspondre)
LOG_LEVELinfooptNiveau de log
Frontend : aucune variable VITE_* ni fichier .env. Le frontend lit le branding/config depuis le serveur (GET /api/system/settings, GET /api/license/info).

Feature flags & licence

Définis dans packages/shared/src/constants/license.ts (FEATURE_FLAGS + valeurs par défaut). Vérification dans packages/server/src/services/licenseService.ts.

Comment passer de Community à Enterprise

  1. Définissez LICENSE_KEY (JWT HS256) et, recommandé, LICENSE_SECRET.
  2. jwt.verify → payload validé contre licensePayloadSchema (tier, iss, sub, iat, exp, features).
  3. tier=enterprise → démarre depuis ENTERPRISE_FEATURE_DEFAULTS + les overrides features du JWT.
  4. Expiré/invalide → repli Community avec avertissement.

Dégradation progressive : getLicenseInfo() vérifie l'expiration à l'exécution ; si Enterprise expire pendant l'utilisation, elle dégrade vers Community sans redémarrage. requireFeature(flag) → HTTP 402 si désactivé ; requireFeatureLimit(flag, model) → 402 si count >= limit (Enterprise = Infinity).

Flags commodity toujours actifs : depuis la suppression EPA-02, les 8 flags commodity n'existent plus dans FEATURE_FLAGS - webhooks, push_notifications, web search, memory, lead_export, widget_analytics, auto_title, synthesis_rate_limit sont toujours actifs en Community (les routes commodity tournent sans gating). priority_support n'est pas un flag : c'est un contrat commercial/SLA (EPA-08). Il reste 11 flags enterprise, dont widget_credits_editing (édition des crédits widget, Community false / Enterprise true) et custom_agents comme limite numérique (Community 3, Enterprise Infinity).

Tableau des flags (11)

FlagTypeCommunityEnterpriseCe qu'il gate
sso_enabledboolfalsetrueSSO Enterprise
audit_log_immutableboolfalsetrueImmuabilité du journal d'audit
white_labelboolfalsetrueBranding BRANDING_*
max_workspacesnum3InfinityCréation de workspace
max_projectsnum3InfinityCréation de projet
custom_agentsnum3InfinityAgents custom (limite)
widget_enabledboolfalsetrueWidget embarquable
max_widgetsnum1InfinityCréation de widget
backup_enabledboolfalsetrueSystème de sauvegarde
max_backup_destinationsnum1InfinityDestinations de sauvegarde
widget_credits_editingboolfalsetrueÉdition des crédits widget

Runtime config (DB SystemConfig)

Modifiable via GET/PUT /api/system/settings (bulk) et PUT /api/system/chat-retention (spécifique, audité). Les valeurs par défaut vivent dans CONFIG_DEFAULTS (packages/shared/src/constants/permissions.ts).

Groupes de clés : LLM (LLM_PROVIDER, LLM_MODEL, LLM_TEMPERATURE, ...), Embedding/Vector, Ports/URL serveur, 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 renvoie toujours 200 avec { updated: [...], rejected: [...] } (les clés readonly sont rejetées tandis que les autres sont appliquées).

Rétention des messages de chat (reaper)

Service : packages/server/src/services/chatMessageReaperJob.ts. Knob DB : chat_message_retention_days.

  • Pass 1 (soft-delete) : tombstones les messages des chats ACTIFS au-delà de retentionDays. No-op si la valeur est null/""/<=0.
  • Pass 2 (hard-purge) : supprime les lignes tombstonées au-delà d'une grâce de 7 jours (codée en dur). S'exécute toujours, indépendamment de la config de rétention (anti-fuite de PII).
  • Cadence : setInterval de 24h, premier passage à 03:00 heure locale. Mutex isRunning.
  • Uniquement PUT /api/system/chat-retention (audité, confirmDataLoss: true, retentionDays: integer|null, min 1) ; l'endpoint bulk rejette cette clé.

Rétention des sauvegardes

Par job (champ retentionDays sur BackupJob, défaut 30). backupRetentionService.ts nettoie les journaux/fichiers au-delà de cutoffDate. Ce n'est pas global.

Rotation des clés de chiffrement

packages/server/src/services/encryptionService.ts (AES-256-GCM, clé 32 octets, IV 16 octets, sel simmetric-chat-encryption-salt).

  • Clé courante : ENCRYPTION_KEY (base64 32 octets) si définie ; sinon scryptSync(JWT_SECRET, salt, 32).
  • LEGACY_PREVIOUS_ENCRYPTION_KEYS (CSV base64 32 octets) → chaîne de clés de déchiffrement [current, ...previous, scryptLegacy?].
  • encrypt() utilise chain[0]. Aucun job automatique de ré-encryption : la procédure est manuelle déchiffrer-avec-l'ancienne → rechiffrer-avec-la-nouvelle.