vike
Reference

Environment variables

The risk ceilings have no environment layer at all, three variables are refused at startup rather than ignored, and every read the workspace performs is declared in a CI-gated registry.

Three rules govern the environment, each because its opposite produced a real defect.

The ceilings are not env-settable, at all

vike_config::Policy — leverage, per-order notional, the slippage band, the halt-file admit mode, the per-venue arming ceiling — implements neither EnvOverride nor CliOverride, and crates/vike-config/src/layers.rs seals both traits, so an override is a compile error rather than a review comment. Everything else resolves default, then file, then environment, then CLI. Settings carries the split; the files are on the settings reference.

Removed variables refuse to start

Deleting a read is only half the job. An operator who set VIKE_MAX_ORDER_NOTIONAL=250 believes a ceiling is active; a build that quietly stopped reading it would trade uncapped while they believed otherwise. crates/vike-config/src/removed.rs's REMOVED_ENV is the table, and refuse_removed_env is the first step of startup for every root that loads settings — vike-desktop, vike-tradehub and vike-cli:

variablereplaced bywhy it went
VIKE_MAX_ORDER_NOTIONALpolicy.toml — max_notional_per_orderan order-size ceiling any exported variable can raise is not a ceiling
VIKE_TRADEHUB_MAX_ORDER_NOTIONALpolicy.toml — max_notional_per_orderan order-size ceiling any exported variable can raise is not a ceiling
VIKE_SECRETS_PASSPHRASEsecrets.envnothing consumes it — credentials are read from the project's own store, in plaintext

"Set" means present with a non-empty value after trimming: an empty VAR= configured nothing under the old readers either, so refusing over a leftover blank line would turn a harmless artefact into an outage. Every offender is reported in one pass, and the message renders the operator's own value as a paste-ready TOML line — unless the value would itself be a secret, where echo_value is false and only the name is printed, since echoing one turns a startup error into a credential in any log capturing stderr.

Two daemons deliberately do not refuse, each stating its reason in its own boot spec rather than as a bare flag — crates/vike-boot/src/lib.rs's RemovedEnv::Ignore. The recorder and the data service read none of the ceilings whose variables were removed, and a recorder must not acquire a new reason to fail to start; on those boxes vike-cli config check, which the shipped units put in their ExecStartPre=, is the surface that refuses a stale environment.

A removed FILE refuses the same way — and says which of two things it found

A <project>/vike.toml override layer once sat above <project>/settings/, reintroducing the which file won? question that directory exists to answer. It is refused by name from inside the loader, and only NotFound counts as absent — anything else means absence was not established, so it refuses too, with a different message. Under a service sandbox a stat below the home tree returns EACCES, not ENOENT, and the fail-closed verdict once named a file that did not exist. Nothing here rewrites the file: it is the operator's.

Every read is declared

vike_ops::settings::SETTINGS is a verbatim registry of every environment variable the workspace reads: one row per (name, crate) pair, carrying scope, the layer the read happens at, how the name reaches the code, and the documented default. The table is data — the runtime never consults it. It exists so crates/vike-ops/tests/settings_registry.rs can gate the source tree and the table against each other both ways: an undeclared env::var fails CI, and so does a stale row.

Layer encodes the rule the registry exists for — libraries take configuration as parameters; only binaries read the process environment. Binary and Injected (a pure parser over a caller-supplied map) are the correct shapes; Library, a direct env::var under src/ outside a binary, is the work list. That list is a ratchet: LIBRARY_PIN holds it as a fixed-size array, so it may shrink but never grow. It had to be — the count went from 60 on 2026-07-29 to 77 a week later, across five changes that each had no reason to notice.

Finding out what a box is actually reading

vike-cli config show --section env prints the registry resolved against this machine, with --filter (a substring of the name or the reading crate), --changed-only and --json. The store precedence is process env, then the credential store, then the documented default, and presence wins rather than non-emptiness: an exported NAME= beats the store with an empty string, reported as such.

That order is what the stores support, not a promise any reader honours

Most consumers read exactly one store, so a source word alone would assert a provenance the tool cannot verify. Every row therefore also prints what its reader does: env for a direct env::var, caller-map for a map the caller supplies, unknown for a computed name. A value found only in the credential store while its reader calls env::var is warned about under the table.

Redaction happens on construction, inside the resolver rather than in either printer, so --json cannot leak what the table hides. One disclosure is stated rather than hidden: the registry declares the whole per-venue, per-tier API-key grid, so the table names those keys and marks each set or unset — pasted output shows which venues a box holds keys for, never a value.

Three worth knowing before you need them

VIKE_SETTINGS_DIR names the settings directory outright, honoured before any filesystem probe and skipping the project walk entirely. A blank value is ignored rather than honoured: an empty Environment=VIKE_SETTINGS_DIR= line would otherwise resolve settings to the working directory.

RUST_LOG (aliased VIKE_LOG) filters the console only. The file layer defaults to trace and captures the log-to-tracing bridge, so a batch tool driving a chatty dependency writes a JSON file no console setting can turn down: one hour of a backfill measured 6.4 GB, and a long range once wrote 341 GB and nearly filled the disk hosting a live trading node. VIKE_LOG_FILE_LEVEL=warn (or off) is the switch — see log volume. VIKE_LOG_DIR tops the log-directory precedence, above a config file's log_dir and the project's own settings/state/logs. The gates behind all of this are on settings gates.

On this page