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:

  1. 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.
  2. 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.
  3. 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:

FileIn Chezmoi SourceCommitted to Git?Purpose
config.tomlprivate_dot_config/fnox/config.tomlYes (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.