How TOML Configuration Is Loaded at Server Startup Using Environment Variables in Switchyard
Switchyard loads TOML configuration by reading a filesystem path, deserializing it into ServerConfig, then resolving *_env fields by looking up the named environment variables and injecting their values into the runtime server state.
This pattern lets operators store sensitive credentials like API keys outside of version-controlled configuration files. The implementation lives primarily in the Rust server crate, with Python CLI helpers passing the configuration path through environment variables.
Overview of the Configuration Loading Flow
The Switchyard server follows a four-stage initialization process when it boots:
- Path resolution – The server obtains a TOML file path, typically from the
SWITCHYARD_CONFIGenvironment variable - File reading – Raw bytes are read from disk using standard Rust filesystem APIs
- TOML deserialization –
toml::from_strparses the file into theServerConfigstruct - Environment variable injection – Fields ending in
_envtrigger lookups viastd::env::var, with results merged into the final configuration
This architecture separates structural configuration (routes, limits, timeouts) from secret material (API keys, authentication tokens), addressing a common operational security requirement for LLM gateway deployments.
Key Source Files and Their Roles
| File | Purpose | Direct Source Link |
|---|---|---|
crates/switchyard-server/src/config.rs |
Core configuration types, TOML parsing, and *_env resolution logic |
config.rs on GitHub |
crates/switchyard-server/src/lib.rs |
Server initialization and load_server_state export |
lib.rs on GitHub |
switchyard/cli/launch_command.py |
Python CLI that sets SWITCHYARD_CONFIG and invokes the Rust binary |
launch_command.py on GitHub |
dev-server/config.toml |
Reference configuration demonstrating environment variable patterns | config.toml on GitHub |
Implementation Details in config.rs
The ServerConfig struct in crates/switchyard-server/src/config.rs defines the schema for TOML configuration. Critical to environment variable support are fields like api_key_env and base_url_env, which store the name of an environment variable rather than its value.
After deserialization completes, the configuration loader iterates over these *_env fields:
- Calls
std::env::var(env_var_name)for each configured variable name - Returns a descriptive error if the variable is unset or contains only whitespace
- Substitutes the retrieved value into the corresponding operational field (e.g.,
api_keyfor LLM client authentication)
This two-step process ensures that TOML files can be committed to repositories safely, while still permitting per-deployment customization of secrets and endpoint URLs.
Running the Server with Environment-Driven Configuration
Shell Example
# Point Switchyard to your TOML configuration file
export SWITCHYARD_CONFIG=/etc/switchyard/production.toml
# Provide secrets that the TOML file references by variable name
export OPENAI_API_KEY=sk-...
export ANTHROPIC_API_KEY=sk-ant-...
# Launch the server (CLI passes SWITCHYARD_CONFIG to the Rust binary)
switchyard launch
Minimal TOML Snippet with Environment References
[llm_clients.openai_gpt4]
base_url = "https://api.openai.com/v1"
api_key_env = "OPENAI_API_KEY" # Value pulled from environment at startup
[llm_clients.anthropic_claude]
base_url = "https://api.anthropic.com/v1/complete"
api_key_env = "ANTHROPIC_API_KEY"
Verifying Configuration Resolution Programmatically
For debugging or integration testing, you can inspect the resolved configuration from Python:
from switchyard_rust.server import load_server_state
import os
# Mimic the environment setup that the CLI performs
os.environ["SWITCHYARD_CONFIG"] = "dev-server/config.toml"
os.environ["OPENAI_API_KEY"] = "sk-test-key-12345"
# Load and validate the full server state
state = load_server_state(os.getenv("SWITCHYARD_CONFIG"))
# The API key has been resolved from the environment and is now populated
print(state.llm_clients["openai_gpt4"].api_key) # outputs: sk-test-key-12345
print(state.routes) # shows fully configured routing table
This pattern is particularly useful in test suites that need to verify configuration parsing without spawning a full HTTP server.
Error Handling for Missing Variables
The Switchyard implementation is strict about environment variable presence. If a TOML file declares api_key_env = "REQUIRED_SECRET" but REQUIRED_SECRET is unset at runtime, load_server_state fails fast with an error message identifying:
- The configuration file path
- The field requiring the variable
- The exact environment variable name that was not found
This fail-fast behavior prevents silent misconfigurations that would otherwise manifest as authentication failures downstream.
Summary
- TOML configuration in Switchyard is loaded via
load_server_stateincrates/switchyard-server/src/config.rs - Environment variables are referenced by name in
*_envfields and resolved after TOML parsing completes - Secrets stay out of files – only variable names are stored in TOML, with values injected at runtime from
std::env::var - CLI integration – The
switchyard launchcommand setsSWITCHYARD_CONFIGbefore invoking the Rust server binary - Strict validation – Missing environment variables produce immediate, descriptive errors rather than silent defaults
Frequently Asked Questions
What environment variable specifies the TOML configuration file path?
Switchyard uses SWITCHYARD_CONFIG as the conventional environment variable for the configuration file path. The Python launch command sets this automatically when you invoke switchyard launch, or you can set it manually to override the default location.
Can I use environment variables for values other than API keys?
Yes. The *_env pattern applies to multiple configuration fields. In addition to api_key_env, the Switchyard schema supports base_url_env and potentially other environment-referenced fields defined in ServerConfig. Any value that varies across deployments—endpoints, timeout values, feature flags—can be externalized using this mechanism.
What happens if an environment variable referenced in my TOML file is missing?
The server fails during startup with a clear error message. The load_server_state implementation validates that every *_env field resolves to a non-empty string, returning an error that identifies the missing variable by name. This prevents the server from starting in a partially configured state.
Is there a way to inspect the resolved configuration without starting the HTTP server?
Yes. Import load_server_state from switchyard_rust.server in Python, set your environment variables and SWITCHYARD_CONFIG path, then call the function directly. This returns a populated ServerState object containing all resolved values without binding to any network ports.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →