cfg-rs is a lightweight, flexible configuration loader for Rust applications. It composes multiple sources (files, env, inline maps, random, etc.), supports live refresh, placeholder expansion, and derive-based typed configs — all without a serde dependency.
See the examples directory for end-to-end demos: https://github.com/leptonyu/cfg-rs/tree/main/examples
- Single call to load typed config: see Configuration::get
- Derive your config types: see FromConfig
- Default values via field attributes: see field attributes
- Placeholder expansion like
${cfg.key}: see ConfigValue - Random values under the
randfeature (e.g.configuration.get::<u8>("random.u8")) - Refreshable values via RefValue and refreshable Configuration
- Pluggable sources with clear priority: see register_source1
- No serde dependency
Built-in file parsers (enable via Cargo features):
toml: extensions.toml,.tmlyaml: extensions.yaml,.ymljson: extension.jsonini: extension.ini
Other useful features:
rand: random value provider (e.g.random.u8,random.string)log: minimal logging integration for value parsingcoarsetime: coarse time helpers for time-related values
Add to your Cargo.toml with the features you need:
[dependencies]
cfg-rs = { version = "^0.6", features = ["toml"] }For a batteries-included setup, use the convenience feature set:
cfg-rs = { version = "^0.6", features = ["full"] }use cfg_rs::*;
let configuration = Configuration::with_predefined().unwrap();
// use configuration.get::<T>("your.key") or derive types (see below)See PredefinedConfigurationBuilder::init for details.
use cfg_rs::*;
init_cargo_env!();
let configuration = Configuration::with_predefined_builder()
.set_cargo_env(init_cargo_env())
.init()
.unwrap();use cfg_rs::*;
init_cargo_env!();
let mut configuration = Configuration::new()
// Layer 0: Cargo env source.
.register_source(init_cargo_env()).unwrap()
// Layer 1: Inline key-values.
.register_kv("inline")
.set("hello", "world")
.finish()
.unwrap();
// Layer 2: Random values (feature = "rand").
#[cfg(feature = "rand")]
{
configuration = configuration.register_random().unwrap();
}
// Layer 3: All environment variables with prefix `CFG_`.
configuration = configuration.register_prefix_env("CFG").unwrap();
// Layer 4: File(s) — extension inferred by feature (e.g. yaml).
configuration = configuration.register_file("/conf/app.yaml", true).unwrap();
// Optional: register an inline file content (e.g. TOML) and merge.
#[cfg(feature = "toml")]
{
let toml = inline_source!("../app.toml").unwrap();
configuration = configuration.register_source(toml).unwrap();
}
// Finally use it.
// let port: u16 = configuration.get("server.port").unwrap();See register_kv, register_file, register_random, and register_prefix_env.
- From inline map (macro):
#[derive(Debug, cfg_rs::FromConfig)]
struct AppCfg { port: u16, host: String }
let cfg: AppCfg = cfg_rs::from_static_map!(AppCfg, {
"port" => "8080",
"host" => "localhost",
});- From environment variables:
#[derive(Debug, cfg_rs::FromConfig)]
struct AppCfg { port: u16, host: String }
std::env::set_var("CFG_APP_PORT", "8080");
std::env::set_var("CFG_APP_HOST", "localhost");
let cfg: AppCfg = cfg_rs::from_env("CFG_APP").unwrap();Implement strong-typed configs via derive:
#[derive(Debug, cfg_rs::FromConfig)]
#[config(prefix = "cfg.app")] // optional, implements FromConfigWithPrefix
struct AppCfg {
port: u16, // required
#[config(default = true)]
enabled: bool, // has default value
#[config(name = "ip")] // remap field name
host: String,
}Attributes summary:
#[config(prefix = "cfg.app")]on struct: implementFromConfigWithPrefix#[config(name = "...")]on field: rename field key#[config(default = <expr>)]on field: default value when missing
See the full reference in derive.FromConfig.
- Placeholder expansion: use
${some.key}inside string values; see ConfigValue - Random values: under
rand, keys likerandom.u8,random.stringprovide per-read randoms - Refreshing:
Configuration::refresh()re-reads sources that allow refresh;RefValue<T>updates on refresh
Browse runnable examples covering common patterns:
simple: minimal setup (full feature set)profile: working with profiles (requirestoml)watch: basic file watching and refresh (requiresyaml)refresh: manual refresh andRefValuelogger: logging integration (requiresfull)thread_pool,salak,test_suit: larger samples and integrations
https://github.com/leptonyu/cfg-rs/tree/main/examples
rustc 1.81+
MIT © contributors. See LICENSE.
- Source priority is deterministic: earlier registrations override later ones1
- This crate intentionally does not depend on serde
- Docs.rs builds enable all features for a comprehensive reference