refactor: split scoped secrets and narrow SOPS recipients #122

Merged
nimmo merged 7 commits from feat/split-scoped-secrets into main 2026-07-29 22:18:22 +01:00
Owner

Refs #80
Refs #39

Summary

  • remove the monolithic secrets/secrets.yaml file
  • keep service and host secrets in scoped encrypted files
  • add explicit SOPS creation rules for all migrated files
  • remove temporary Electra access where it is not an actual consumer
  • give new external Nebula nodes an admin-only fallback
  • make secret rotation process only tracked files
  • document recipient rotation, recovery, and explicit scoped editing in the wiki

Validation

  • nix fmt -- --ci
  • nix flake check
  • verified recipient metadata for all affected files

Live deployment evidence is intentionally still outstanding, so this PR does not close the issues automatically.

Refs #80 Refs #39 ## Summary - remove the monolithic secrets/secrets.yaml file - keep service and host secrets in scoped encrypted files - add explicit SOPS creation rules for all migrated files - remove temporary Electra access where it is not an actual consumer - give new external Nebula nodes an admin-only fallback - make secret rotation process only tracked files - document recipient rotation, recovery, and explicit scoped editing in the wiki ## Validation - nix fmt -- --ci - nix flake check - verified recipient metadata for all affected files Live deployment evidence is intentionally still outstanding, so this PR does not close the issues automatically.
refactor: narrow scoped secret recipients
All checks were successful
Build and Push Attic Cache / test (pull_request) Successful in 41s
Build and Push Attic Cache / build (pull_request) Has been skipped
AI pull-request review / review (pull_request) Successful in 6m37s
875ac08927
Author
Owner

Automated code review

Reviewed commit: 9c02457316a4a1291b7ac536fc7ae28b1b9d5367

Verdict: Ready to merge

No blocking or important findings were retained, and deterministic checks passed. Suggestions remain advisory.

Overall assessment

Refactors monolithic SOPS secrets into scoped files with narrowed recipient rules, updates Nix modules and Just recipes accordingly, and introduces validation for Nebula secret injection. The change improves secret isolation but leaves a broad catch-all rule in .sops.yaml and removes default arguments from secret editing recipes without input guards.

Blocking findings

None.

Important findings

None.

Suggestions

  • Catch-all SOPS creation rule remains overly broad (.sops.yaml; high confidence)

    • path_regex: secrets/.*.yaml$
      key_groups:
      • age:
        Impact: Any new secret file not explicitly covered by the preceding rules will inherit broad access to all hosts, undermining the scoping policy.
        Suggested fix: Restrict the catch-all rule to only include admin, YubiKey, and provision-key recipients. This forces explicit creation rules for future files and enforces the principle of least privilege.
  • edit-secrets recipe lacks input validation (justfiles/secrets.just:321; high confidence)
    edit-secrets NAME:
    #!/usr/bin/env bash
    set -euo pipefail
    AGE_KEY=$(sudo ssh-to-age -private-key -i /etc/ssh/ssh_host_ed25519_key)
    sops secrets/{{ NAME }}.yaml
    Impact: Running just edit-secrets without an argument will execute sops secrets/.yaml, which may fail or create an unintended empty file.
    Suggested fix: Add a guard at the start of the recipe: [[ -z "${NAME:-}" ]] && { echo "Error: NAME argument required"; exit 1; }.

  • Secret rotation relies on staged Git files only (justfiles/secrets.just:100; medium confidence)
    done < <(git ls-files 'secrets/.yaml' 'secrets/**/.yaml' | sort)
    Impact: Newly created secret files that have not been staged will be skipped during key rotation, leaving them undecryptable by newly registered hosts.
    Suggested fix: Update documentation to explicitly require staging before running rotation recipes. Alternatively, consider using find secrets/ -name '*.yaml' if processing untracked files is desired, though tracked-only aligns with the stated PR goal.

Tests and validation

  • No configured deterministic checks.

Questions

  • Are there any existing scoped secret files (e.g., secrets/wifi.yaml, secrets/newt.yaml) that were split outside this diff but are already referenced in .sops.yaml and Nix modules?
  • Is yq expected to be available in all CI runners and developer environments where nebula.just recipes are executed?

Review limitations

  • Review is based on provided diff and documentation; live deployment validation was explicitly noted as outstanding.
  • SOPS rule evaluation order was verified conceptually, but actual decryption behavior depends on runtime SOPS version and key availability.
  • Nix module path updates were validated against the diff, but full flake evaluation results were not reproduced.

