Back to docs
Guide 03

Configuration

Env vars, flags and runtime settings.

Simmetric Chat ha due livelli di configurazione:

  1. Environment variables (avvio del processo) — validate con Zod in packages/<pkg>/src/config/env.ts; process.exit(1) se invalide.
  2. Runtime config (DB SystemConfig) — modificabile da UI admin senza restart.

Risoluzione:

  • Chiavi ALWAYS_READONLY (JWT_SECRET, DATABASE_URL, SERVER_PORT, COLLECTOR_PORT, SERVER_URL, COLLECTOR_URL, LICENSE_SECRET): ENV > Default, non modificabili da UI.
  • Tutte le altre: DB > ENV > Default, modificabili via PUT /api/system/settings.

I tre package leggono .env via path.resolve(__dirname, "../../.env") (indipendente dalla cwd). Il riferimento documentale è .env.example alla radice del repo.


Variabili d'ambiente — server

Schema: packages/server/src/config/env.ts. Default mostrati; OBBL = obbligatorio.

Core / infra

VariabileDefaultObbl.Descrizione
NODE_ENVdevelopmentoptdevelopment/production/test
SERVER_PORT3000optPorta API server
COLLECTOR_PORT3210optPorta collector (per default URL)
SERVER_URLhttp://localhost:3000optURL pubblico server
COLLECTOR_URLhttp://localhost:3210optURL collector
WIDGET_SERVICE_URLhttp://localhost:3211optURL widget service (push cache-bust)
WIDGET_API_KEYoptShared secret widget push; se assente, cache-bust no-op (TTL 5 min)
DATABASE_URLpostgresql://simmetricchat:[email protected]:5432/simmetricchatoptURL PostgreSQL
JWT_SECRETOBBLSegreto JWT
ENCRYPTION_KEYoptBase64 di 32 byte per AES-256-GCM (data-at-rest). Se unset → fallback scryptSync(JWT_SECRET, salt)
SESSION_EXPIRY86400000 (24h ms)optScadenza JWT
ALLOWED_ORIGINShttp://localhost:5173,127.0.0.1:5173,localhost:3000optAllowlist CORS globale (CSV). /api/internal/widget escluso
LOG_LEVELinfooptdebug/info/warn/error
ALLOW_REGISTRATIONfalseoptSelf-registration toggle
DISABLE_TELEMETRYtrueoptDisabilita telemetria

Bootstrap admin (seed)

VariabileDefaultDescrizione
SEED_BOOTSTRAP_ADMINtrueAuto-seed admin al primo avvio (transform custom: false/0/no/off/"" = disabilitato)
SEED_ADMIN_USERNAMEadminUsername admin bootstrap
SEED_ADMIN_PASSWORDadmin123Password (min 8); account mustChangePassword=true
SEED_ADMIN_EMAIL[email protected]Email admin bootstrap

LLM

VariabileDefaultDescrizione
LLM_PROVIDERollamaopenai/anthropic/ollama/openrouter
LLM_MODELgemma4:latestModello default
LLM_TEMPERATURE0.70–2
LLM_MAX_TOKENS4096Cap token completamento
LLM_TIMEOUT0Timeout Axios ms (0 = nessuno, per LLM locali lenti)
LLM_API_KEY / LLM_API_BASE_URLOverride generici
OPENAI_API_KEY / OPENAI_MODELOpenAI
ANTHROPIC_API_KEY / ANTHROPIC_MODELAnthropic
OLLAMA_BASE_URLhttp://ollama:11434Endpoint Ollama
OLLAMA_MODEL / OLLAMA_API_KEYOllama override
OPENROUTER_API_KEY / OPENROUTER_BASE_URL / OPENROUTER_MODELhttps://openrouter.ai/api / —OpenRouter

Agent watchdog (prevenzione loop/stall)

VariabileDefaultDescrizione
AGENT_WALLCLOCK_TIMEOUT_MS600000 (10 min)Upper bound assoluto per request ReAct
AGENT_MAX_TOTAL_TOKENS200000Totale prompt+completion per request
AGENT_MAX_CONTEXT_BYTES500000 (500 KB)Cap dimensione context array
AGENT_MAX_TOOL_OUTPUT_LENGTH5000Truncation per-skill output
AGENT_MAX_SKILL_EXECUTION_MS60000Timeout per-skill
AGENT_LOOP_DETECTION_WINDOW3Abort dopo N tool+input identici consecutivi
CHAT_MAX_CONCURRENT_PER_USER5Limite concorrenza chat per utente

Embedding / Vector DB / OCR / Synthesis

VariabileDefaultDescrizione
EMBEDDING_PROVIDERlocallocal/openai/ollama
EMBEDDING_MODELXenova/all-MiniLM-L6-v2Modello embedding
EMBEDDING_API_KEYAPI key embedding
VECTOR_DB_PROVIDERlancedblancedb/qdrant
VECTOR_DB_URL / VECTOR_DB_API_KEYPer Qdrant remoto
OCR_MODELglm-ocr:latestModello vision OCR (formato model:version)
OCR_TIMEOUT600000Timeout OCR vision
SYNTHESIS_LLM_MODELgemma4:latestModello pipeline synthesis
PUPPETEER_EXECUTABLE_PATHChromium per export PDF archivi

Licenza, push, email, collector

VariabileDefaultDescrizione
LICENSE_KEYJWT Enterprise license (HS256). Assente → Community
LICENSE_SECRETSegreto verifica JWT (consigliato); fallback a LICENSE_KEY
COLLECTOR_SECRETOBBL — shared secret server↔collector
VAPID_PUBLIC_KEY / VAPID_PRIVATE_KEY / VAPID_SUBJECTWeb Push; se unset, generate effimere in dev
SMTP_HOST / SMTP_PORT / SMTP_USER / SMTP_PASS / SMTP_FROMSMTP per password-reset + notifiche fail backup
LEGACY_PREVIOUS_ENCRYPTION_KEYSCSV base64 32-byte per rotazione chiavi

