How It Works
fnox uses a simple TOML config file (fnox.toml) that you check into git.
Two Storage Modes
Secrets can be stored in two ways:
1. Encrypted Inline
The encrypted ciphertext lives directly in the config file:
toml
[providers.age]
type = "age"
recipients = ["age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p"]
[secrets.DATABASE_URL]
provider = "age"
value = "YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNjcnlwdC4uLg==" # ← encrypted, safe to commitProviders: age, aws-kms, azure-kms, gcp-kms
Pros:
- Secrets live in git (version control, code review)
- Works offline
- Fast (no network calls)
Cons:
- Key rotation requires re-encrypting all secrets
- No centralized access control
2. Remote References
The config contains only a reference to a secret stored remotely:
toml
[providers.aws]
type = "aws-sm"
region = "us-east-1"
prefix = "myapp/"
[secrets.DATABASE_URL]
provider = "aws"
value = "database-url" # ← Just a reference, actual secret in AWSProviders: aws-sm, azure-sm, gcp-sm, vault, 1password, bitwarden, keychain
Pros:
- Centralized secret management
- Audit logs
- Access control
- Easy rotation
Cons:
- Requires network access
- Costs money (for cloud providers)
- Slower (network latency)
Secret Resolution Order
When fnox resolves a secret, it checks in this order:
- Encrypted value (
provider = "age",value = "encrypted...") - Provider reference (
provider = "aws",value = "secret-name") - Environment variable (if already set in shell)
- Default value (
default = "fallback")
First match wins!
Example Config
toml
# Provider definitions
[providers.age]
type = "age"
recipients = ["age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p"]
[providers.aws]
type = "aws-sm"
region = "us-east-1"
# Encrypted secret (in git)
[secrets.JWT_SECRET]
provider = "age"
value = "YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNjcnlwdC4uLg=="
# Remote secret (in AWS)
[secrets.DATABASE_URL]
provider = "aws"
value = "prod-database-url"
# Default value (fallback)
[secrets.NODE_ENV]
default = "development"Execution Flow
When you run fnox exec -- <command>:
- fnox reads
fnox.tomlfrom current directory (or parent directories) - Resolves all secrets based on the active profile
- Decrypts encrypted secrets or fetches remote secrets
- Exports all secrets as environment variables
- Executes your command with those env vars
Security Model
- Encrypted secrets: Private key required for decryption (via
FNOX_AGE_KEYorFNOX_AGE_KEY_FILE) - Remote secrets: Authentication via provider (AWS credentials, 1Password token, etc.)
- Never logged: Secrets are never written to logs or stdout (except
fnox getoutput) - CI-safe: Use
if_missing = "warn"to handle missing secrets in CI environments
Next Steps
- Profiles - Manage multiple environments
- Providers - Choose the right provider for your needs
- Shell Integration - Auto-load secrets in your shell