Load configuration once

Hard-coded loopback settings are useful for a first example. When a deployment needs to choose a listen address or a database URL, load those values at startup and validate them before opening listeners. Business services should receive the settings they need, not read environment variables during each operation.

Use an existing component's settings

With iet-http-axum's host feature enabled, HostConfig already describes HTTP listener settings. This startup fragment loads them; the enclosing function returns iet_core::AppResult<()>:

rust
use iet_config::ConfigLoader;
use iet_config_env::EnvSource;
use iet_http_axum::HostConfig;

let source = EnvSource::snapshot("NOTES")?;
let http: HostConfig = ConfigLoader::new(source).load()?;

EnvSource takes an immutable snapshot, rather than rereading the environment later. The NOTES argument adds a deployment-specific prefix. HostConfig asks for the logical key HTTP_ADDRESS; this source reads NOTES_HTTP_ADDRESS.

Environment variable with this prefixDefaultMeaning
NOTES_HTTP_ADDRESS127.0.0.1:3000Address on which to bind
NOTES_HTTP_BODY_LIMIT16384Host body limit in bytes; allowed 1–16777216
NOTES_HTTP_SHUTDOWN_SECONDS30Drain budget after shutdown; allowed 1–3600

These are HostConfig defaults, not a claim that every example uses this prefix or this port. Check the example's startup code before applying an environment variable to it.

Missing values use the declared defaults. Malformed supplied values fail instead of silently falling back. EnvSource does not load .env files: export variables in your shell or arrange for your process manager to supply them.

Declare application-owned settings

For your own component, derive Configuration on a settings struct. The following is a complete definition; it needs iet-config, iet-config-macros, and iet-core:

rust
#[derive(Debug, iet_config_macros::Configuration)]
#[config(prefix = "NOTES")]
pub struct StorageConfig {
    #[config(default = 1000, range(min = 1, max = 100_000))]
    pub capacity: usize,
}

capacity is an application choice: the framework does not impose this setting on a notes service. Load it through ConfigLoader::load::<StorageConfig>(), then pass the validated capacity to your service constructor.

Be careful with the two prefixes. #[config(prefix = "NOTES")] makes the logical key NOTES_CAPACITY. An EnvSource::snapshot("APP") then reads APP_NOTES_CAPACITY. The struct prefix groups a component's keys; the environment prefix groups one application's variables. This StorageConfig is an independent example, not the tutorial's NotesConfig: the tutorial uses no struct prefix and loads NOTES_CAPACITY through its NOTES environment prefix.

Keep secrets explicit

iet_config::Secret<T> redacts its Debug output and requires an explicit .expose() to access the value. It is not a zeroizing secret vault and does not make logging the exposed value safe. Configuration errors intentionally omit raw supplied values.

If the derive cannot express your validation, implement Configuration::load and Configuration::validate yourself. Keep using ConfigLoader: it calls both steps and prevents a caller from forgetting validation.

Source: crates/core/iet-config/src/lib.rs, crates/features/iet-config-env/src/lib.rs, and crates/features/iet-http-axum/src/config.rs.

IET Framework documentation — built with the IET Framework.