A sops-nix extension adding secret generation and automatic rekeying using a YubiKey or master-identity (heavily inspired by agenix-rekey)
  • Rust 65.8%
  • Nix 33.5%
  • Shell 0.7%
Find a file
2026-11-04 23:26:26 +01:00
cli feat: track staleness per secret 2026-11-04 13:56:57 +01:00
nix feat[module]: optional rekeying of all secrets by default 2026-11-04 23:26:26 +01:00
tests feat: make rekey opt-in 2026-11-04 22:58:00 +01:00
.gitignore feat: Initial commit 2026-10-14 19:12:37 +02:00
flake.lock feat: add flake 2026-11-03 19:47:15 +01:00
flake.nix feat[module]: optional rekeying of all secrets by default 2026-11-04 23:26:26 +01:00
LICENSE feat: Initial commit 2026-10-14 19:12:37 +02:00
README.md feat[module]: make pubFile configurable 2026-11-04 22:58:04 +01:00

sops-rekey

If you ever wished you had just gone with agenix instead of sops-nix in order to be able to use agenix-rekey, then fret no more! This module "ports" its functionality to sops :)

Setup

{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    sops-nix.url = "github:Mic92/sops-nix";
    sops-rekey.url = "github:Swarsel/sops-rekey";
  };

  outputs = { self, nixpkgs, sops-nix, sops-rekey, ... }: {
    nixosConfigurations.host = nixpkgs.lib.nixosSystem {
      modules = [ sops-nix.nixosModules.sops sops-rekey.nixosModules.default ./host.nix ];
    };

    apps = (sops-rekey.lib.configure {
      nodes = self.nixosConfigurations;
      masterRecipients.pgp = [ "<fingerprint>" ];
    }).apps;
  };
}

With flake-parts:

{
  inputs = {
    flake-parts.url = "github:hercules-ci/flake-parts";
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    sops-nix.url = "github:Mic92/sops-nix";
    sops-rekey.url = "github:Swarsel/sops-rekey";
  };

  outputs = inputs@{ flake-parts, nixpkgs, sops-nix, sops-rekey, ... }:
    flake-parts.lib.mkFlake { inherit inputs; } {
      imports = [ sops-rekey.flakeModule ];
      systems = [ "x86_64-linux" ];

      sops-rekey.masterRecipients.pgp = [ "<fingerprint>" ];

      flake.nixosConfigurations.host = nixpkgs.lib.nixosSystem {
        modules = [ sops-nix.nixosModules.sops sops-rekey.nixosModules.default ./host.nix ];
      };
    };
}

Usage

On the hosts:

{
  sops = {

    defaultSopsFile = ./secrets/common.yaml;
    rekey = {
      hostPubkey = "ssh-ed25519 AAAA...";
      storageDir = ./rekeyed;
    };

    secrets = {
      normalSecret = { };
      defaultRekeyedSecret.rekey = { key = "rekeyedSecret"; };
      rekeyedSecret.rekey = { file = ./secrets/local.yaml; };
      generatedSecret.rekey.generator.script = "wireguard";
    };
  };
}

In the above example, as soon as nix run .#sops-rekey -- rekey is called (this is preferable as it will automatically build and pick the correct manifest):

  • normalSecret is not touched by this module
  • defaultRekeyedSecret looks for a key called rekeyedSecret in ./secrets/common.yaml
  • rekeyedSecret looks for a key called rekeyedSecret in ./secrets/local.yaml.
  • generatedSecret generates (only when missing) a WireGuard private key into generatedSecret in ./secrets/common.yaml and writes the matching public key to ./secrets/common/generatedSecret.pub (you can override this location using [...].rekey.pubFile). Also see the complete set of generators.

All of the above "managed" secrets are then rekeyed into ./rekeyed/<name>.yaml. <name> is the hostnames that use this secret, concatenated with +.