cfg-rs: A Configuration Library for Rust Applications
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
Features
- 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_source[^priority]
- No serde dependency
[^priority]: Source precedence follows registration order — earlier registrations have higher priority.
Supported formats and feature flags
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
Installation
Add to your Cargo.toml with the features you need:
[]
= { = "^0.6", = ["toml"] }
For a batteries-included setup, use the convenience feature set:
= { = "^0.6", = ["full"] }
Quick start
1) One-liner with predefined sources
use *;
let configuration = with_predefined.unwrap;
// use configuration.get::<T>("your.key") or derive types (see below)
See PredefinedConfigurationBuilder::init for details.
2) Customize predefined builder
use *;
init_cargo_env!;
let configuration = with_predefined_builder
.set_cargo_env
.init
.unwrap;
3) Compose your own sources (priority = registration order)
use *;
init_cargo_env!;
let mut configuration = new
// Layer 0: Cargo env source.
.register_source.unwrap
// Layer 1: Inline key-values.
.register_kv
.set
.finish
.unwrap;
// Layer 2: Random values (feature = "rand").
// Layer 3: All environment variables with prefix `CFG_`.
configuration = configuration.register_prefix_env.unwrap;
// Layer 4: File(s) — extension inferred by feature (e.g. yaml).
configuration = configuration.register_file.unwrap;
// Optional: register an inline file content (e.g. TOML) and merge.
// Finally use it.
// let port: u16 = configuration.get("server.port").unwrap();
See register_kv, register_file, register_random, and register_prefix_env.
4) Handy helpers for tests and small apps
- From inline map (macro):
use *;
let cfg: AppCfg = from_static_map!;
- From environment variables:
use *;
set_var;
set_var;
let cfg: AppCfg = from_env.unwrap;
Derive typed configs
Implement strong-typed configs via derive:
use *;
// optional, implements FromConfigWithPrefix
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.
Placeholders, randoms, and refresh
- 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
Examples
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
Minimum supported Rust version
rustc 1.81+
License
MIT © contributors. See LICENSE.
Tips and notes
- Source priority is deterministic: earlier registrations override later ones[^priority]
- This crate intentionally does not depend on serde
- Docs.rs builds enable all features for a comprehensive reference