Simmetric Chat ha due livelli di configurazione:
- Environment variables (avvio del processo) — validate con Zod in
packages/<pkg>/src/config/env.ts;process.exit(1)se invalide. - 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 viaPUT /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
| Variabile | Default | Obbl. | Descrizione |
|---|---|---|---|
NODE_ENV | development | opt | development/production/test |
SERVER_PORT | 3000 | opt | Porta API server |
COLLECTOR_PORT | 3210 | opt | Porta collector (per default URL) |
SERVER_URL | http://localhost:3000 | opt | URL pubblico server |
COLLECTOR_URL | http://localhost:3210 | opt | URL collector |
WIDGET_SERVICE_URL | http://localhost:3211 | opt | URL widget service (push cache-bust) |
WIDGET_API_KEY | — | opt | Shared secret widget push; se assente, cache-bust no-op (TTL 5 min) |
DATABASE_URL | postgresql://simmetricchat:[email protected]:5432/simmetricchat | opt | URL PostgreSQL |
JWT_SECRET | — | OBBL | Segreto JWT |
ENCRYPTION_KEY | — | opt | Base64 di 32 byte per AES-256-GCM (data-at-rest). Se unset → fallback scryptSync(JWT_SECRET, salt) |
SESSION_EXPIRY | 86400000 (24h ms) | opt | Scadenza JWT |
ALLOWED_ORIGINS | http://localhost:5173,127.0.0.1:5173,localhost:3000 | opt | Allowlist CORS globale (CSV). /api/internal/widget escluso |
LOG_LEVEL | info | opt | debug/info/warn/error |
ALLOW_REGISTRATION | false | opt | Self-registration toggle |
DISABLE_TELEMETRY | true | opt | Disabilita telemetria |
Bootstrap admin (seed)
| Variabile | Default | Descrizione |
|---|---|---|
SEED_BOOTSTRAP_ADMIN | true | Auto-seed admin al primo avvio (transform custom: false/0/no/off/"" = disabilitato) |
SEED_ADMIN_USERNAME | admin | Username admin bootstrap |
SEED_ADMIN_PASSWORD | admin123 | Password (min 8); account mustChangePassword=true |
SEED_ADMIN_EMAIL | [email protected] | Email admin bootstrap |
LLM
| Variabile | Default | Descrizione |
|---|---|---|
LLM_PROVIDER | ollama | openai/anthropic/ollama/openrouter |
LLM_MODEL | gemma4:latest | Modello default |
LLM_TEMPERATURE | 0.7 | 0–2 |
LLM_MAX_TOKENS | 4096 | Cap token completamento |
LLM_TIMEOUT | 0 | Timeout Axios ms (0 = nessuno, per LLM locali lenti) |
LLM_API_KEY / LLM_API_BASE_URL | — | Override generici |
OPENAI_API_KEY / OPENAI_MODEL | — | OpenAI |
ANTHROPIC_API_KEY / ANTHROPIC_MODEL | — | Anthropic |
OLLAMA_BASE_URL | http://ollama:11434 | Endpoint Ollama |
OLLAMA_MODEL / OLLAMA_API_KEY | — | Ollama override |
OPENROUTER_API_KEY / OPENROUTER_BASE_URL / OPENROUTER_MODEL | https://openrouter.ai/api / — | OpenRouter |
Agent watchdog (prevenzione loop/stall)
| Variabile | Default | Descrizione |
|---|---|---|
AGENT_WALLCLOCK_TIMEOUT_MS | 600000 (10 min) | Upper bound assoluto per request ReAct |
AGENT_MAX_TOTAL_TOKENS | 200000 | Totale prompt+completion per request |
AGENT_MAX_CONTEXT_BYTES | 500000 (500 KB) | Cap dimensione context array |
AGENT_MAX_TOOL_OUTPUT_LENGTH | 5000 | Truncation per-skill output |
AGENT_MAX_SKILL_EXECUTION_MS | 60000 | Timeout per-skill |
AGENT_LOOP_DETECTION_WINDOW | 3 | Abort dopo N tool+input identici consecutivi |
CHAT_MAX_CONCURRENT_PER_USER | 5 | Limite concorrenza chat per utente |
Embedding / Vector DB / OCR / Synthesis
| Variabile | Default | Descrizione |
|---|---|---|
EMBEDDING_PROVIDER | local | local/openai/ollama |
EMBEDDING_MODEL | Xenova/all-MiniLM-L6-v2 | Modello embedding |
EMBEDDING_API_KEY | — | API key embedding |
VECTOR_DB_PROVIDER | lancedb | lancedb/qdrant |
VECTOR_DB_URL / VECTOR_DB_API_KEY | — | Per Qdrant remoto |
OCR_MODEL | glm-ocr:latest | Modello vision OCR (formato model:version) |
OCR_TIMEOUT | 600000 | Timeout OCR vision |
SYNTHESIS_LLM_MODEL | gemma4:latest | Modello pipeline synthesis |
PUPPETEER_EXECUTABLE_PATH | — | Chromium per export PDF archivi |
Licenza, push, email, collector
| Variabile | Default | Descrizione |
|---|---|---|
LICENSE_KEY | — | JWT Enterprise license (HS256). Assente → Community |
LICENSE_SECRET | — | Segreto verifica JWT (consigliato); fallback a LICENSE_KEY |
COLLECTOR_SECRET | — | OBBL — shared secret server↔collector |
VAPID_PUBLIC_KEY / VAPID_PRIVATE_KEY / VAPID_SUBJECT | — | Web Push; se unset, generate effimere in dev |
SMTP_HOST / SMTP_PORT / SMTP_USER / SMTP_PASS / SMTP_FROM | — | SMTP per password-reset + notifiche fail backup |
LEGACY_PREVIOUS_ENCRYPTION_KEYS | — | CSV base64 32-byte per rotazione chiavi |
Variabili in
.env.examplema gestite come settings DB (non inenvSchema):OCR_ENABLED,OCR_PRECHECK_CHARS,STORAGE_PATH(collector),RESET_PASSWORD_STRATEGY.
Variabili d'ambiente — collector
Schema: packages/collector/src/config/env.ts.
| Variabile | Default | Obbl. | Descrizione |
|---|---|---|---|
COLLECTOR_PORT | 3210 | opt | Porta HTTP |
COLLECTOR_URL | http://localhost:3210 | opt | URL proprio |
SERVER_URL | http://localhost:3000 | opt | URL server (callback) |
EMBEDDING_PROVIDER | local | opt | local/openai/ollama |
EMBEDDING_MODEL | — | opt | Modello embedding |
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 | Filesystem storage |
COLLECTOR_SECRET | — | OBBL | Deve matchare il server |
Variabili d'ambiente — widget
Schema: packages/widget/src/config/env.ts.
| Variabile | Default | Obbl. | Descrizione |
|---|---|---|---|
NODE_ENV | development | opt | Ambiente |
WIDGET_PORT | 3211 | opt | Porta HTTP |
SERVER_URL | http://localhost:3000 | opt | URL server |
WIDGET_API_KEY | — | OBBL | Shared secret widget↔server (deve matchare) |
LOG_LEVEL | info | opt | Livello 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
- Imposta
LICENSE_KEY(JWT HS256) e, consigliato,LICENSE_SECRET. jwt.verify→ payload validato controlicensePayloadSchema(tier,iss,sub,iat,exp,features).tier=enterprise→ parte daENTERPRISE_FEATURE_DEFAULTS+ overridefeaturesdel JWT.- 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)
| Flag | Tipo | Community | Enterprise | Cosa gatea |
|---|---|---|---|---|
sso_enabled | bool | false | true | SSO enterprise |
audit_log_immutable | bool | false | true | Immutabilità audit log |
white_label | bool | false | true | Branding BRANDING_* |
max_workspaces | num | 3 | Infinity | Creazione workspace |
max_projects | num | 3 | Infinity | Creazione progetto |
priority_support | bool | false | true | Informativo |
custom_agents | bool | false | true | Agent custom |
webhooks | bool | false | true | Webhook outbound |
push_notifications | bool | false | true | Web Push (VAPID) |
widget_enabled | bool | false | true | Widget embeddabile |
max_widgets | num | 1 | Infinity | Creazione widget |
lead_export | bool | false | true | Export CSV lead |
widget_analytics | bool | false | true | Tab analytics widget |
synthesis_rate_limit | num | 50 | 200 | Rate limit synthesis |
backup_enabled | bool | false | true | Sistema backup |
max_backup_destinations | num | 1 | Infinity | Destinazioni 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 valorenull/""/<=0. - Pass 2 (hard-purge): elimina righe tombstonate oltre grace di 7 giorni (hardcoded). Runna sempre, indipendentemente dalla config retention (anti-PII leak).
- Cadenza
setInterval24h, primo run alle 03:00 locali. MutexisRunning. - 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; elsescryptSync(JWT_SECRET, salt, 32). LEGACY_PREVIOUS_ENCRYPTION_KEYS(CSV base64 32-byte) → key chain decrypt[current, ...previous, scryptLegacy?].encrypt()usachain[0]. Non esiste job automatico di re-encryption: procedura manuale decrypt-con-old → re-encrypt-con-new.
Cross-link
- Endpoint settings: 04 — API Reference
- Internals feature: 05 — Feature Guide
- Deploy env vars: 09 — Deployment