Diff coverage

  • .sops.yaml: reviewed — included in a context-limited batch
  • README.md: reviewed — included in a context-limited batch
  • hosts/lyra/default.nix: reviewed — included in a context-limited batch
  • hosts/vega/default.nix: reviewed — included in a context-limited batch
  • justfiles/nebula.just: reviewed — included in a context-limited batch
  • justfiles/secrets.just: reviewed — included in a context-limited batch
  • modules/common/default-config.nix: reviewed — included in a context-limited batch
  • modules/networking/nebula.nix: reviewed — included in a context-limited batch
  • modules/networking/wifi-networks.nix: reviewed — included in a context-limited batch
  • modules/networking/wireguard-vpn.nix: reviewed — included in a context-limited batch
  • modules/profiles/ai-agents.nix: reviewed — included in a context-limited batch
  • modules/profiles/ai-runtime.nix: reviewed — included in a context-limited batch
  • modules/services/backrest.nix: reviewed — included in a context-limited batch
  • modules/services/beszel-agent.nix: reviewed — included in a context-limited batch
  • modules/services/docker-report.nix: reviewed — included in a context-limited batch
  • modules/services/hermes.nix: reviewed — included in a context-limited batch
  • modules/services/nixos-auto-update.nix: reviewed — included in a context-limited batch
  • modules/services/service-failure-monitor.nix: reviewed — included in a context-limited batch
  • secrets/README.md: reviewed — included in a context-limited batch
  • secrets/ai-agents.yaml: reviewed — included in a context-limited batch
  • secrets/ai-runtime.yaml: reviewed — included in a context-limited batch
  • secrets/attic.yaml: reviewed — included in a context-limited batch
  • secrets/backrest.yaml: reviewed — included in a context-limited batch
  • secrets/beszel/cosmos.yaml: reviewed — included in a context-limited batch
  • secrets/beszel/electra.yaml: reviewed — included in a context-limited batch
  • secrets/beszel/lena.yaml: reviewed — included in a context-limited batch
  • secrets/beszel/lyra.yaml: reviewed — included in a context-limited batch
  • secrets/beszel/vega.yaml: reviewed — included in a context-limited batch
  • secrets/docker-report.yaml: reviewed — included in a context-limited batch
  • secrets/hermes.yaml: reviewed — included in a context-limited batch
Review metadata
  • Reviewer: forgejo-ai-review v1
  • Model: qwen3.6:35b-a3b-q8_0
  • Guidance loaded: .forgejo/ai-review.md, .forgejo/ai-review.yml, AGENTS.md, README.md
  • Commits considered: 7
  • Previous automated review: updated
  • Findings: 3
