{ lib, pkgs, config, ... }: let inherit (lib.modules) mkIf mkMerge; inherit (lib.options) mkOption; inherit (lib) types; inherit (pkgs) writeShellApplication; cfg = config.services.secrets; secretsLib = import ./secrets-lib/lib.nix { inherit lib pkgs; }; in { options = { services.secrets = { enable = mkOption { type = types.bool; default = false; }; debug = mkOption { type = types.bool; default = false; }; createSecretsDir = mkOption { type = types.bool; default = true; }; secretsDirUser = mkOption { type = types.either types.str types.int; default = "root"; }; secretsDirGroup = mkOption { type = types.either types.str types.int; default = "root"; }; secretsDir = mkOption { type = types.str; default = "/secrets"; }; vaultURL = mkOption { type = types.str; default = "https://vault.owo.monster"; description = "default Vault URL, can be overrided with env variables"; }; extraFunctions = mkOption { type = types.lines; default = ""; description = "extra bash functions to add to top of script"; }; uidMap = mkOption { type = types.attrsOf types.int; default = {}; description = "optional mapping of users to user IDs; required for SYSROOT when user isn't available on host"; }; gidMap = mkOption { type = types.attrsOf types.int; default = {}; description = "optional mapping of groups to group IDs; required for SYSROOT when group isn't available on host"; }; packages = mkOption { type = types.listOf types.package; default = with pkgs; []; description = "packages for script"; }; secrets = mkOption { type = types.attrsOf (types.submodule ({name, ...}: { options = { user = mkOption { type = types.either types.str types.int; default = "root"; }; group = mkOption { type = types.either types.str types.int; default = "root"; }; permissions = mkOption { type = types.str; default = "660"; }; path = mkOption { type = types.str; default = "${cfg.secretsDir}/${name}"; }; fetchScript = mkOption { type = types.nullOr types.lines; default = null; description = '' script used to fetch secrets, $secretFile is secret.path ''; }; checkScript = mkOption { type = types.nullOr types.lines; default = null; description = '' script used to check contents of secret file, set LOCAL_FAIL to true on failure ''; }; manual = mkOption { type = types.bool; default = false; description = "should the secret be manually deployed"; }; }; })); }; }; }; config = mkMerge [ (mkIf (cfg.enable) (let scripts = secretsLib.genScripts cfg; defaultPackages = with pkgs; [vault jq]; in { environment.systemPackages = [ (writeShellApplication { name = "secrets-init"; runtimeInputs = defaultPackages ++ cfg.packages; text = scripts.initScript; }) (writeShellApplication { name = "secrets-check"; runtimeInputs = defaultPackages ++ cfg.packages; text = scripts.checkScript; }) ]; })) (mkIf (cfg.enable && cfg.createSecretsDir) { systemd.tmpfiles.rules = [ "d ${cfg.secretsDir} - ${toString cfg.secretsDirUser} ${toString cfg.secretsDirGroup}" ]; }) ]; }