Global Settings Management
This document describes the global key-value store system with group-based organization for managing application-wide configuration and credentials in DeployStack.Overview
The global settings system provides secure storage for application-wide configuration values organized into logical groups for better management and frontend display:- SMTP Mail Settings: Host, port, username, password for email functionality
- GitHub OAuth Configuration: GitHub OAuth client ID and secret for authentication
- API Keys: External service credentials (OpenAI, AWS, etc.)
- System Configuration: Application-wide settings and feature flags
- Integration Credentials: Third-party service authentication tokens
- Environment Variables: Dynamic configuration that can be changed without code deployment
Group-Based Organization
The system now uses groups to organize settings into logical categories that can be displayed as tabs in the frontend:- Group ID: Technical identifier used for API queries (e.g.,
smtp
) - Group Name: Human-readable display name (e.g.,
SMTP Mail Settings
) - Group Metadata: Description, icon, and sort order for frontend display
Auto-Initialization System
The system includes an auto-initialization feature that automatically creates missing groups and global settings when the server starts. Settings are defined in modular files within thesrc/global-settings/
directory, and the system will:
- Scan for setting definition files on startup
- Create missing groups with metadata
- Check which settings exist in the database
- Create missing settings with default values (non-destructive)
- Link settings to their appropriate groups
- Preserve existing settings and their values
- Log initialization results for transparency
Key Features
- Group-Based Organization: Settings organized into logical groups for frontend tabs
- Hierarchical Keys: Dot notation organization (e.g.,
smtp.host
,api.openai.key
) - Encryption Support: Automatic encryption for sensitive values using AES-256-GCM
- Group Metadata: Display names, descriptions, icons, and sort order for groups
- Admin-Only Access: Only
global_admin
users can manage settings - Audit Trail: Track setting changes with timestamps
- Search Functionality: Find settings by key patterns
- Bulk Operations: Create/update multiple settings at once
- Health Monitoring: Built-in encryption system health checks
Security
Encryption
Sensitive values are encrypted using industry-standard AES-256-GCM encryption:- Algorithm: AES-256-GCM (Galois/Counter Mode)
- Key Derivation: Scrypt with fixed salt from
DEPLOYSTACK_ENCRYPTION_SECRET
environment variable - Authenticated Encryption: Prevents tampering with encrypted data
- Unique IVs: Each encryption operation uses a unique initialization vector
- Additional Authenticated Data: Extra security layer to prevent manipulation
Access Control
- Role-Based Access: Only users with
global_admin
role can access settings - Permission-Based: Granular permissions for view, edit, and delete operations
- Session Validation: All requests require valid authentication
Environment Variables
The system requires theDEPLOYSTACK_ENCRYPTION_SECRET
environment variable:
Database Schema
API Endpoints
Authentication
All endpoints require authentication and appropriate permissions:- View Settings: Requires
settings.view
permission - Create/Update Settings: Requires
settings.edit
permission - Delete Settings: Requires
settings.delete
permission
Group Management
Get All Groups with Settings
Get Specific Group
Create Group
Update Group
Settings Management
List All Settings
Get Settings by Group
Get Specific Setting
Create New Setting
Update Existing Setting
Delete Setting
Search Settings
Bulk Create/Update Settings
Health Check
Helper Methods (Recommended)
The GlobalSettings helper class provides simple, type-safe methods for retrieving setting values. These helpers are designed for common use cases where you just need the value of a setting, similar to the Email service helper methods.Import the Helper Class
Basic Usage
Get Setting Values
Type-Safe Getters
Advanced Data Types
Batch Operations
Get Multiple Settings
Utility Methods
Check Setting Status
Error Handling
Real-World Examples
SMTP Configuration
Feature Flags
API Configuration
System Configuration
Usage Examples (GlobalSettingsService)
For more complex operations like creating, updating, or searching settings, use the GlobalSettingsService directly:SMTP Configuration
API Keys Management
Auto-Initialization System
Overview
The auto-initialization system automatically creates missing groups and global settings when the server starts. This ensures that all required groups and settings are available without manual configuration, while preserving existing values.File-Based Setting Definitions
Settings are defined in TypeScript files within thesrc/global-settings/
directory:
Setting Definition Format
Each setting file exports aGlobalSettingsModule
with group metadata:
Startup Behavior
When the server starts:- Discovery: Scans
src/global-settings/
for.ts
files - Loading: Dynamically imports each settings module
- Validation: Ensures each module has the correct structure
- Group Creation: Creates missing groups with metadata
- Database Check: Checks which settings exist in the database
- Creation: Creates missing settings with default values and group links
- Preservation: Skips existing settings (non-destructive)
- Logging: Reports initialization results
Example Startup Output
Built-in Setting Groups
SMTP Settings (Group ID: smtp
)
Key | Default | Required | Encrypted | Description |
---|---|---|---|---|
smtp.host | '' | ✅ | ❌ | SMTP server hostname |
smtp.port | '587' | ✅ | ❌ | SMTP server port |
smtp.username | '' | ✅ | ❌ | SMTP authentication username |
smtp.password | '' | ✅ | ✅ | SMTP authentication password |
smtp.secure | 'true' | ❌ | ❌ | Use SSL/TLS connection |
smtp.from_name | 'DeployStack' | ❌ | ❌ | Default sender name |
smtp.from_email | '' | ❌ | ❌ | Default sender email |
GitHub OAuth Settings (Group ID: github-oauth
)
Key | Default | Required | Encrypted | Description |
---|---|---|---|---|
github.oauth.client_id | '' | ❌ | ❌ | GitHub OAuth client ID |
github.oauth.client_secret | '' | ❌ | ✅ | GitHub OAuth client secret |
github.oauth.enabled | 'false' | ❌ | ❌ | Enable GitHub OAuth |
github.oauth.callback_url | 'http://localhost:3000/api/auth/github/callback' | ❌ | ❌ | OAuth callback URL |
github.oauth.scope | 'user:email' | ❌ | ❌ | OAuth requested scopes |
Global Settings (Group ID: global
)
Key | Default | Required | Encrypted | Description |
---|---|---|---|---|
global.page_url | 'http://localhost:5173' | ❌ | ❌ | Base URL for the application frontend |
global.send_mail | 'false' | ❌ | ❌ | Enable or disable email sending functionality |
global.enable_login | 'true' | ❌ | ❌ | Enable or disable all login functionality |
global.enable_email_registration | 'true' | ❌ | ❌ | Enable or disable email registration |
global.enable_swagger_docs | 'true' | ❌ | ❌ | Enable or disable Swagger API documentation endpoint (/documentation) |
Helper Methods
The system provides helper methods for retrieving complete configurations:Adding New Setting Groups (Core)
To add a new core setting group (managed directly by the application):- Create Setting File: Add a new
.ts
file insrc/global-settings/
- Restart Server: The new group and settings will be automatically discovered and initialized
-
Add Helper Method (optional): Add a helper method to
GlobalSettingsInitService
Frontend Integration
The group-based system is designed for easy frontend integration:Dynamic Tab Creation
Group Management
System Configuration
Best Practices
Key Naming Conventions
- Use dot notation for hierarchy:
category.subcategory.setting
- Use lowercase with underscores for readability:
smtp.max_retry_count
- Be descriptive but concise:
api.openai.key
notapi.openai.api_key
- Group related settings:
database.host
,database.port
,database.name
Group Design
- Logical Grouping: Group related settings together (e.g., all SMTP settings)
- Clear Names: Use descriptive group names for frontend display
- Consistent Icons: Use consistent iconography across groups
- Proper Ordering: Set sort_order to control tab display sequence
Setting Organization
- Hierarchical Keys: Use dot notation within groups:
group.subcategory.setting
- Group Consistency: Keep all related settings in the same group
- Clear Descriptions: Provide helpful descriptions for administrators
Security Guidelines
- Always encrypt sensitive data: Passwords, API keys, tokens, secrets
- Use descriptive descriptions: Help other administrators understand the purpose
- Group sensitive settings: Keep all sensitive settings for a service in one group
- Regular audits: Review settings periodically for unused or outdated values
- Environment separation: Use different encryption secrets for different environments
Performance Considerations
- Cache frequently accessed settings: Consider caching non-sensitive, frequently used settings
- Batch operations: Use bulk endpoints when creating multiple related settings
- Minimize database calls: Retrieve settings by group when you need multiple related values
Error Handling
Migration and Setup
Initial Setup
- Environment Variable: Set
DEPLOYSTACK_ENCRYPTION_SECRET
in your environment - Database Migration: Run
npm run db:generate
and restart the server - Admin Access: Ensure you have a user with
global_admin
role
Migrating from Category-Based System
The new group-based system replaces the old category-based approach. The migration is handled automatically:- Database Migration: The
category
column is renamed togroup_id
- Auto-Initialization: Groups are created automatically from setting definitions
- Setting Linking: Existing settings are linked to appropriate groups
Plugin-Contributed Global Settings
In addition to core global settings, plugins can also define and register their own global settings and setting groups. These are managed through the same system and are subject to the same access controls (i.e., editable byglobal_admin
).
Key points for plugin-contributed settings:
- Declaration: Plugins declare global settings via a
globalSettingsExtension
property in their main class. - Initialization: The
PluginManager
processes these definitions at startup, creating new groups and settings if they don’t already exist. - Precedence: Core global settings always take precedence. If a plugin tries to define a setting with a key that already exists (either from core or another plugin), the plugin’s definition for that specific key is ignored.
- Documentation: For details on how plugins can define global settings, refer to the Backend Plugins Docs document.
Helper Methods API Reference
GlobalSettings Class Methods
Method | Description | Returns |
---|---|---|
get(key, defaultValue?) | Get a setting value as string | Promise<string | null> |
getString(key, defaultValue?) | Get a setting value as string (alias) | Promise<string | null> |
getBoolean(key, defaultValue?) | Get a setting value as boolean | Promise<boolean | null> |
getNumber(key, defaultValue?) | Get a setting value as number | Promise<number | null> |
getInteger(key, defaultValue?) | Get a setting value as integer | Promise<number | null> |
getUrl(key, defaultValue?) | Get and validate setting as URL | Promise<string | null> |
getEmail(key, defaultValue?) | Get and validate setting as email | Promise<string | null> |
getJson<T>(key, defaultValue?) | Get and parse setting as JSON | Promise<T | null> |
getArray(key, defaultValue?) | Get setting as array (comma-separated) | Promise<string[]> |
getRequired(key) | Get required setting (throws if missing) | Promise<string> |
getMultiple(keys) | Get multiple settings at once | Promise<Record<string, string | null>> |
getGroupValues(groupId) | Get group settings (without prefix) | Promise<Record<string, string | null>> |
getGroupValuesWithFullKeys(groupId) | Get group settings (with full keys) | Promise<Record<string, string | null>> |
isSet(key) | Check if setting exists and has value | Promise<boolean> |
isEmpty(key) | Check if setting is empty | Promise<boolean> |
exists(key) | Check if setting exists in database | Promise<boolean> |
getRaw(key) | Get raw setting object with metadata | Promise<GlobalSetting | null> |
refreshCaches() | Refresh any cached configurations | Promise<void> |
Boolean Value Parsing
ThegetBoolean()
method accepts these string values:
Value | Result |
---|---|
'true' , '1' , 'yes' , 'on' , 'enabled' | true |
'false' , '0' , 'no' , 'off' , 'disabled' | false |
Usage Patterns
Simple Value Retrieval
Type-Safe Retrieval
Batch Retrieval
Validation and Checks
REST API Reference Summary
Endpoint | Method | Permission | Description |
---|---|---|---|
/api/settings/groups | GET | settings.view | List all groups with settings |
/api/settings/groups/:groupId | GET | settings.view | Get specific group |
/api/settings/groups | POST | settings.edit | Create new group |
/api/settings/groups/:groupId | PUT | settings.edit | Update group |
/api/settings | GET | settings.view | List all settings |
/api/settings/:key | GET | settings.view | Get specific setting |
/api/settings | POST | settings.edit | Create new setting |
/api/settings/:key | PUT | settings.edit | Update setting |
/api/settings/:key | DELETE | settings.delete | Delete setting |
/api/settings/group/:groupId | GET | settings.view | Get settings by group |
/api/settings/search | POST | settings.view | Search settings |
/api/settings/bulk | POST | settings.edit | Bulk create/update |
/api/settings/health | GET | settings.view | System health check |
For more information about the role-based access control system, see ROLES. For security details, see SECURITY.