Secrets¶
small-config is designed so that sensitive values (API keys, SSH public keys, tokens) are never written to disk — not to config.py, not to state files, not to rendered templates on disk beyond what's strictly necessary for the tool they're passed to.
How secrets work¶
Use sc.secret("name") in config.py to declare a secret reference:
from small_config import sc
ssh_pub_key = sc.secret("ssh_pub_key")
api_key = sc.secret("stripe_api_key")
This returns a SecretRef object — a lazy reference. The actual value is not read yet.
When the engine resolves vars before running a component, it calls SC_SECRET_<NAME_UPPER> from the environment:
sc.secret(...) call |
Environment variable read |
|---|---|
sc.secret("ssh_pub_key") |
SC_SECRET_SSH_PUB_KEY |
sc.secret("stripe_api_key") |
SC_SECRET_STRIPE_API_KEY |
sc.secret("db_password") |
SC_SECRET_DB_PASSWORD |
The rule: dots and lowercase letters become _ and uppercase.
Exporting secrets¶
Export secrets in your shell before running any sc command:
export SC_SECRET_SSH_PUB_KEY="$(cat ~/.ssh/id_ed25519.pub)"
export SC_SECRET_STRIPE_API_KEY="sk_live_..."
In CI (GitHub Actions example):
- name: Deploy
env:
SC_SECRET_STRIPE_API_KEY: ${{ secrets.STRIPE_API_KEY }}
run: uv run sc build --env production
Error if missing¶
If a required secret is not set, the engine raises a clear error before running any command:
Dry-run mode¶
In dry-run mode (--dry-run), secrets are not read from the environment. A safe placeholder string is substituted instead, so you can render templates and inspect planned commands without needing real secrets:
--secrets-in-plaintext¶
By default, even in verbose mode (-v), secret values are masked in logs. If you need to see the actual resolved value (e.g. to debug a template), pass --secrets-in-plaintext:
Warning
Never use --secrets-in-plaintext in CI logs that are stored or shared.
HttpTest and proxies¶
HttpTest uses trust_env=False by default, which means it ignores HTTP_PROXY, HTTPS_PROXY, and ALL_PROXY environment variables. This is intentional: smoke tests hit infrastructure IPs directly, and proxy variables (often set for secrets managers or corporate networks) frequently cause timeouts to raw public IPs while the same URL loads fine in a browser.
If you genuinely need the test to route through a proxy: