Skip to content

Secret Lifecycle Management Story #89

@sini

Description

@sini

I’d like to start a discussion about encrypted secret lifecycle management with nixidy, and explore whether there’s a path toward a more native or upstreamable solution.

After reviewing public nixidy repositories, the dominant pattern appears to be external-secrets with backends like Vault or Bitwarden. While effective, that approach moves the source of truth outside of Nix.

My goal is to keep encrypted secrets (e.g., via sops/agenix) as the canonical source of truth within the Nix workflow.

Kubenix documents an approach using helm/vals as a preprocessing step for secrets. However, as far as I can tell, this pattern is not currently viable with argocd as-is. My recent work is largely about making a similar model viable in a nixidy-based workflow while preserving encrypted output.

My Current Approach

I’m currently using isindir/sops-secrets-operator and wrote a preprocessing utility that:

  1. Builds all nixidyEnvs derivations for the current flake.

  2. Diffs generated output against {nixidyEnv}.target.rootPath.

  3. Transforms Secret resources into SopsSecret resources.

  4. Pipes them through:

    • vals eval
    • sops -e
    • YAML re-serialization

Only encrypted manifests are written to disk.

This effectively makes a vals-style secret reference workflow usable with nixidy while preserving encrypted resources as the source of truth.

However:

  • It bypasses the nixidy CLI and generated apply scripts.
  • It relies on system key material (PGP/age), so it cannot run inside a pure derivation.
  • Bootstrapping still requires out-of-band provisioning (e.g., agenix-rekey + systemd oneshot to create the initial decryption secret).

Functionally it works well, but architecturally it feels like I’m layering a transformation phase around nixidy rather than integrating with it.

Related Work

I found a somewhat similar pattern in duck1123/k3s-fleetops, which exposes decrypted inputs via environment variables during build, though it appears secrets may still enter derivation inputs.

I’ve also seen SOPS-encrypted YAML defined directly in nix configs, but that approach feels much harder to maintain and rotate long-term.

What I’m Looking For

I’d appreciate guidance on:

  • Is encrypted secret transformation intentionally out of scope for nixidy?
  • Would a formal “post-render transformation” phase or extension hook align with nixidy’s design?
  • Is there a viable path to upstreaming something like this (potentially backend-agnostic: SopsSecret, SealedSecrets, etc.)?

I’m willing to invest time in turning my utility into a more general and polished solution if there’s architectural alignment.

Additionally, I don’t yet have a clean pattern for handling obfuscated-but-not-secret values (e.g., rendered hostnames). If there’s guidance there, I’d be interested.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions