Secrets #
Cattery uses SOPS for file-level secrets. You keep
control of recipients and identities; Cattery keeps encrypted files in the
repository and writes plaintext only to its intended target under $HOME.
Before you begin #
Install sops and your chosen key backend, such as age, and make them
available on PATH. Define recipients in .sops.yaml at the repository root.
creation_rules:
- path_regex: .*
age: age1replace-with-your-public-recipient
Keep private identities outside the repository. Make sure more than one trusted recovery path can decrypt important secrets; Cattery cannot recover a lost identity for you.
If you install Cattery through its Nix package, the packaged command includes
sops and age on its runtime path. Other installations use the tools from
your shell’s PATH.
Add a secret #
Adopt an existing file as an encrypted source:
cattery add --secret ~/.config/example/token
The source is stored below _secrets/ while keeping its target path:
repo/app/_secrets/.config/example/token -> ~/.config/example/token
For a platform-specific secret, put _secrets/ inside _darwin/ or _linux/:
repo/app/_darwin/_secrets/.config/example/token
Use --group or --platform with add when you need to choose where the
source belongs. Run cattery status and cattery apply as usual afterward.
To deploy ordinary files while leaving every secret target and secret baseline untouched, run:
cattery apply --skip-secrets
The flag also prevents secret decryption and SOPS dependency checks. Group selection still applies normally to the remaining ordinary files and aliases.
cattery add --secret is the adoption workflow. The lifecycle commands below
inventory, verify, or rotate sources that are already managed; they do not
create, edit, or delete plaintext secrets.
Inventory and verification #
List every managed encrypted source across base, Linux, and macOS layers:
cattery secrets list
cattery secrets verify
Both commands accept group arguments and repeatable exact source selectors. Selectors are combined as a union:
cattery secrets verify work --source _secrets/.config/example/root-token
list reads repository metadata only and does not invoke SOPS. verify
decrypts each selected source in memory, reports only verified or failed,
continues after independent failures, and never reads the corresponding file
under $HOME.
Rotate recipients or creation rules #
SOPS and .sops.yaml remain the authority for recipients. A practical
rotation is:
- Edit the repository's
.sops.yamlcreation rules or recipients. - Run
cattery secrets verifyto confirm the existing identities work. - Preview with
cattery secrets reencrypt(or explicitly add--dry-run). - Apply with
cattery secrets reencrypt --yes. - Review and commit the encrypted repository changes.
Re-encryption decrypts the source in memory, encrypts the same bytes using the repository-relative source path as SOPS's filename override, then decrypts the new ciphertext and compares it with the original plaintext before publishing. Publication preserves the source mode and uses Cattery's atomic replacement path. Each source is processed independently, so a failure does not prevent other selected sources from being checked or rotated.
The command never synchronizes or inspects $HOME, runs hooks, or writes
plaintext state. A successful replacement refreshes only a matching active
baseline's raw encrypted-source fingerprint; inactive platform sources and
secrets without a baseline do not change state.
What Cattery protects #
- Encrypted source files stay encrypted in the repository.
- Secret plaintext is not printed by
status,diff, or interactive prompts. - Plaintext is not stored in Cattery’s state database, logs, command arguments, errors, or a general temporary directory.
- Secret targets are always mode
0600, or0700when executable.
Cattery treats a secret as bytes, not as YAML, JSON, or an environment file. Re-encrypting a file without changing its plaintext does not create a content conflict.
Plaintext necessarily exists briefly in memory while Cattery encrypts, decrypts, compares, or writes it. Cattery minimizes that exposure, but no Go program can promise that every memory copy is erased.
Backup and recovery #
Back up both your SOPS identities and Cattery’s local state directory. The state directory includes a local key used to recognize unchanged secret plaintext across applies. If that key no longer matches existing secret state, Cattery stops safely rather than guessing.
If sops is missing when an operation needs it, Cattery exits with code 4
without changing the repository, target, or state.
See repository layout for placement and reconciliation for apply behavior.