Configuration Reference
Complete reference for the fnox.toml configuration file.
File Location
fnox looks for configuration files in this order:
- Path specified via
-c, --configflag fnox.tomlin current directoryfnox.tomlin parent directories (hierarchical search)fnox.local.tomlalongside eachfnox.toml(for local overrides)
Basic Structure
# Top-level settings
if_missing = "warn" # Global default for missing secrets
imports = ["./shared/secrets.toml"] # Import other configs
# Provider definitions
[providers]
PROVIDER_NAME = { type = "PROVIDER_TYPE" } # ... provider-specific config ...
# Secret definitions
[secrets]
SECRET_NAME = { provider = "PROVIDER_NAME", value = "...", default = "...", if_missing = "error", description = "..." }
# Profile definitions
[profiles.PROFILE_NAME]
# ... same structure as top-level ...Top-Level Settings
if_missing
Global default behavior when secrets cannot be resolved.
if_missing = "error" # or "warn", "ignore"Values:
"error"- Fail if secret is missing"warn"- Print warning and continue (default)"ignore"- Silently skip missing secrets
Priority: Lowest (overridden by secret-level, env vars, CLI flags).
imports
List of config files to import.
imports = ["./shared/base.toml", "./envs/dev.toml"]Usage:
- Paths relative to current config file
- Imported files merged into current config
- Later imports override earlier ones
Provider Configuration
[providers.PROVIDER_NAME]
type = "PROVIDER_TYPE"
# ... provider-specific fields ...Common Provider Types
Age Encryption
[providers.age]
type = "age"
recipients = [
"age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p",
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGQs..."
]AWS Secrets Manager
[providers]
aws = { type = "aws-sm", region = "us-east-1", prefix = "myapp/" } # prefix is optionalAWS KMS
[providers]
kms = { type = "aws-kms", key_id = "arn:aws:kms:us-east-1:123456789012:key/...", region = "us-east-1" }Azure Key Vault Secrets
[providers]
azure = { type = "azure-sm", vault_url = "https://myapp-vault.vault.azure.net/", prefix = "myapp/" } # prefix is optionalAzure Key Vault Keys
[providers]
azurekms = { type = "azure-kms", vault_url = "https://myapp-vault.vault.azure.net/", key_name = "encryption-key" }GCP Secret Manager
[providers]
gcp = { type = "gcp-sm", project = "my-project-id", prefix = "myapp/" } # prefix is optionalGCP Cloud KMS
[providers.gcpkms]
type = "gcp-kms"
project = "my-project-id"
location = "us-central1"
keyring = "fnox-keyring"
key = "fnox-key"1Password
[providers]
onepass = { type = "1password", vault = "Development", account = "my.1password.com" } # account is optionalBitwarden
[providers]
bitwarden = { type = "bitwarden", collection = "collection-id", organization_id = "org-id" } # both optionalHashiCorp Vault
[providers]
vault = { type = "vault", address = "https://vault.example.com:8200", path = "secret/myapp", token = "hvs.CAESIJ..." } # token optional, can use VAULT_TOKEN env varOS Keychain
[providers]
keychain = { type = "keychain", service = "fnox", prefix = "myapp/" } # prefix is optionalSecret Configuration
[secrets]
SECRET_NAME = { provider = "PROVIDER_NAME", value = "...", default = "...", if_missing = "error", description = "..." }Fields
provider
Provider to use for this secret.
[secrets]
DATABASE_URL = { provider = "age", value = "encrypted..." }Required: Unless using only default (plain text).
value
Provider-specific value:
- Encryption providers (age, aws-kms, etc.): Encrypted ciphertext
- Remote providers (aws-sm, 1password, etc.): Secret name/reference
[secrets]
# Encrypted ciphertext (age)
DATABASE_URL = { provider = "age", value = "YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNjcnlwdC..." }
# Remote reference (AWS)
DATABASE_URL = { provider = "aws", value = "database-url" } # Secret name in AWS Secrets Managerdefault
Fallback value if secret cannot be resolved.
[secrets]
DATABASE_URL = { provider = "age", value = "encrypted...", default = "postgresql://localhost/dev" } # Fallback for local devUse for:
- Non-sensitive defaults
- Local development fallbacks
- Optional configuration
if_missing
Behavior when secret cannot be resolved.
[secrets]
DATABASE_URL = { provider = "aws", value = "database-url", if_missing = "error" } # Fail if missing (critical secret)
ANALYTICS_KEY = { provider = "aws", value = "analytics-key", if_missing = "ignore" } # Silently skip if missing (optional)Values: "error", "warn", "ignore"
Priority: Overrides top-level if_missing, but overridden by env vars and CLI flags.
description
Human-readable description.
[secrets]
DATABASE_URL = { provider = "age", value = "encrypted...", description = "Production database connection string" }Profile Configuration
Profiles allow environment-specific configuration:
# Default profile (no prefix)
[secrets]
DATABASE_URL = { provider = "age", value = "encrypted-dev..." }
# Production profile
[profiles.production]
[profiles.production.providers]
aws = { type = "aws-sm", region = "us-east-1" }
[profiles.production.secrets]
DATABASE_URL = { provider = "aws", value = "database-url" }Profile Structure
[profiles.PROFILE_NAME]
if_missing = "error" # Profile-specific default
[profiles.PROFILE_NAME.providers]
PROVIDER_NAME = { type = "PROVIDER_TYPE" } # ... provider config ...
[profiles.PROFILE_NAME.secrets]
SECRET_NAME = { provider = "PROVIDER_NAME", value = "..." } # ... secret config ...Profile Inheritance
Profiles inherit top-level secrets and providers:
# Top-level (inherited by all profiles)
[secrets]
LOG_LEVEL = { default = "info" }
DATABASE_URL = { provider = "age", value = "encrypted-dev..." }
# Production profile
[profiles.production.secrets]
DATABASE_URL = { provider = "aws", value = "prod-db" } # Overrides top-level DATABASE_URL
# Inherits LOG_LEVEL="info" from top-levelComplete Example
# Global settings
if_missing = "warn"
imports = ["./shared/common.toml"]
# Providers
[providers]
age = { type = "age", recipients = ["age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p"] }
aws = { type = "aws-sm", region = "us-east-1", prefix = "myapp/" }
# Default profile secrets
[secrets]
DATABASE_URL = { provider = "age", value = "YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNjcnlwdC...", default = "postgresql://localhost/dev", description = "Database connection string" }
JWT_SECRET = { provider = "age", value = "encrypted...", if_missing = "error" }
LOG_LEVEL = { default = "info" }
# Production profile
[profiles.production]
if_missing = "error"
[profiles.production.providers]
aws = { type = "aws-sm", region = "us-east-1", prefix = "myapp-prod/" }
[profiles.production.secrets]
DATABASE_URL = { provider = "aws", value = "database-url", description = "Production database" }
JWT_SECRET = { provider = "aws", value = "jwt-secret" }
# Inherits LOG_LEVEL from top-levelLocal Overrides
Create fnox.local.toml alongside fnox.toml for local overrides:
# fnox.local.toml (gitignored)
[secrets]
DATABASE_URL = { default = "postgresql://localhost/mylocal" } # Override for local development
DEBUG_MODE = { default = "true" }Important: Add to .gitignore:
fnox.local.tomlProfile-Specific Config Files
You can create environment-specific config files that load based on the FNOX_PROFILE environment variable:
# Directory structure
project/
├── fnox.toml # Base config
├── fnox.production.toml # Production overrides
├── fnox.staging.toml # Staging overrides
├── fnox.development.toml # Development overrides
└── fnox.local.toml # Local overrides (gitignored)Example usage:
# Use default config (fnox.toml only)
fnox exec -- npm start
# Use production config (fnox.toml + fnox.production.toml)
FNOX_PROFILE=production fnox exec -- ./deploy.sh
# Use staging config (fnox.toml + fnox.staging.toml)
FNOX_PROFILE=staging fnox exec -- ./deploy.shKey differences:
fnox.$FNOX_PROFILE.tomlfiles are committed to git (environment-specific, but shared with team)fnox.local.tomlis gitignored (machine-specific, personal overrides)- Profile-specific files work with the default profile's secrets, not
[profiles.xxx]sections fnox.default.tomlis not loaded (usefnox.tomlinstead)
Hierarchical Configuration
fnox searches parent directories for fnox.toml files:
project/
├── fnox.toml # Root config
└── services/
└── api/
└── fnox.toml # API config (inherits from root)Merge order (lowest to highest priority):
- Root
fnox.toml - Root
fnox.$FNOX_PROFILE.toml(ifFNOX_PROFILEis set and not "default") - Root
fnox.local.toml - Child
fnox.toml - Child
fnox.$FNOX_PROFILE.toml(ifFNOX_PROFILEis set and not "default") - Child
fnox.local.toml
Next Steps
- CLI Reference - All available commands
- Environment Variables - Environment variable reference
- Providers Overview - Available providers