4.0 KiB
4.0 KiB
description, applyTo
| description | applyTo |
|---|---|
| Use when working with SOPS in this repo: editing secrets, adding multiline values, changing recipients, or wiring sops-nix consumers. Captures repo conventions, safe commands, and validation habits. | .sops.yaml, keys/secrets.yaml, modules/hosts/**/secrets.yaml, modules/hosts/**/*.nix, modules/programs/sops.nix, modules/features/**/*.nix, modules/services/**/*.nix |
Using SOPS In This Repo
This repo treats SOPS files as the source of encrypted runtime material, and Nix code as the wiring that exposes those secrets to services. Keep those roles separate: edit secret values with SOPS, consume them through sops-nix paths, and keep recipient policy scoped to the machines or operators that actually need access.
Mental Model
- Secrets live in encrypted YAML files; Nix modules should refer to secret paths, not decrypted values.
- Host-only credentials belong in
modules/hosts/<host>/secrets.yaml. - Shared credentials belong in
keys/secrets.yamlonly when multiple hosts intentionally consume the same material. .sops.yamlcontrols who can decrypt each file; keep those recipient sets narrow and explicit.- Secret key names are an interface. Rename them only when every consumer changes in the same edit.
Editing Secrets
- Use SOPS tooling for all value changes:
sops <file>,edit-secrets, orsops set .... - Do not hand-edit
ENC[...]payloads. That bypasses SOPS and breaks the encrypted document's integrity metadata. - Keep plaintext out of tracked files. Temporary plaintext files are acceptable only as local working inputs and should be removed after use.
- Prefer
SOPS_EDITOR=nvim sops <file>for interactive edits when editor choice matters.
For large or generated values, avoid putting the secret directly in shell history:
sops set --value-file <secrets-file> '["parent"]["key"]' /path/to/plaintext-value
If using inline sops set, the value argument must be valid JSON.
Multiline Values
Use YAML literal blocks for private keys, certificates, provisioner keys, and other values where newlines matter:
janus:
ssh_user_ca_key: |-
-----BEGIN OPENSSH PRIVATE KEY-----
...
-----END OPENSSH PRIVATE KEY-----
- Use
|-when the final trailing newline should be stripped. - Use
|when the consuming program expects the final trailing newline. - Avoid folded style (
>) for keys and certs because it rewrites line breaks.
Wiring Secrets Into Nix
- Consume secrets through
config.sops.secrets."<key>".pathorconfig.sops.placeholderwhere templating requires it. - Do not read decrypted secret contents during Nix evaluation.
- Set
owner,group, andmodeexplicitly for non-root services. - Use
pathorsops.templateswhen a service needs a specific file layout instead of copying secret contents into the store or tracked files. - If moving a secret between shared and host-local files, update
sops.defaultSopsFile,mysops.hostSecretFile, and every affectedsops.secretsdeclaration together.
Recipient And Rotation Practices
- Add dedicated
.sops.yamlpath_regexrules for host-local files before broad fallback rules. - Keep broad fallback rules conservative; do not expand them to grant casual access to every YAML or JSON file.
- Run
sops updatekeys <file>after changing recipients so data is rewrapped for the new key set. - Rotate or migrate in order: update recipients, re-encrypt affected files, update consumers, then validate affected hosts.
Validation Habits
After SOPS or sops-nix changes, check the contract rather than only the syntax:
- The expected secrets file is still selected by
sops.defaultSopsFileormysops.hostSecretFile. .sops.yamlhas a specific rule for any host-localsecrets.yamltouched.- Secret names in YAML still match the
sops.secrets."<key>"declarations. - Services that need restart or reload behavior have
restartUnitsorreloadUnitsset. - Affected host evaluation/build catches missing secret keys before deployment.