This document describes the system settings architecture in AnythingLLM, which manages configuration across the entire application. The architecture implements a dual persistence model where settings are stored both as environment variables (.env file) and in the database (system_settings table), ensuring configuration persists across restarts while remaining accessible at runtime.
This page covers the core configuration management system, including the SystemSettings model, the updateENV pipeline, and validation mechanisms. For information about the validation functions and lifecycle hooks that execute during configuration changes, see Settings Validation and Lifecycle Hooks. For details on how the frontend interacts with these settings, see Frontend Settings UI.
The system settings architecture enables runtime reconfiguration of critical application components (LLM providers, vector databases, embedding engines, etc.) without requiring server restarts. It achieves this through a sophisticated pipeline that validates inputs, executes side effects, and persists changes to both memory and disk.
Sources: server/utils/helpers/updateENV.js1-1338 server/models/systemSettings.js1-800
The system maintains three synchronized copies of configuration:
process.env - Runtime access for immediate consumption by application code.env file - Persistent storage that survives restarts and redeployssystem_settings table - Database storage supporting selective field updates and queriesThe SystemSettings model provides the database abstraction layer for configuration persistence and retrieval.
| Method | Purpose | Returns |
|---|---|---|
currentSettings() | Returns all system settings with computed values | Object with 100+ fields |
get({ label }) | Retrieves a single setting by label | { label, value } or null |
getValueOrFallback(clause, fallback) | Safe getter with default value | string or fallback |
updateSettings(updates) | Public update method with field filtering | { success, error } |
_updateSettings(updates) | Internal update with validation execution | { success, error } |
Sources: server/models/systemSettings.js22-408
Protected fields cannot be modified through standard update endpoints. Public fields can be read without authentication. All other fields require admin authentication to modify.
Sources: server/models/systemSettings.js26-42
The KEY_MAPPING object in updateENV.js serves as the central registry defining all configurable settings. Each key maps a frontend field name to its environment variable and validation rules.
Sources: server/utils/helpers/updateENV.js7-830
Each KEY_MAPPING entry follows this schema:
Example entries:
Sources: server/utils/helpers/updateENV.js292-305
The registry contains 200+ entries covering LLM providers, vector databases, embedding engines, TTS/STT providers, agent configurations, and system settings.
The updateENV function orchestrates the entire configuration update lifecycle with validation, side effects, and persistence.
Sources: server/utils/helpers/updateENV.js1164-1220
Only keys defined in KEY_MAPPING are processed. Values containing ****** (masked passwords) are excluded.
Sources: server/utils/helpers/updateENV.js1167-1170
Each validator function returns null (valid) or an error string. Validation failures immediately halt the pipeline.
Sources: server/utils/helpers/updateENV.js1184-1191 server/utils/helpers/updateENV.js1222-1227
Pre-update hooks perform asynchronous validations like connection tests. Example: validatePGVectorConnectionString attempts to connect to PostgreSQL before accepting the connection string.
Sources: server/utils/helpers/updateENV.js1193-1205 server/utils/helpers/updateENV.js1116-1132
Valid values are immediately assigned to process.env, making them available to all application code.
Sources: server/utils/helpers/updateENV.js1207-1208
Post-update hooks execute side effects. Critical example: handleVectorStoreReset purges vector databases when embedding configuration changes to prevent data corruption.
Sources: server/utils/helpers/updateENV.js1210-1211 server/utils/helpers/updateENV.js1062-1078
Changes are logged to the event system for audit trails. In production, dumpENV() writes all protected keys to the .env file.
Sources: server/utils/helpers/updateENV.js1217-1218 server/utils/helpers/updateENV.js1244-1332
The system includes 30+ built-in validators covering common validation patterns.
| Validator | Purpose | Example Usage |
|---|---|---|
isNotEmpty(input) | Ensures non-empty string | All API keys |
isValidURL(input) | URL format validation | LLM base paths |
nonZero(input) | Numeric > 0 validation | Token limits |
supportedLLM(input) | Whitelist check against 46 providers | LLM_PROVIDER |
supportedVectorDB(input) | Whitelist check against 10 databases | VECTOR_DB |
validDockerizedUrl(input) | Docker loopback validation | Service URLs in Docker |
Sources: server/utils/helpers/updateENV.js832-1047
This validator prevents users from configuring services on localhost:port when running in Docker, where localhost refers to the container, not the host machine. It suggests using host.docker.internal instead.
Sources: server/utils/helpers/updateENV.js1024-1047
Settings are consumed throughout the application stack in three primary patterns:
Most runtime code directly reads process.env variables. This is the fastest access pattern and works because updateENV keeps process.env synchronized.
Sources: server/utils/helpers/index.js84-123
The currentSettings() method aggregates and formats settings for frontend consumption. It returns computed values (like masked API keys) and combines multiple ENV variables into logical groups.
Sources: server/models/systemSettings.js209-321
Settings stored exclusively in the database (not in ENV) are retrieved via direct queries. Examples: footer_data, custom_app_name, logo_filename.
Sources: server/models/systemSettings.js323-340
Sources: frontend/src/models/system.js180-191 server/endpoints/system.js539-555 frontend/src/pages/GeneralSettings/LLMPreference/index.jsx1-500
During first-time setup, the onboarding wizard (/onboarding/* routes) guides users through configuration of LLM, embedding engine, and vector database. Each step submits to /system/update-env.
Sources: frontend/src/pages/OnboardingFlow/Steps/LLMPreference/index.jsx1-500 frontend/src/pages/OnboardingFlow/Steps/DataHandling/index.jsx1-36
Admin users access configuration via settings pages (/settings/* routes). The LLMPreference component renders provider-specific configuration forms that submit through System.updateSystem().
Sources: frontend/src/pages/GeneralSettings/LLMPreference/index.jsx1-600 frontend/src/models/system.js180-191
Certain configuration changes trigger destructive side effects to maintain data integrity.
When VectorDB, EmbeddingEngine, or EmbeddingModelPref changes, all vector namespaces are purged. This prevents embedding dimension mismatches and incompatible vector data.
Sources: server/utils/helpers/updateENV.js1062-1078 server/utils/helpers/updateENV.js292-305
When selecting a native embedding model, the model is automatically downloaded in the background during the configuration update.
Sources: server/utils/helpers/updateENV.js1085-1094
The dumpENV function maintains a whitelist of 50+ protected variables that persist across restarts.
Only variables in this whitelist are written to the .env file. This prevents accidental persistence of runtime-generated values.
Sources: server/utils/helpers/updateENV.js1249-1306
Values are sanitized to prevent ENV injection attacks via newlines, quotes, or special characters.
Sources: server/utils/helpers/updateENV.js1309-1327
All configuration changes are logged to the event_logs table for audit trails.
Critical configuration changes (LLM provider, embedding engine, vector database) generate specific event types for tracking.
Sources: server/utils/helpers/updateENV.js1229-1242
| Endpoint | Method | Purpose | Authentication |
|---|---|---|---|
/setup-complete | GET | Returns currentSettings() | None |
/system/update-env | POST | Updates configuration via updateENV | Admin only |
/system/update-password | POST | Updates instance password (single-user) | Validated request |
/system/enable-multi-user | POST | Enables multi-user mode | Validated request |
Sources: server/endpoints/system.js103-111 server/endpoints/system.js539-555 server/endpoints/system.js559-589 server/endpoints/system.js592-645
The frontend System model abstracts API communication, handling errors and returning structured responses.
Sources: frontend/src/models/system.js180-191
The system_settings table stores configuration values not suitable for environment variables.
Common database-only settings:
footer_data - Custom footer links (JSON array)support_email - Support contact emailcustom_app_name - Branded application namelogo_filename - Custom logo filenametelemetry_id - Anonymous telemetry identifiermulti_user_mode - Multi-user mode flagonboarding_complete - Onboarding statusSources: server/models/systemSettings.js22-68
The SystemSettings model includes its own validation layer for database-persisted fields:
These validations execute during _updateSettings() and can trigger side effects (like cache purging).
Sources: server/models/systemSettings.js68-208
The system settings architecture provides:
The updateENV pipeline is the critical path for all configuration changes, ensuring validation, side-effect execution, and synchronized persistence across memory, disk, and database.
Refresh this wiki