Settings Reference
Complete reference for Reinhardt settings.
Reinhardt Settings System Documentation
Overview
Reinhardt provides a flexible and powerful configuration management system. By combining TOML-format configuration files with environment variables, it enables consistent configuration management across all environments, from development to production.
Key Features
- TOML Format: Easy-to-read and write configuration files
- Environment-Specific Settings: Different configurations for local, staging, production, etc.
- Priority System: Integrates settings from multiple sources with clear priority rules
- Composable Fragments: Build your settings struct from reusable fragments with the
#[settings]macro - No Recompilation Required: No need to rebuild Rust code when changing settings
- Secure: Protects sensitive information with
.gitignore - Extensible: Easy to add custom sources and configuration items
Quick Start
1. Project Setup
Projects created with the reinhardt-admin startproject command already include a settings/ directory:
my-project/
├── settings/
│ ├── .gitignore # Ignores *.toml, only commits *.example.toml
│ ├── base.example.toml # Base configuration template
│ ├── local.example.toml # Local development template
│ ├── staging.example.toml
│ └── production.example.toml
└── src/
└── config/
└── settings.rs # Settings loading logic2. Creating Configuration Files
# Copy example files to create actual configuration files
cd my-project/settings
cp base.example.toml base.toml
cp local.example.toml local.toml
cp staging.example.toml staging.toml
cp production.example.toml production.toml3. Editing Configuration Files
settings/base.toml:
debug = false
secret_key = "your-secret-key-here"
[databases.default]
engine = "postgresql"
host = "localhost"
port = 5432
name = "mydb"
user = "postgres"
password = "change-this"settings/local.toml:
debug = true
secret_key = "development-secret-key"
[databases.default]
name = "mydb_dev"
password = "local-password"4. Settings Loading Code
src/config/settings.rs:
use reinhardt::settings;
use reinhardt::{
CoreSettings, DefaultSource, LowPriorityEnvSource, Profile, SettingsBuilder, TomlFileSource,
};
use std::env;
#[settings(core: CoreSettings /* add fragments here, e.g.: | cache: CacheSettings | session: SessionSettings */)]
pub struct ProjectSettings;
pub fn get_settings() -> ProjectSettings {
let profile_str = env::var("REINHARDT_ENV").unwrap_or_else(|_| "dev".to_string());
let profile = Profile::parse(&profile_str);
let settings_dir = env::current_dir().expect("Failed to get current directory").join("settings");
SettingsBuilder::new()
.profile(profile)
.add_source(DefaultSource::new())
.add_source(LowPriorityEnvSource::new().with_prefix("REINHARDT_"))
.add_source(TomlFileSource::new(settings_dir.join("base.toml")))
.add_source(TomlFileSource::new(settings_dir.join(format!("{}.toml", profile_str))))
.build()
.expect("Failed to build settings")
.into_typed()
.expect("Failed to convert settings")
}5. Starting the Application
# Start in development environment (default)
cargo make runserver
# Explicitly specify environment
REINHARDT_ENV=dev cargo make runserver
REINHARDT_ENV=staging cargo make runserver
REINHARDT_ENV=production cargo make runserverSettings Priority
Settings are merged based on the priority value of each source. Sources with higher priority values override sources with lower priority values.
Priority Values by Source Type
The table below lists sources in order of priority (highest to lowest):
| Source Type | Priority Value | Description |
|---|---|---|
EnvSource | 100 | Highest priority - Environment variables (override all other sources) |
DotEnvSource | 90 | .env file variables (override TOML and defaults) |
TomlFileSource | 50 | TOML configuration files (override defaults and low-priority env vars) |
LowPriorityEnvSource | 40 | Low-priority environment variables (overridden by TOML files) |
DefaultSource | 0 | Lowest priority - Default values defined in code |
Common Configuration Pattern
The documentation examples use this configuration pattern:
SettingsBuilder::new()
.add_source(LowPriorityEnvSource::new().with_prefix("REINHARDT_"))
.add_source(TomlFileSource::new("settings/base.toml"))
.add_source(TomlFileSource::new("settings/local.toml"))
.build()Priority order for this pattern (highest priority first):
- Environment-Specific TOML Files (
local.toml,staging.toml,production.toml) - Priority 50 - Base TOML File (
base.toml) - Priority 50 - Low-Priority Environment Variables (
REINHARDT_prefix withLowPriorityEnvSource) - Priority 40 - Default Values (defined in code) - Priority 0
Note: When multiple sources have the same priority (e.g., base.toml and local.toml), sources added later override earlier ones.
Environment Variable Priority Options
You can choose between two environment variable sources depending on your needs:
Option 1: Low-Priority Environment Variables (Recommended for Development)
.add_source(LowPriorityEnvSource::new().with_prefix("REINHARDT_"))- Priority: 40 (lower than TOML files)
- TOML files override environment variables
- Useful for setting defaults that can be overridden by configuration files
Option 2: High-Priority Environment Variables (Recommended for Production)
.add_source(EnvSource::new().with_prefix("REINHARDT_"))- Priority: 100 (higher than TOML files)
- Environment variables override TOML files
- Useful for production deployments where environment variables should take precedence
Example with LowPriorityEnvSource
# base.toml
debug = false
secret_key = "base-secret"
[databases.default]
host = "localhost"
port = 5432# local.toml
debug = true
[databases.default]
host = "127.0.0.1"# Environment variable (using LowPriorityEnvSource)
export REINHARDT_DATABASE_PORT=5433Result with LowPriorityEnvSource:
debug = true(local.toml overrides base.toml)secret_key = "base-secret"(not defined in local.toml, uses base.toml value)databases.default.host = "127.0.0.1"(local.toml overrides base.toml)databases.default.port = 5432(base.toml overrides environment variable because TOML has higher priority than LowPriorityEnvSource)
Result if using EnvSource instead:
debug = true(local.toml value)secret_key = "base-secret"(base.toml value)databases.default.host = "127.0.0.1"(local.toml value)databases.default.port = 5433(environment variable overrides TOML because EnvSource has higher priority)
Configuration File Structure
Base Configuration (base.toml)
Common settings for all environments:
debug = false
secret_key = "CHANGE_THIS_IN_PRODUCTION"
allowed_hosts = ["localhost", "127.0.0.1"]
[databases.default]
engine = "postgresql"
host = "localhost"
port = 5432
name = "mydb"
user = "postgres"
password = "CHANGE_THIS"
[static_files]
url = "/static/"
root = "static/"
[media]
url = "/media/"
root = "media/"
[logging]
level = "info"
format = "json"Local Development Environment (local.toml)
Settings for development:
debug = true
secret_key = "dev-secret-key-not-for-production"
[databases.default]
name = "mydb_dev"
password = "local-dev-password"
[logging]
level = "debug"
format = "pretty"Staging Environment (staging.toml)
debug = false
secret_key = "staging-secret-key"
allowed_hosts = ["staging.example.com"]
[databases.default]
host = "staging-db.example.com"
name = "mydb_staging"
password = "staging-db-password"
[logging]
level = "info"
format = "json"Production Environment (production.toml)
debug = false
secret_key = "production-secret-key-from-secret-manager"
allowed_hosts = ["www.example.com", "api.example.com"]
[databases.default]
host = "prod-db.example.com"
port = 5432
name = "mydb_production"
user = "app_user"
password = "production-db-password"
[static_files]
url = "https://cdn.example.com/static/"
[media]
url = "https://cdn.example.com/media/"
[logging]
level = "warn"
format = "json"Composable Settings Architecture
Reinhardt's settings system is built on a composable fragment architecture. Instead of a monolithic Settings struct, you compose your ProjectSettings from reusable fragments using the #[settings] macro.
The SettingsFragment Trait
Every settings fragment implements the SettingsFragment trait, which defines the TOML section name and optional profile-based validation:
pub trait SettingsFragment:
Clone + Debug + Serialize + DeserializeOwned + Send + Sync + 'static
{
/// The accessor trait for this fragment.
/// Use `()` for fragments without a dedicated accessor trait.
type Accessor: ?Sized;
/// The TOML section key for this fragment (e.g., "core", "cache").
fn section() -> &'static str;
/// Returns the default field policies for this fragment.
fn field_policies() -> &'static [FieldPolicy] {
&[]
}
/// Optional validation that runs after deserialization.
/// Override this to add profile-specific validation logic.
fn validate(&self, _profile: &Profile) -> ValidationResult {
Ok(())
}
}Available Fragments
Reinhardt provides 12 built-in fragments:
| Fragment | Field Name | TOML Section | Has Trait |
|---|---|---|---|
CoreSettings | core | (flattened) | HasCoreSettings |
SecuritySettings | security | [security] | HasSecuritySettings |
CacheSettings | cache | [cache] | HasCacheSettings |
SessionSettings | session | [session] | HasSessionSettings |
CorsSettings | cors | [cors] | HasCorsSettings |
StaticSettings | static_files | [static_files] | HasStaticSettings |
MediaSettings | media | [media] | HasMediaSettings |
EmailSettings | email | [email] | HasEmailSettings |
LoggingSettings | logging | [logging] | HasLoggingSettings |
I18nSettings | i18n | [i18n] | HasI18nSettings |
TemplateSettings | templates | [templates] | HasTemplateSettings |
ContactSettings | contacts | [contacts] | HasContactSettings |
Note: CoreSettings uses #[serde(flatten)], so its fields (debug, secret_key, database, etc.) appear at the top level in TOML files rather than under a [core] section.
The #[settings] Macro
The #[settings] macro generates a ProjectSettings struct with the specified fragments. All fragments, including CoreSettings, must be declared explicitly.
Basic Usage (CoreSettings only)
use reinhardt::settings;
use reinhardt::CoreSettings;
#[settings(core: CoreSettings)]
pub struct ProjectSettings;
// Generated struct has a `core` field of type CoreSettings.
// Access: settings.core.debug, settings.core.secret_key, etc.Adding Fragments
Use field_name: FragmentType syntax, separated by |:
use reinhardt::settings;
use reinhardt::CoreSettings;
use reinhardt::conf::{CacheSettings, SessionSettings, CorsSettings};
#[settings(core: CoreSettings | cache: CacheSettings | session: SessionSettings | cors: CorsSettings)]
pub struct ProjectSettings;
// Access:
// settings.core.debug
// settings.cache.backend
// settings.session.cookie_name
// settings.cors.allow_originsWithout CoreSettings
If you don't need CoreSettings, simply omit it:
use reinhardt::settings;
use reinhardt::conf::CacheSettings;
#[settings(cache: CacheSettings)]
pub struct ProjectSettings;
// Only has settings.cache, no settings.coreHas* Accessor Traits
Each fragment has a corresponding Has* trait that enables generic programming over settings types. This is useful for writing functions that only require specific fragments.
Note: You do not need to implement Has*Settings traits manually. The #[settings] macro automatically provides blanket implementations for all declared fragments. To use method-call syntax like settings.core() in generic bounds, import the specific Has*Settings trait:
use reinhardt::conf::{HasCoreSettings, HasCacheSettings};
fn configure_app<S: HasCoreSettings + HasCacheSettings>(settings: &S) {
let debug = settings.core().debug;
let cache_backend = &settings.cache().backend;
// Use settings without knowing the concrete ProjectSettings type
}When using the #[settings] macro, you only need to import the fragment types (e.g., CoreSettings), not the accessor traits — the macro generates all necessary trait implementations automatically.
Profile-Based Validation
Fragments can implement custom validation logic that runs based on the active profile:
use reinhardt::SettingsFragment;
use reinhardt::Profile;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct ApiSettings {
pub timeout: u64,
pub max_retries: u32,
pub base_url: String,
}
impl SettingsFragment for ApiSettings {
type Accessor = ();
fn section() -> &'static str { "api" }
fn validate(&self, profile: &Profile) -> ValidationResult {
if profile.is_production() && self.base_url.starts_with("http://") {
return Err("Production API base_url must use HTTPS".into());
}
Ok(())
}
}Configuration via Environment Variables
You can configure settings using environment variables. The priority of environment variables depends on which source you use:
LowPriorityEnvSource(Priority: 40): TOML files override environment variablesEnvSource(Priority: 100): Environment variables override TOML files
The examples in this document use LowPriorityEnvSource, which means TOML files have higher priority than environment variables.
Naming Convention
Environment variable names follow this convention:
REINHARDT_<KEY_NAME>
REINHARDT_<SECTION_NAME>_<KEY_NAME>Examples
# Top-level settings
export REINHARDT_DEBUG=true
export REINHARDT_SECRET_KEY="env-secret-key"
# Settings within sections
export REINHARDT_DATABASE_HOST=localhost
export REINHARDT_DATABASE_PORT=5432
export REINHARDT_DATABASE_NAME=mydb
export REINHARDT_DATABASE_USER=postgres
export REINHARDT_DATABASE_PASSWORD=mypassword
# Nested settings
export REINHARDT_LOGGING_LEVEL=debug
export REINHARDT_STATIC_URL=/static/Choosing Between EnvSource and LowPriorityEnvSource
Use LowPriorityEnvSource when:
- You want TOML files to override environment variables
- You're in development and want configuration files to take precedence
- You want environment variables as fallback defaults
SettingsBuilder::new()
.add_source(LowPriorityEnvSource::new().with_prefix("REINHARDT_"))
.add_source(TomlFileSource::new("settings/base.toml"))
.add_source(TomlFileSource::new("settings/local.toml"))
.build()
// Result: local.toml > base.toml > environment variables > defaultsUse EnvSource when:
- You want environment variables to override TOML files
- You're in production and want environment variables to take precedence
- You're deploying to cloud platforms (Heroku, AWS, etc.) that use environment variables
SettingsBuilder::new()
.add_source(DefaultSource::new())
.add_source(TomlFileSource::new("settings/base.toml"))
.add_source(EnvSource::new().with_prefix("REINHARDT_"))
.build()
// Result: environment variables > base.toml > defaultsManaging Configuration with Environment Variables Only
If you want to manage configuration using only environment variables without TOML files, use EnvSource:
use reinhardt::settings;
use reinhardt::{CoreSettings, DefaultSource, EnvSource, SettingsBuilder};
#[settings(core: CoreSettings)]
pub struct ProjectSettings;
pub fn get_settings() -> ProjectSettings {
SettingsBuilder::new()
.add_source(DefaultSource::new())
.add_source(EnvSource::new().with_prefix("REINHARDT_"))
.build()
.expect("Failed to build settings")
.into_typed()
.expect("Failed to convert settings")
}Loading and Accessing Settings
Basic Loading
src/config/settings.rs:
use reinhardt::settings;
use reinhardt::{
CoreSettings, DefaultSource, LowPriorityEnvSource, Profile, SettingsBuilder, TomlFileSource,
};
use std::env;
#[settings(core: CoreSettings)]
pub struct ProjectSettings;
pub fn get_settings() -> ProjectSettings {
let profile_str = env::var("REINHARDT_ENV").unwrap_or_else(|_| "dev".to_string());
let profile = Profile::parse(&profile_str);
let settings_dir = env::current_dir().expect("Failed to get current directory").join("settings");
SettingsBuilder::new()
.profile(profile)
.add_source(DefaultSource::new())
.add_source(LowPriorityEnvSource::new().with_prefix("REINHARDT_"))
.add_source(TomlFileSource::new(settings_dir.join("base.toml")))
.add_source(TomlFileSource::new(settings_dir.join(format!("{}.toml", profile_str))))
.build()
.expect("Failed to build settings")
.into_typed()
.expect("Failed to convert settings")
}Using in Application
Access settings anywhere in your application code:
use crate::config::settings::get_settings;
let settings = get_settings();
println!("Debug mode: {}", settings.core.debug);
println!("Secret key: {}", settings.core.secret_key);Security Best Practices
1. .gitignore Configuration
settings/.gitignore:
# Actual configuration files are not tracked by Git
*.toml
# Only commit example files
!*.example.tomlProject root .gitignore:
# Configuration files
settings/*.toml
!settings/*.example.toml
# Environment variable files
.env
.env.local
.env.*.local2. Creating Example Files
# Create example files from actual configuration files
cd settings
cp base.toml base.example.toml
cp local.toml local.example.toml
cp staging.toml staging.example.toml
cp production.toml production.example.tomlImportant: Remove sensitive information from *.example.toml files:
# Don't include production secrets
secret_key = "actual-production-secret-key"
password = "real-database-password"
# Use placeholders
secret_key = "CHANGE_THIS_IN_PRODUCTION"
password = "CHANGE_THIS"3. Managing Sensitive Information
For production environments, it's recommended not to write sensitive information directly in TOML files:
Option 1: Environment Variables (lower priority)
export REINHARDT_SECRET_KEY="actual-secret-from-vault"
export REINHARDT_DATABASE_PASSWORD="actual-db-password"Option 2: Secret Management Systems
For production deployments, integrate with secret management systems such as AWS Secrets Manager, HashiCorp Vault, or Azure Key Vault by implementing a custom ConfigSource that fetches secrets at startup. See Implementing Custom Sources for details.
Adding Custom Settings
Creating a Custom Fragment
Define a struct that implements SettingsFragment to add project-specific configuration:
src/config/api_settings.rs:
use reinhardt::SettingsFragment;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ApiSettings {
pub timeout: u64,
pub max_retries: u32,
pub base_url: String,
}
impl Default for ApiSettings {
fn default() -> Self {
Self {
timeout: 30,
max_retries: 3,
base_url: "http://localhost:8080".to_string(),
}
}
}
impl SettingsFragment for ApiSettings {
type Accessor = ();
fn section() -> &'static str { "api" }
}Composing with the #[settings] Macro
use reinhardt::settings;
use reinhardt::conf::CacheSettings;
use crate::config::api_settings::ApiSettings;
#[settings(api: ApiSettings | cache: CacheSettings)]
pub struct ProjectSettings;Adding to TOML Files
settings/base.toml:
[api]
timeout = 30
max_retries = 3
base_url = "http://localhost:8080"settings/local.toml:
[api]
timeout = 60Advanced Usage
Using Multiple File Sources
pub fn get_settings() -> ProjectSettings {
SettingsBuilder::new()
.add_source(LowPriorityEnvSource::new().with_prefix("REINHARDT_"))
.add_source(TomlFileSource::new("settings/base.toml"))
.add_source(TomlFileSource::new("settings/database.toml"))
.add_source(TomlFileSource::new("settings/cache.toml"))
.add_source(TomlFileSource::new("settings/local.toml"))
.build()
.expect("Failed to build settings")
.into_typed()
.expect("Failed to convert settings")
}Using JSON Format
use reinhardt::settings::sources::JsonFileSource;
pub fn get_settings() -> ProjectSettings {
SettingsBuilder::new()
.add_source(JsonFileSource::new("settings/base.json"))
.add_source(JsonFileSource::new("settings/local.json"))
.build()
.expect("Failed to build settings")
.into_typed()
.expect("Failed to convert settings")
}Implementing Custom Sources
use reinhardt::settings::sources::{ConfigSource, SourceError};
use indexmap::IndexMap;
use serde_json::Value;
struct RemoteConfigSource {
url: String,
}
impl ConfigSource for RemoteConfigSource {
fn load(&self) -> Result<IndexMap<String, Value>, SourceError> {
// Implementation to fetch configuration from remote server
// Example: HTTP request to fetch JSON configuration
todo!("Implement remote config loading - fetch from {}", self.url)
}
fn priority(&self) -> u8 {
// Custom priority between TOML files and high-priority env vars
// 0 = lowest, 100 = highest
// 75 = higher than TOML (50) but lower than EnvSource (100)
75
}
fn description(&self) -> String {
format!("Remote configuration from: {}", self.url)
}
}Usage:
pub fn get_settings() -> ProjectSettings {
SettingsBuilder::new()
.add_source(DefaultSource::new())
.add_source(TomlFileSource::new("settings/base.toml"))
.add_source(RemoteConfigSource { url: "https://config.example.com/api/settings".to_string() })
.build()
.expect("Failed to build settings")
.into_typed()
.expect("Failed to convert settings")
}
// Priority order: RemoteConfigSource (75) > TomlFileSource (50) > DefaultSource (0)Troubleshooting
Issue 1: Configuration File Not Found
Error:
Failed to build settings: Source error in 'TOML file: settings/base.toml'Cause:
settings/directory doesn't exist- Required TOML files haven't been created
Solution:
ls settings/
# Verify base.toml, local.toml, etc. exist
# If they don't exist, copy from example files
cp settings/base.example.toml settings/base.tomlIssue 2: TOML Syntax Error
Error:
Failed to build settings: Parse errorCause:
- Incorrect TOML syntax
- Invalid quotes
- Duplicate section names
Solution:
# Use TOML validation tool
cargo install toml-cli
toml get settings/base.toml .
# Use online validation tool
# https://www.toml-lint.com/Issue 3: Type Conversion Error
Error:
Failed to deserialize key 'debug': invalid typeCause:
- Setting value type doesn't match expected type
Solution:
# Correct types
debug = true # Boolean
port = 5432 # Integer
timeout = 30.5 # Float
name = "mydb" # String
# Wrong types
debug = "true" # String (Boolean expected)
port = "5432" # String (Integer expected)Issue 4: Missing Required Field
Error:
Failed to convert to ProjectSettings: missing field 'secret_key'Cause:
- Required field not defined in TOML file
Solution:
# Add required field to base.toml
secret_key = "your-secret-key-here"Issue 5: Environment Variables Not Working
Cause:
- TOML files have higher priority than environment variables
- Environment variable name is incorrect
Solution:
# 1. Remove the setting from TOML file (if you want environment variable to take priority)
# 2. Verify environment variable name
echo $REINHARDT_DATABASE_HOST
# 3. Use correct prefix
export REINHARDT_DATABASE_HOST=localhost # Correct
export DATABASE_HOST=localhost # No prefixPractical Examples
Example 1: Multi-Tenant Configuration
# base.toml
[[tenants]]
name = "tenant1"
database = "tenant1_db"
schema = "public"
[[tenants]]
name = "tenant2"
database = "tenant2_db"
schema = "public"#[derive(Debug, Deserialize)]
pub struct TenantConfig {
pub name: String,
pub database: String,
pub schema: String,
}Example 2: Feature Flag Management
Note: This example shows runtime feature flags (application settings). For compile-time feature flags (Cargo features), see the Feature Flags Guide.
# base.toml
[features]
enable_graphql = false
enable_websockets = false
enable_admin_panel = true
enable_api_versioning = true
# local.toml (all features enabled during development)
[features]
enable_graphql = true
enable_websockets = trueExample 3: External Service Configuration
# base.toml
[services.redis]
host = "localhost"
port = 6379
db = 0
[services.rabbitmq]
host = "localhost"
port = 5672
vhost = "/"
[services.elasticsearch]
hosts = ["http://localhost:9200"]Performance and Best Practices
1. Initialize Settings Only Once
use std::sync::LazyLock;
static SETTINGS: LazyLock<ProjectSettings> = LazyLock::new(|| {
get_settings()
});
// Settings are loaded only once, even if accessed multiple times
// Access from anywhere in your application:
// SETTINGS.core.debug
// SETTINGS.core.secret_key2. Settings Validation
Fragments support profile-based validation via the SettingsFragment::validate() method. Validation runs automatically during into_typed() when a profile is set.
You can also add application-level validation:
pub fn get_settings() -> ProjectSettings {
let settings: ProjectSettings = SettingsBuilder::new()
// ... add sources ...
.build()
.expect("Failed to build settings")
.into_typed()
.expect("Failed to convert settings");
// Fragment-level validation has already run at this point.
// Additional application-level validation
validate_settings(&settings).expect("Invalid settings");
settings
}
fn validate_settings(settings: &ProjectSettings) -> Result<(), String> {
if settings.core.secret_key == "CHANGE_THIS_IN_PRODUCTION" {
return Err("Secret key not set!".to_string());
}
Ok(())
}3. Type-Safe Settings Access
// Access via struct field (type-safe)
let debug = settings.core.debug;
let secret = settings.core.secret_key.clone();Summary
Reinhardt's settings system is:
- Flexible: Supports multiple sources including TOML, JSON, and environment variables
- Composable: Build your settings from reusable fragments with
#[settings] - Secure: Protects sensitive information with
.gitignore, type-safe access - Efficient: No recompilation required, settings loaded only once
- Environment-Aware: Separates configuration for local, staging, production, etc.
- Extensible: Easy to add custom sources and configuration items
Next Steps
- Getting Started Guide - Basic usage of Reinhardt
- Example Projects - Real project examples
- reinhardt-conf API Documentation - Detailed API specification
Questions or feedback: https://github.com/kent8192/reinhardt-web/issues