#bakunin #layered-config


Layered configuration for Rust applications

4 releases

0.1.3 May 8, 2024
0.1.2 Mar 10, 2024
0.1.1 Feb 17, 2024
0.1.0 Feb 17, 2024

#132 in Configuration

Download history 71/week @ 2024-03-12 4/week @ 2024-03-19 4/week @ 2024-03-26 31/week @ 2024-04-02 107/week @ 2024-05-07 2/week @ 2024-05-14 7/week @ 2024-05-21 11/week @ 2024-05-28 1/week @ 2024-06-04 87/week @ 2024-06-11 27/week @ 2024-06-18

115 downloads per month




Layered configuration for Rust applications.


It was created to provide a way to search and load configurations from different sources and merge them into a single configuration value. It uses serde to serialize and deserialize the configuration values, which means that you can use any format supported by serde to store your configuration. By default, it supports JSON, JSON5, TOML, and YAML. It employs a slot system to merge the configuration values, starting from 0 to u64::MAX, where the last one takes precedence


// the default value for our configurations
let default_value = value_map! {
    path: "some/path/to/dir",
    delay: 1000,
    enabled: true,
    log: value_map! {
        level: "info",
        file: "log.txt"

// create a new configuration builder from the default value
let mut builder = ConfigBuilder::from_base(default_value.clone())?;

// Create the root config file path
let root_file: PathBuf = ConfigFileFinder::for_file(".app-config".to_string()) // will search for files .app-config.{ext}
    .with_os_folder(OSFolder::UserHome) // will search in the user home directory: /home/user/
    .with_os_folder(OSFolder::Config) // will search in the user config directory: /home/user/.config/
    .with_os_folder(OSFolder::AppConfig("myapp".to_string())) // will search in the user config directory: /home/user/.config/myapp/
    .with_supported_extensions() // will search for files with the supported extensions: .json, .json5, .toml, .yaml, .yml
    .find_or_first(); // will search for the first file that exists, if none is found, will return the first path

let config_file = ConfigFile::new(root_file)
    .with_init(default_value) // Will create the file with the default value if it does not exist

// add the root config file to the builder, first available means that will be added in the first slot available
builder.add_config_file(config_file, Priority::FirstAvailable)?;

// Will use environment variables to override the configuration values, ex: MY_APP_path will override the path value

let config: Value = builder.build();

#[derive(Serialize, Deserialize)]
/// Logger configuration
pub struct LoggerConfig {
    pub level: String,
    pub file: String,

// Deserialize the configuration value into a LoggerConfig
let log = config.get("log").deserialize::<LoggerConfig>().unwrap();

// Get the path value as a string
let path = config.get("path").try_into_String().unwrap(); // Will panic if the value is not a string

// Get the delay value as a u64
let delay: u64 = config.get("delay").try_into().unwrap(); // Will panic if the value is not a valid u64


~135K SLoC