9 · Secrets via .env layering
Highest wins: process env > -env/ROUTSI_ENV_FILE > ./.env > ~/.config/routsi/.env.
What it is
On startup routsi loads environment variables from up to three files, layered under whatever the process already has exported, so that api_key_env / auth.tokens_env names in models.yaml resolve without every deployment having to export vars in its shell profile.
Why
models.yaml only ever holds env-var names, never secret values — that's the whole point of api_key_env. This scenario proves the precedence is real: a value already in the process environment (systemd unit, launchd plist, CI secret) can never be silently overridden by a stray .env file lying around in a working directory, which matters once multiple .env files could plausibly exist on the same box.
Configure
1. process environment # shell export / systemd / launchd — always wins 2. -env <path> or ROUTSI_ENV_FILE # an explicit env file 3. ./.env # working directory 4. ~/.config/routsi/.env # per-user default
echo 'OPENAI_API_KEY=from-config-dir-file' > ~/.config/routsi/.env echo 'OPENAI_API_KEY=from-dot-env' > ./.env OPENAI_API_KEY=from-shell routsi serve # → routsi uses "from-shell": process env always wins, files never override it
Full precedence details: Auth & mTLS → Secrets via .env.
How to adapt
Pick whichever layer fits your deployment: a container/service manager that already injects env vars needs nothing extra (layer 1 wins outright); a shared dev box can keep provider keys in ~/.config/routsi/.env (chmod 600) so they survive across projects; a one-off or CI run can point -env ./ci.env (or ROUTSI_ENV_FILE) at a specific file without touching the others. Whichever file you use, reference the variable by name in models.yaml (api_key_env: OPENAI_API_KEY) — never inline the value.