LogseqSpringThing uses a layered configuration system combining YAML files, environment variables, and runtime settings. This guide covers all configuration options and best practices.
graph TD
ENV[Environment Variables] --> YAML[YAML Config Files]
YAML --> RUNTIME[Runtime Settings]
RUNTIME --> APP[Application State]
style ENV fill:#f9f,stroke:#333,stroke-width:2px
style YAML fill:#bbf,stroke:#333,stroke-width:2px
style RUNTIME fill:#bfb,stroke:#333,stroke-width:2px
Priority order (highest to lowest):
- Environment variables
- Command-line arguments
- YAML configuration files
- Default values
# Server Configuration
server:
host: "0.0.0.0"
port: 8080
workers: 4
shutdown_timeout: 30
# Database Configuration
database:
url: "postgres://user:pass@localhost/dbname"
max_connections: 10
connection_timeout: 30
# Graph Settings
graph:
max_nodes: 100000
simulation:
repulsion_strength: 100.0
attraction_strength: 0.01
centering_strength: 0.01
damping: 0.9
time_step: 0.016
# AI Services
ragflow:
api_key: "${RAGFLOW_API_KEY}"
base_url: "https://api.ragflow.com"
timeout: 30
max_retries: 3
perplexity:
api_key: "${PERPLEXITY_API_KEY}"
base_url: "https://api.perplexity.ai"
model: "mixtral-8x7b-instruct"
max_tokens: 2048
temperature: 0.7
# Authentication
auth:
nostr:
enabled: true
relay_urls:
- "wss://relay.damus.io"
- "wss://nostr.wine"
api_keys:
enabled: true
rotation_days: 90
# Feature Access
features:
power_users_enabled: true
power_user_keys:
- "${POWER_USER_KEY_1}"
- "${POWER_USER_KEY_2}"
enabled_features:
- graph_visualization
- ai_chat
- speech_recognition
- xr_support
# GPU Configuration
gpu:
enabled: true
device_id: 0
fallback_to_cpu: true
block_size: 256
max_memory_mb: 4096
# Logging
logging:
level: "info"
format: "json"
file: "logs/server.log"
max_size_mb: 100
max_files: 10
# CORS Settings
cors:
allowed_origins:
- "http://localhost:3000"
- "http://localhost:5173"
allowed_methods:
- "GET"
- "POST"
- "PUT"
- "DELETE"
allowed_headers:
- "Content-Type"
- "Authorization"
- "X-API-Key"# User-specific settings
theme: "dark"
language: "en"
# Visualization preferences
visualization:
node_size: 10
edge_width: 2
label_size: 12
show_labels: true
animation_speed: 1.0
# Client preferences
client:
auto_connect: true
reconnect_attempts: 5
reconnect_delay: 1000# Server
HOST=0.0.0.0
PORT=8080
RUST_LOG=info
# Database
DATABASE_URL=postgres://user:pass@localhost/dbname
# Security
SECRET_KEY=your-secret-key-here
JWT_SECRET=your-jwt-secret
# AI Services
RAGFLOW_API_KEY=your-ragflow-key
PERPLEXITY_API_KEY=your-perplexity-key
OPENAI_API_KEY=your-openai-key
# Feature Access
POWER_USER_KEY_1=key1
POWER_USER_KEY_2=key2
# GPU
CUDA_ENABLED=true
CUDA_DEVICE_ID=0
CUDA_VISIBLE_DEVICES=0
# Development
DEV_MODE=false
HOT_RELOAD=true# Docker-specific
DOCKER_BUILDKIT=1
COMPOSE_PROJECT_NAME=logseq-spring-thing
# Volumes
DATA_PATH=/data
LOGS_PATH=/logs
# Networking
EXTERNAL_PORT=8080
INTERNAL_PORT=8080The SettingsActor manages runtime configuration changes:
// Get current settings
let settings = settings_actor.send(GetSettings).await?;
// Update specific setting
settings_actor.send(SetSettingByPath {
path: "graph.simulation.damping".to_string(),
value: json!(0.95),
}).await?;Client settings are synchronized via WebSocket:
// Client-side
const settings = {
theme: 'dark',
visualization: {
nodeSize: 12,
showLabels: true
}
};
websocket.send({
type: 'updateSettings',
payload: settings
});pub struct AppFullSettings {
// Server configuration
pub server: ServerConfig,
// Graph settings
pub graph: GraphConfig,
// AI service settings
pub ragflow: Option<RagflowConfig>,
pub perplexity: Option<PerplexityConfig>,
// Authentication
pub auth: AuthConfig,
// Feature flags
pub features: FeatureConfig,
// GPU settings
pub gpu: GpuConfig,
// User settings
pub user_settings: UserSettings,
}Configuration is validated on load:
impl AppFullSettings {
pub fn validate(&self) -> Result<(), ConfigError> {
// Validate port range
if self.server.port < 1024 || self.server.port > 65535 {
return Err(ConfigError::InvalidPort);
}
// Validate GPU settings
if self.gpu.enabled && self.gpu.device_id > 7 {
return Err(ConfigError::InvalidGpuDevice);
}
Ok(())
}
}sequenceDiagram
participant Main
participant Config
participant Env
participant File
Main->>Config: load_configuration()
Config->>File: Read config.yml
Config->>File: Read settings.yaml
Config->>Env: Override with env vars
Config->>Config: Validate
Config-->>Main: AppFullSettings
pub async fn load_configuration() -> Result<AppFullSettings, ConfigError> {
// Load base configuration
let mut config = Config::new();
// Add YAML files
config.merge(File::with_name("config.yml"))?;
config.merge(File::with_name("data/settings.yaml").required(false))?;
// Override with environment variables
config.merge(Environment::with_prefix("APP").separator("__"))?;
// Deserialize and validate
let settings: AppFullSettings = config.try_into()?;
settings.validate()?;
Ok(settings)
}Enable configuration hot reloading:
// Watch for config file changes
let mut watcher = notify::recommended_watcher(|res| {
match res {
Ok(event) => reload_config(event),
Err(e) => error!("Watch error: {:?}", e),
}
})?;
watcher.watch(Path::new("config.yml"), RecursiveMode::NonRecursive)?;Dynamic feature toggles:
// Check if feature is enabled
if settings.features.is_enabled("ai_chat") {
// Enable AI chat functionality
}
// Toggle feature at runtime
settings_actor.send(SetSettingByPath {
path: "features.enabled_features".to_string(),
value: json!(["graph_visualization", "ai_chat"]),
}).await?;-
Never commit secrets: Use environment variables
api_key: "${API_KEY}" # Good api_key: "sk-12345" # Bad
-
Rotate keys regularly
# Generate new API key openssl rand -hex 32 -
Use secrets management
# Docker secrets docker secret create api_key ./api_key.txt
# Restrict feature access
features:
power_users_only:
- admin_panel
- gpu_compute
- bulk_operations-
Environment-Specific Configs
# Development cp config.dev.yml config.yml # Production cp config.prod.yml config.yml
-
Configuration Validation
#[test] fn test_config_validation() { let config = load_test_config(); assert!(config.validate().is_ok()); }
-
Documentation
# Always document configuration options graph: max_nodes: 100000 # Maximum nodes in graph (affects memory usage)
-
Defaults
impl Default for GraphConfig { fn default() -> Self { Self { max_nodes: 10000, simulation: SimulationParams::default(), } } }
-
Configuration not loading
# Check file permissions ls -la config.yml # Validate YAML syntax yamllint config.yml
-
Environment variables not working
# Debug environment env | grep APP_ # Check variable expansion echo $DATABASE_URL
-
Type mismatches
# Ensure correct types port: 8080 # Number, not "8080" enabled: true # Boolean, not "true"
// Enable config debugging
std::env::set_var("CONFIG_DEBUG", "true");
// Log loaded configuration
info!("Loaded config: {:?}", settings);# Old format
ai_service:
type: "ragflow"
key: "xxx"
# New format
ragflow:
api_key: "xxx"
base_url: "https://api.ragflow.com"- Server Configuration - Server-specific settings
- Feature Access - Feature flag system
- Environment Setup - Development environment
- Deployment - Production configuration