| name | nix-sops-secrets |
| description | Secrets in NixOS flakes with sops-nix + age (+ age-plugin-yubikey) — .sops.yaml recipients and creation_rules, a centralized sops.secrets declaration module, and runtime consumption from /run/secrets. Apply when adding, editing or rotating an encrypted secret; when adding a recipient (new host key or YubiKey) or a new host that must decrypt; when a service or user can't read a secret (permission denied, file missing, empty env var); when wiring an API key or password into a NixOS service, home-manager tool or wrapper script; when configuring .sops.yaml, sops.defaultSopsFile or the age host key. Do NOT use for agenix or vault-based setups, for git-crypt, or for generic sops usage outside Nix. |
| user-invocable | true |
| license | MIT |
| compatibility | Designed for Claude Code, Codex or similar harness, and for NixOS flakes using Mic92/sops-nix with age encryption. |
| metadata | {"author":"aldoborrero","version":"1.0.0","openclaw":{"emoji":"🔐","homepage":"https://github.com/aldoborrero/cc-skills-nix","requires":{"bins":"[Truncated]"},"install":[]}} |
| allowed-tools | Read Edit Write Glob Grep Bash(nix:*) Bash(git:*) Bash(sops:*) Bash(ssh-to-age:*) Bash(age:*) Agent |
| paths | ["**/.sops.yaml","**/secrets/**","**/sops.nix"] |
sops-nix + age secrets
Model: secrets live encrypted in git (secrets/*.sops.yaml), .sops.yaml says who can decrypt, one NixOS module declares which keys become files, and consumers read /run/secrets/<key> at runtime — never at eval time. Requires inputs.sops-nix (with inputs.nixpkgs.follows = "nixpkgs") and its module in every host (via the flake's shared modules).
Defaults verified against sops-nix's module source: secrets materialize at /run/secrets/<name>, mode 0400, owned by root unless owner is set; the host decrypts with the age key derived from its ed25519 SSH host key (config.services.openssh.hostKeys) unless sops.age.keyFile is set.
.sops.yaml — recipients as anchors, one rule
keys:
- &framework age18lmn8r9...
- &yk-5 age1yubikey1qt3vym...
creation_rules:
- path_regex: secrets/[^/]+\.sops\.ya?ml$
key_groups:
- age:
- *framework
- *yk-5
Two kinds of recipients, both age: host keys (each machine that must decrypt at boot) and operator keys on YubiKey (each human who edits secrets). Anchors keep the recipient list writable once and referenced per rule. After ANY change to keys/creation_rules, run sops updatekeys secrets/*.sops.yaml — editing .sops.yaml alone re-encrypts nothing.
Declaration — one central module
# modules/nixos/sops.nix
{ config, ... }:
let
user = config.users.users.aldo.name; # derive, don't hardcode
in
{
sops.defaultSopsFile = ../../secrets/secrets.sops.yaml;
sops.secrets = {
"ai/pi/groq".owner = user; # nested YAML key "ai: pi: groq:"
# "db/password" = { }; # root-owned 0400 — for system services
};
}