Skip to content

Configuration

Oxide reads .env on boot and loads every config/*.toml file into a merged tree keyed by filename stem. Values support shell-style interpolation: "${APP_NAME:-My App}".

Files

A new project ships with:

config/
├── app.toml
└── database.toml

Add config/whatever.toml and it’s reachable at the whatever.* key path with zero extra wiring.

Reading config

Three flavours, pick whichever fits the call site:

use oxide_http::prelude::*;
// 1. Free helper — works anywhere.
let name: String = config("app.name").unwrap_or_default();
// 2. Off the request — same semantics, scoped per-request.
async fn handler(req: Request) -> Response {
let debug: bool = req.config("app.debug").unwrap_or(false);
// ...
Response::text("ok")
}
// 3. Typed section, resolved via the container — bound at boot.
#[derive(serde::Deserialize)]
struct AppConfig {
name: String,
debug: bool,
}
// In ConfigServiceProvider::register:
// app.bind_config::<AppConfig>("app");
// In a handler:
let typed = req.resolve::<AppConfig>();
println!("{}", typed.name);

Environment overrides

Inside a TOML value, wrap the env var in ${...}:

name = "${APP_NAME:-Billing API}"
debug = "${APP_DEBUG:-false}"
  • ${VAR} — required; fails loud if unset.
  • ${VAR:-default} — falls back to default if unset.
  • When the whole value is one ${...} expression, it auto-coerces to bool / int / float where the target field expects it.

Tunable framework knobs

Env varDefaultWhat it controls
APP_LISTEN127.0.0.1:8000address the HTTP server binds
APP_BODY_MAX_MB10request body size cap
APP_REQUEST_TIMEOUT_SECS30per-request timeout
APP_SHUTDOWN_TIMEOUT_SECS30graceful drain window on SIGTERM
DB_CONNECTIONsqlitewhich [connections.*] section to use
BCRYPT_ROUNDS12password hash cost (matches Laravel’s default)

Set any of these in .env or your deployment’s environment.