Overview
SBproxy has three systems for keeping values out of your config file: environment variable interpolation (${VAR} anywhere in the YAML), config variables (static values under a variables block, available to templates), and the secrets plane (values resolved from a secrets backend at config load, referenced by logical name or provider URI). All three ship in the open-source binary.
Environment Variables in Config
Reference environment variables anywhere in the config with ${VAR_NAME}. They resolve at config load time, which is the simplest way to keep an API key out of the file:
origins:
"ai.example.com":
action:
type: ai_proxy
providers:
- name: openai
api_key: ${OPENAI_API_KEY}
An unset variable leaves the literal ${VAR_NAME} string in place rather than failing the load, so validate configs with sbproxy validate before shipping them.
A separate set of process-level variables controls the binary itself:
| Variable | Description |
|---|---|
SB_CONFIG_FILE | Path to the sb.yml config file (the path must be supplied; the binary does not auto-discover it) |
SB_LOG_LEVEL | Log level (debug, info, warn, error) |
SB_REQUEST_LOG_LEVEL | Request log level |
SB_LOG_FORMAT | Log output format |
SB_GRACE_TIME | Graceful shutdown timeout |
SB_WORKER_THREADS | Worker thread count |
Config Variables
The variables block on an origin defines static values available to templates under the {{ variables.name }} scope. Any JSON type works, including nested objects:
origins:
"api.example.com":
variables:
api_version: v2
base_url: https://api.example.com
feature_flags:
new_ui: true
action:
type: proxy
url: "{{ variables.base_url }}/{{ variables.api_version }}"
Secrets
The secrets plane is open source. The top-level proxy.secrets block picks a backend, maps logical names to backend paths, and controls rotation. Resolved secrets are available in templates as {{ secrets.name }}:
proxy:
secrets:
backend: hashicorp
hashicorp:
addr: https://vault.example.com:8200
mount: secret
map:
openai_key: secret/data/prod/openai_key
rotation:
grace_period_secs: 300
re_resolve_interval_secs: 60
fallback: cache
Backends: env (the default), local, and hashicorp. The fallback field says what happens when the backend is unreachable: serve the cached value, reject, or fall back to the environment.
Secret Reference URIs
Secret-bearing fields (provider API keys, auth tokens, signing keys) also accept provider-specific reference URIs directly. The scheme names the provider type, the authority names a configured backend instance, and the path is the backend's own:
| Scheme | Provider | Example |
|---|---|---|
vault:// | HashiCorp Vault KV | vault://primary/secret/data/openai-prod?key=api_key |
awssm:// | AWS Secrets Manager | awssm://primary/openai-keys?version=3&key=api_key |
gcpsm:// | GCP Secret Manager | gcpsm://primary/openai-api-key?version=latest |
k8ssecret:// | Kubernetes Secret | k8ssecret://primary/sbproxy-secrets/openai-key |
secretfile:// | Local YAML or JSON secret file | secretfile://local/openai-prod?key=api_key |
secret:// | Local static secret map | secret://local/openai-prod |
version= pins a secret version on backends that support versioning; key= extracts one field from a JSON payload. References resolve at boot, and a reference that cannot be resolved fails the load loudly instead of starting with a missing credential. All of these backends ship in the open-source binary.
Template Scopes
Templates use {{ scope.path }} syntax. Available scopes:
| Scope | Description | Example |
|---|---|---|
request | Current HTTP request | {{ request.headers.x_api_key }} |
variables | User-defined variables | {{ variables.api_version }} |
secrets | Loaded secrets | {{ secrets.api_token }} |
config | Config metadata | {{ config.hostname }} |
session | Session data | {{ session.auth.email }} |
env | Config identity fields | {{ env.workspace_id }} |
server | Server-level vars | {{ server.var_name }} |
See also
- Config reference for the full proxy.secrets field table.
- Authentication for where secret references plug into auth blocks.