Fnox: Secret Management for Dotfiles & Workstations
Fnox is a lightweight CLI secret manager designed to handle local environment variables and secrets using age encryption. It pairs seamlessly with chezmoi for managing dotfiles without exposing credentials in plaintext repositories.
Why Fnox?
When managing dotfiles across multiple machines (Linux, WSL2, macOS, Windows), you frequently need access to API tokens, private keys, and environment variables. Storing these directly in dotfiles or shell startup scripts (.bashrc, .zshrc) risks accidental leaks to public Git remotes.
Fnox solves this by:
- Age-Encrypted Config Files: Configuration files (
config.toml) contain secrets encrypted with an age public key. These files are completely safe to commit to version control. - Local-Only Private Keys: Decryption relies on a local age private identity key that remains strictly on the host and is never committed to Git.
- In-Flight Secret Injection: Secrets can be injected directly into ephemeral processes (
fnox exec -- <cmd>) without writing secrets to persistent shell history or disk.
Directory & File Structure
In a chezmoi-managed dotfiles repository, the encrypted secret configuration is tracked while private keys remain ignored:
| File | In Chezmoi Source | Committed to Git? | Purpose |
|---|---|---|---|
config.toml | private_dot_config/fnox/config.toml | Yes (encrypted values) | Encrypted secret definitions |
| Private Key | (Ignored / untracked) | No (Strictly local-only) | Age private identity key for decryption |
Basic Workflow
1. Generating an Age Identity
Generate an age private key and obtain the recipient public key:
age-keygen
# Outputs:
# Public key: age1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
2. Initializing Configuration
Configure your config.toml with the recipient public key:
[encryption]
recipient = "age1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
[secrets]
OPENAI_API_KEY = "age-encrypted-data..."
GITHUB_TOKEN = "age-encrypted-data..."
3. Setting and Retrieving Secrets
Add or update a secret:
fnox set OPENAI_API_KEY "sk-..."
Retrieve a single secret:
fnox get OPENAI_API_KEY
Process Secret Injection (fnox exec)
The most secure way to use secrets is injecting them on-demand into child processes rather than exporting them into long-lived shell sessions:
# Injects secrets defined in config.toml into the environment of the command
fnox exec -- my-tool --option
# Target a specific environment configuration file
fnox exec -c ~/.config/fnox/homelab.toml -- ansible-playbook site.yml
Combining with Chezmoi
When configuring tools like coding agents, CLI tools, or shell templates:
- Keep the dotfile template clean and reference environment variables.
- Wrap application launches or session commands in
fnox exec:
# Example alias in .bashrc:
alias agent="fnox exec -c ~/.config/fnox/agent.toml -- agent-cli"
This ensures credentials remain encrypted at rest and are only decrypted into memory during the execution lifecycle.