Web

Config and logging

Settings come from .env and the environment, and real environment variables always win, so production sets values in the environment and development keeps them in .env. Logs follow the familiar PSR-3 levels.

Reading settings#

use rustclamp::config::Config;

let config = Config::load();                          // .env, then the environment on top
let name = config.get("APP_NAME");                   // Option<&str>
let per_minute: u32 = config.get_or("API_PER_MINUTE", 60);
let mail_from = config.require("MAIL_FROM");          // panics at startup, naming the key
  • .env format: KEY=value lines, optional export, # comments, and quotes around a value are removed. Loading never changes the process environment.
  • Fail at startup, not at 3 a.m.: get_or panics when a key is set but does not parse, and require when it is missing. Both name the key.
  • No leaks: Debug on Config prints keys only, never values.

Typed settings#

The web template reads everything once, into a struct the rest of the app uses:

pub struct Settings {
    pub api_per_minute: u32,
    pub trust_proxy: bool,
}

impl Settings {
    pub fn from(config: &Config) -> Self {
        Self {
            api_per_minute: config.get_or("API_PER_MINUTE", 60),
            trust_proxy: config.get_or("TRUST_PROXY", false),
        }
    }
}

.env.example lists every key, and .env itself stays out of git.

Logging#

use rustclamp::log::Log;

Log::info("server started");
Log::warning(format_args!("slow request: {} ms", 850));
SettingValues
LOG_LEVELdebug (default), info, notice, warning, error, critical, alert, emergency, or silent
LOG_CHANNELfile (default) appends to storage/logs/app.log; stderr for systemd and containers
APP_ENVThe environment name in each line, local by default

Each entry is one line, [2026-09-29 14:03:07] local.INFO: message, in UTC, with line breaks escaped so an entry never spans lines. A failed write is ignored: logging never takes the app down. For a separate file, or in tests, build a Logger with Logger::file or Logger::stderr.