Variabili in .env.example ma gestite come settings DB (non in envSchema): OCR_ENABLED, OCR_PRECHECK_CHARS, STORAGE_PATH (collector), RESET_PASSWORD_STRATEGY.


Variabili d'ambiente — collector

Schema: packages/collector/src/config/env.ts.

VariabileDefaultObbl.Descrizione
COLLECTOR_PORT3210optPorta HTTP
COLLECTOR_URLhttp://localhost:3210optURL proprio
SERVER_URLhttp://localhost:3000optURL server (callback)
EMBEDDING_PROVIDERlocaloptlocal/openai/ollama
EMBEDDING_MODELoptModello embedding
EMBEDDING_API_KEYoptAPI key
VECTOR_DB_PROVIDERlancedboptlancedb/qdrant
VECTOR_DB_URL / VECTOR_DB_API_KEYoptQdrant
OLLAMA_BASE_URLhttp://ollama:11434optOllama
STORAGE_PATH./storageoptFilesystem storage
COLLECTOR_SECRETOBBLDeve matchare il server

Variabili d'ambiente — widget

Schema: packages/widget/src/config/env.ts.

VariabileDefaultObbl.Descrizione
NODE_ENVdevelopmentoptAmbiente
WIDGET_PORT3211optPorta HTTP
SERVER_URLhttp://localhost:3000optURL server
WIDGET_API_KEYOBBLShared secret widget↔server (deve matchare)
LOG_LEVELinfooptLivello log

Frontend: nessuna variabile VITE_* né file .env. Il frontend legge branding/config dal server (GET /api/system/settings, GET /api/license/info).


Feature flag & licenza

Definiti in packages/shared/src/constants/license.ts (FEATURE_FLAGS + defaults). Verifica in packages/server/src/services/licenseService.ts.

Come si passa Community → Enterprise

  1. Imposta LICENSE_KEY (JWT HS256) e, consigliato, LICENSE_SECRET.
  2. jwt.verify → payload validato contro licensePayloadSchema (tier, iss, sub, iat, exp, features).
  3. tier=enterprise → parte da ENTERPRISE_FEATURE_DEFAULTS + override features del JWT.
  4. Scaduto/invalido → fallback Community con warn.

Graceful degradation: getLicenseInfo() controlla la scadenza a runtime; se Enterprise scade durante l'attività, degrada a Community senza restart. requireFeature(flag) → HTTP 402 se disabilitato; requireFeatureLimit(flag, model) → 402 se count >= limit (Enterprise = Infinity).

Tabella flag (16)

FlagTipoCommunityEnterpriseCosa gatea
sso_enabledboolfalsetrueSSO enterprise
audit_log_immutableboolfalsetrueImmutabilità audit log
white_labelboolfalsetrueBranding BRANDING_*
max_workspacesnum3InfinityCreazione workspace
max_projectsnum3InfinityCreazione progetto
priority_supportboolfalsetrueInformativo
custom_agentsboolfalsetrueAgent custom
webhooksboolfalsetrueWebhook outbound
push_notificationsboolfalsetrueWeb Push (VAPID)
widget_enabledboolfalsetrueWidget embeddabile
max_widgetsnum1InfinityCreazione widget
lead_exportboolfalsetrueExport CSV lead
widget_analyticsboolfalsetrueTab analytics widget
synthesis_rate_limitnum50200Rate limit synthesis
backup_enabledboolfalsetrueSistema backup
max_backup_destinationsnum1InfinityDestinazioni backup

Runtime config (DB SystemConfig)

Modificabile via GET/PUT /api/system/settings (bulk) e PUT /api/system/chat-retention (specifica, audited). Default in CONFIG_DEFAULTS (packages/shared/src/constants/permissions.ts).

Gruppi di chiavi: LLM (LLM_PROVIDER, LLM_MODEL, LLM_TEMPERATURE, ...), Embedding/Vector, Server porte/URL, 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 ritorna sempre 200 con { updated: [...], rejected: [...] } (le chiavi readonly sono rifiutate ma le altre applicate).

Chat message retention (reaper)

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

  • Pass 1 (soft-delete): tombstone messaggi di chat ATTIVE oltre retentionDays. No-op se valore null/""/<=0.
  • Pass 2 (hard-purge): elimina righe tombstonate oltre grace di 7 giorni (hardcoded). Runna sempre, indipendentemente dalla config retention (anti-PII leak).
  • Cadenza setInterval 24h, primo run alle 03:00 locali. Mutex isRunning.
  • Solo PUT /api/system/chat-retention (audited, confirmDataLoss: true, retentionDays: integer|null, min 1); la bulk settings rifiuta questa chiave.

Backup retention

Per-job (campo retentionDays su BackupJob, default 30). backupRetentionService.ts pulisce log/file oltre cutoffDate. Non è globale.

Encryption key rotation

packages/server/src/services/encryptionService.ts (AES-256-GCM, 32-byte key, 16-byte IV, salt simmetric-chat-encryption-salt).

  • Chiave corrente: ENCRYPTION_KEY (base64 32 byte) se set; else scryptSync(JWT_SECRET, salt, 32).
  • LEGACY_PREVIOUS_ENCRYPTION_KEYS (CSV base64 32-byte) → key chain decrypt [current, ...previous, scryptLegacy?].
  • encrypt() usa chain[0]. Non esiste job automatico di re-encryption: procedura manuale decrypt-con-old → re-encrypt-con-new.

Cross-link