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

precedence, highest first
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
proof: a shell export beats every file
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.

← Back to Scenarios