<!-- forgejo-ai-review:v1 --> ## Automated code review Reviewed commit: `9c02457316a4a1291b7ac536fc7ae28b1b9d5367` ## Verdict: Ready to merge No blocking or important findings were retained, and deterministic checks passed. Suggestions remain advisory. ### Overall assessment Refactors monolithic SOPS secrets into scoped files with narrowed recipient rules, updates Nix modules and Just recipes accordingly, and introduces validation for Nebula secret injection. The change improves secret isolation but leaves a broad catch-all rule in .sops.yaml and removes default arguments from secret editing recipes without input guards. ### Blocking findings None. ### Important findings None. ### Suggestions - **Catch-all SOPS creation rule remains overly broad** (.sops.yaml; high confidence) - path_regex: secrets/.*\.yaml$ key_groups: - age: Impact: Any new secret file not explicitly covered by the preceding rules will inherit broad access to all hosts, undermining the scoping policy. Suggested fix: Restrict the catch-all rule to only include admin, YubiKey, and provision-key recipients. This forces explicit creation rules for future files and enforces the principle of least privilege. - **edit-secrets recipe lacks input validation** (justfiles/secrets.just:321; high confidence) edit-secrets NAME: #!/usr/bin/env bash set -euo pipefail AGE_KEY=$(sudo ssh-to-age -private-key -i /etc/ssh/ssh_host_ed25519_key) sops secrets/{{ NAME }}.yaml Impact: Running `just edit-secrets` without an argument will execute `sops secrets/.yaml`, which may fail or create an unintended empty file. Suggested fix: Add a guard at the start of the recipe: `[[ -z "${NAME:-}" ]] && { echo "Error: NAME argument required"; exit 1; }`. - **Secret rotation relies on staged Git files only** (justfiles/secrets.just:100; medium confidence) done < <(git ls-files 'secrets/*.yaml' 'secrets/**/*.yaml' | sort) Impact: Newly created secret files that have not been staged will be skipped during key rotation, leaving them undecryptable by newly registered hosts. Suggested fix: Update documentation to explicitly require staging before running rotation recipes. Alternatively, consider using `find secrets/ -name '*.yaml'` if processing untracked files is desired, though tracked-only aligns with the stated PR goal. ### Tests and validation - No configured deterministic checks. ### Questions - Are there any existing scoped secret files (e.g., secrets/wifi.yaml, secrets/newt.yaml) that were split outside this diff but are already referenced in .sops.yaml and Nix modules? - Is yq expected to be available in all CI runners and developer environments where nebula.just recipes are executed? ### Review limitations - Review is based on provided diff and documentation; live deployment validation was explicitly noted as outstanding. - SOPS rule evaluation order was verified conceptually, but actual decryption behavior depends on runtime SOPS version and key availability. - Nix module path updates were validated against the diff, but full flake evaluation results were not reproduced. ### Diff coverage - `.sops.yaml`: **reviewed** — included in a context-limited batch - `README.md`: **reviewed** — included in a context-limited batch - `hosts/lyra/default.nix`: **reviewed** — included in a context-limited batch - `hosts/vega/default.nix`: **reviewed** — included in a context-limited batch - `justfiles/nebula.just`: **reviewed** — included in a context-limited batch - `justfiles/secrets.just`: **reviewed** — included in a context-limited batch - `modules/common/default-config.nix`: **reviewed** — included in a context-limited batch - `modules/networking/nebula.nix`: **reviewed** — included in a context-limited batch - `modules/networking/wifi-networks.nix`: **reviewed** — included in a context-limited batch - `modules/networking/wireguard-vpn.nix`: **reviewed** — included in a context-limited batch - `modules/profiles/ai-agents.nix`: **reviewed** — included in a context-limited batch - `modules/profiles/ai-runtime.nix`: **reviewed** — included in a context-limited batch - `modules/services/backrest.nix`: **reviewed** — included in a context-limited batch - `modules/services/beszel-agent.nix`: **reviewed** — included in a context-limited batch - `modules/services/docker-report.nix`: **reviewed** — included in a context-limited batch - `modules/services/hermes.nix`: **reviewed** — included in a context-limited batch - `modules/services/nixos-auto-update.nix`: **reviewed** — included in a context-limited batch - `modules/services/service-failure-monitor.nix`: **reviewed** — included in a context-limited batch - `secrets/README.md`: **reviewed** — included in a context-limited batch - `secrets/ai-agents.yaml`: **reviewed** — included in a context-limited batch - `secrets/ai-runtime.yaml`: **reviewed** — included in a context-limited batch - `secrets/attic.yaml`: **reviewed** — included in a context-limited batch - `secrets/backrest.yaml`: **reviewed** — included in a context-limited batch - `secrets/beszel/cosmos.yaml`: **reviewed** — included in a context-limited batch - `secrets/beszel/electra.yaml`: **reviewed** — included in a context-limited batch - `secrets/beszel/lena.yaml`: **reviewed** — included in a context-limited batch - `secrets/beszel/lyra.yaml`: **reviewed** — included in a context-limited batch - `secrets/beszel/vega.yaml`: **reviewed** — included in a context-limited batch - `secrets/docker-report.yaml`: **reviewed** — included in a context-limited batch - `secrets/hermes.yaml`: **reviewed** — included in a context-limited batch <details><summary>Review metadata</summary> - Reviewer: forgejo-ai-review v1 - Model: qwen3.6:35b-a3b-q8_0 - Guidance loaded: .forgejo/ai-review.md, .forgejo/ai-review.yml, AGENTS.md, README.md - Commits considered: 7 - Previous automated review: updated - Findings: 3 </details>
hardening: make scoped secret workflows safer
All checks were successful
Build and Push Attic Cache / test (pull_request) Successful in 39s
Build and Push Attic Cache / build (pull_request) Has been skipped
AI pull-request review / review (pull_request) Successful in 8m42s
f39d1d1cb2
hardening: validate Nebula secret files
Some checks failed
Build and Push Attic Cache / test (pull_request) Successful in 40s
Build and Push Attic Cache / build (pull_request) Has been skipped
AI pull-request review / review (pull_request) Has been cancelled
19c5f0b967
chore: remove retired Mem0 secret
All checks were successful
Build and Push Attic Cache / test (pull_request) Successful in 39s
Build and Push Attic Cache / build (pull_request) Has been skipped
AI pull-request review / review (pull_request) Successful in 7m44s
9c02457316
nimmo merged commit c1bb2c3eef into main 2026-07-29 22:18:22 +01:00
nimmo referenced this pull request from a commit 2026-07-29 22:18:23 +01:00
Sign in to join this conversation.
No reviewers
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
nimmo/nixos-config!122
No description provided.