{ inputs, ... }: { flake.modules.nixos.step-ca = { config, pkgs, lib, ... }: let cfg = config.step-ca; caPasswordPath = (lib.getAttr cfg.secrets.caPassword config.sops.secrets).path; intermediateCrtPath = (lib.getAttr cfg.secrets.intermediateCrt config.sops.secrets).path; intermediateKeyPath = (lib.getAttr cfg.secrets.intermediateKey config.sops.secrets).path; sshHostCaKeyPath = (lib.getAttr cfg.secrets.sshHostCaKey config.sops.secrets).path; sshUserCaKeyPath = (lib.getAttr cfg.secrets.sshUserCaKey config.sops.secrets).path; in { options.step-ca = { rootCertPath = lib.mkOption { description = "Path to the Step CA root certificate served by this host."; type = lib.types.path; }; dnsNames = lib.mkOption { description = "DNS names and IP SANs advertised by this Step CA instance."; type = with lib.types; listOf str; }; secrets = { sopsFile = lib.mkOption { description = "Host-local SOPS file that stores Step CA secret material."; type = lib.types.path; }; caPassword = lib.mkOption { description = "SOPS key for the Step CA intermediate password."; type = lib.types.str; }; intermediateCrt = lib.mkOption { description = "SOPS key for the Step CA intermediate certificate."; type = lib.types.str; }; intermediateKey = lib.mkOption { description = "SOPS key for the Step CA intermediate private key."; type = lib.types.str; }; sshHostCaKey = lib.mkOption { description = "SOPS key for the Step SSH host CA private key."; type = lib.types.str; }; sshUserCaKey = lib.mkOption { description = "SOPS key for the Step SSH user CA private key."; type = lib.types.str; }; }; }; config = { # Placeholders are expected initially until real material is inserted into sops. sops.secrets."${cfg.secrets.caPassword}" = { sopsFile = cfg.secrets.sopsFile; owner = "step-ca"; group = "step-ca"; mode = "0400"; }; sops.secrets."${cfg.secrets.intermediateCrt}" = { sopsFile = cfg.secrets.sopsFile; owner = "step-ca"; group = "step-ca"; mode = "0400"; }; sops.secrets."${cfg.secrets.intermediateKey}" = { sopsFile = cfg.secrets.sopsFile; owner = "step-ca"; group = "step-ca"; mode = "0400"; }; sops.secrets."${cfg.secrets.sshHostCaKey}" = { sopsFile = cfg.secrets.sopsFile; owner = "step-ca"; group = "step-ca"; mode = "0400"; }; sops.secrets."${cfg.secrets.sshUserCaKey}" = { sopsFile = cfg.secrets.sopsFile; owner = "step-ca"; group = "step-ca"; mode = "0400"; }; # https://github.com/NixOS/nixpkgs/blob/nixos-23.05/nixos/modules/services/security/step-ca.nix services.step-ca = { enable = true; openFirewall = true; address = "0.0.0.0"; port = 443; intermediatePasswordFile = caPasswordPath; # https://smallstep.com/docs/step-ca/configuration/#configuration-options settings = { root = cfg.rootCertPath; crt = intermediateCrtPath; key = intermediateKeyPath; dnsNames = cfg.dnsNames; ssh = { hostKey = sshHostCaKeyPath; userKey = sshUserCaKeyPath; }; db = { type = "badgerv2"; dataSource = "/var/lib/step-ca/db"; }; authority = { backdate = "1m0s"; provisioners = [ { type = "ACME"; name = "acme"; } { type = "SSHPOP"; name = "sshpop"; claims.enableSSHCA = true; } { type = "JWK"; name = "admin"; key = { use = "sig"; kty = "EC"; kid = "xoxgOJFbveSLIL2gm1Yu5ZiRb9v8Jxe44F56i3v-Nf8"; crv = "P-256"; alg = "ES256"; x = "zFO8hPx_eH0Iyz7UJI-w8ODMusEKCZ28M76sGWmWYxA"; y = "XIWLLyKDzqxV9UH-2KeAkKPDrgLoPrxxW9-PzkXggME"; }; encryptedKey = "eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJjdHkiOiJqd2sranNvbiIsImVuYyI6IkEyNTZHQ00iLCJwMmMiOjYwMDAwMCwicDJzIjoiUVJnTnJVTF9KcmxJYkJMVTlGNVRPZyJ9.DMu7xBNCq5pr-_--YTxNr5Hrcqy6ZmSVHsWurfVXL7Hk0Q3vyYRxiw.h-CnFiYc-DhxThI3.plx3_Qa_0kU-2TwnqFNfAfGnCpfQ2e0iiCMLruNHbLMnHeXQ1BysHBqps45_02zZXIRdHoDgYGtXRSfcdUYYoS0pLoPzC6m301ZFNSAFdRVlSZ3Q6VmWdixPXXnEB4EgSKTT_wxR33L8t9OpFzD85KfY-b_Un1l99ufjCnfg-EYkcICTn_G4-8bcW3eFIvJ6setzu-l0jHMhLQdIweqncn9on9xBXBD-ANhZfP95P2BJt-APqCi8eqiAvn_vClovdg0PxzRwOVDvWREz66FDw-HTU7xDtGO9hACopT5tfZOXDoykgZw1mJsq9NEq9ZzvKG2hvyk1UXtExxrNtFo.5q1OfGU4Amo4Si-vpeI42g"; claims = { enableSSHCA = true; disableRenewal = false; allowRenewalAfterExpiry = false; disableSmallstepExtensions = false; }; options = { x509 = { }; ssh = { }; }; } ]; }; tls = { cipherSuites = [ "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256" "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" ]; minVersion = 1.2; maxVersion = 1.3; renegotiation = false; }; }; }; environment.systemPackages = with pkgs; [ step-ca step-cli ]; }; }; }