The configuration module manages application settings, environment variables, and feature flags.
The primary configuration struct is AppFullSettings, defined in src/config/mod.rs. This struct aggregates all server-side settings, which are then used to derive client-facing settings (UISettings).
// In src/config/mod.rs
pub struct AppFullSettings {
pub visualisation: VisualisationSettings,
pub system: ServerSystemConfigFromFile, // Contains network, websocket, security, debug
pub xr: XRSettings,
pub auth: AuthSettings,
// Optional AI Service Configurations
pub ragflow: Option<RagFlowSettings>,
pub perplexity: Option<PerplexitySettings>,
pub openai: Option<OpenAISettings>,
pub kokoro: Option<KokoroSettings>,
pub whisper: Option<WhisperSettings>,
}visualisation: VisualisationSettings: Configures 3D graph rendering, physics, animations, labels, bloom, and hologram effects. Contains nested structs likeNodeSettings,EdgeSettings,PhysicsSettings, etc.system: ServerSystemConfigFromFile: Contains core server system settings:network: NetworkSettings(e.g.,bind_address,port,enable_tls)websocket: ServerFullWebSocketSettings(e.g.,binary_chunk_size,update_rate,compression_enabled,min_update_rate,max_update_rate,motion_threshold)security: SecuritySettings(e.g.,allowed_origins,session_timeout)debug: DebugSettings(e.g.,enabled,log_level,log_full_json)
xr: XRSettings: Configures WebXR-specific parameters.auth: AuthSettings: Configures authentication provider settings (e.g., Nostr challenge settings).- Optional AI Services:
ragflow: Option<RAGFlowConfig>perplexity: Option<PerplexityConfig>openai: Option<OpenAIConfig>(may include API keys for various OpenAI services like TTS, STT/Whisper)kokoro: Option<KokoroConfig>
Note: whisper settings are now included as Option<WhisperSettings> within AppFullSettings.
Settings are loaded from a YAML file (defaulting to /app/settings.yaml) and can be overridden by environment variables. The config crate is used for this hierarchical loading.
impl AppFullSettings {
pub fn new() -> Result<Self, ConfigError> {
dotenvy::dotenv().ok(); // Loads .env file
let settings_path = std::env::var("SETTINGS_FILE_PATH")
.map(PathBuf::from)
.unwrap_or_else(|_| PathBuf::from("/app/settings.yaml"));
let builder = config::ConfigBuilder::<config::builder::DefaultState>::default()
.add_source(config::File::from(settings_path.clone()).required(true))
.add_source(
config::Environment::default()
.separator("_") // e.g., SYSTEM_NETWORK_PORT
.list_separator(",")
);
let config = builder.build()?;
config.try_deserialize()
}
}Feature access is managed by the FeatureAccess struct defined in src/config/feature_access.rs. This struct is initialized from environment variables and provides fine-grained access control.
pub struct FeatureAccess {
// Base access control
pub approved_pubkeys: Vec<String>,
// Feature-specific access
pub perplexity_enabled: Vec<String>,
pub openai_enabled: Vec<String>,
pub ragflow_enabled: Vec<String>,
// Role-based access control
pub power_users: Vec<String>,
pub settings_sync_enabled: Vec<String>,
}
impl FeatureAccess {
pub fn from_env() -> Self;
pub fn register_new_user(&mut self, pubkey: &str) -> bool;
pub fn has_access(&self, pubkey: &str) -> bool;
pub fn has_perplexity_access(&self, pubkey: &str) -> bool;
pub fn has_openai_access(&self, pubkey: &str) -> bool;
pub fn has_ragflow_access(&self, pubkey: &str) -> bool;
pub fn is_power_user(&self, pubkey: &str) -> bool;
pub fn can_sync_settings(&self, pubkey: &str) -> bool;
pub fn has_feature_access(&self, pubkey: &str, feature: &str) -> bool;
pub fn get_available_features(&self, pubkey: &str) -> Vec<String>;
}For detailed information about feature access control, see Feature Access Documentation.
Security-related configurations are defined in the SecuritySettings struct, which is nested within ServerSystemConfigFromFile (i.e., app_full_settings.system.security).
pub struct SecuritySettings {
pub allowed_origins: Vec<String>,
pub audit_log_path: String,
pub cookie_httponly: bool,
pub cookie_samesite: String,
pub cookie_secure: bool,
pub csrf_token_timeout: u32,
pub enable_audit_logging: bool,
pub enable_request_validation: bool,
pub session_timeout: u32,
}Rate limiting is configured within NetworkSettings (e.g., rate_limit_requests, rate_limit_window) and applied at the network layer.
- YAML Configuration File: Primary source of settings (
/app/settings.yaml). - Environment Variables: Overrides values from the YAML file (e.g.,
APP_NETWORK_PORT). - Default Values: Provided by
Defaultimplementations for structs if not specified elsewhere.
Settings are validated during deserialization by the config crate. Custom validation logic can be implemented within AppFullSettings or its sub-structs if needed.
The current implementation does not support hot reloading of configuration. Changes to settings.yaml or environment variables require a server restart to take effect.
AppFullSettings implements a save(&self) -> Result<(), String> method to persist the current settings state back to the specified YAML file (typically settings.yaml). This serialization is done using serde_yaml and handles converting the Rust struct (usually in snake_case or as defined by serde attributes) to YAML format. This method is invoked when power users modify global settings that need to be persisted.
The AppFullSettings struct itself derives Serialize and Deserialize from serde for this purpose.
The client communicates settings updates through a comprehensive payload structure defined in src/models/client_settings_payload.rs. This structure mirrors the client's TypeScript settings but uses Rust conventions:
#[derive(Deserialize, Debug, Default, Clone)]
pub struct ClientSettingsPayload {
pub visualisation: Option<ClientVisualisationSettings>,
pub system: Option<ClientSystemSettings>,
pub xr: Option<ClientXRSettings>,
pub auth: Option<ClientAuthSettings>,
pub ragflow: Option<ClientRagFlowSettings>,
pub perplexity: Option<ClientPerplexitySettings>,
pub openai: Option<ClientOpenAISettings>,
pub kokoro: Option<ClientKokoroSettings>,
}The system handles automatic conversion between:
- Client Format: camelCase JSON from TypeScript
- Server Format: snake_case Rust structs
- UI Settings: Subset of settings safe for client display
Users with settings_sync permission can store and retrieve their settings across devices:
- Settings are stored per user (by Nostr pubkey)
- Power users can modify global server settings
- Cache management for performance optimization
SETTINGS_FILE_PATH- Path to settings YAML file (default:/app/settings.yaml)SYSTEM_NETWORK_PORT- Override network portSYSTEM_NETWORK_BIND_ADDRESS- Override bind address
APPROVED_PUBKEYS- Comma-separated list of approved user pubkeysPERPLEXITY_ENABLED_PUBKEYS- Users with Perplexity AI accessOPENAI_ENABLED_PUBKEYS- Users with OpenAI/Kokoro accessRAGFLOW_ENABLED_PUBKEYS- Users with RAGFlow chat accessPOWER_USER_PUBKEYS- Comma-separated list of administrative usersSETTINGS_SYNC_ENABLED_PUBKEYS- Users who can sync settings
PERPLEXITY_API_KEY- Perplexity AI service keyOPENAI_API_KEY- OpenAI service keyRAGFLOW_API_KEY- RAGFlow service keyKOKORO_API_URL- Kokoro TTS service URL
- Secrets Management: Never commit API keys to version control
- Environment Separation: Use different settings files for dev/staging/prod
- Validation: Implement custom validation for critical settings
- Documentation: Keep settings documentation in sync with code
- Backwards Compatibility: Handle missing optional fields gracefully
- Performance: Cache frequently accessed settings
- Security: Validate all client-provided settings before applying