refactor(secrets): simplify home manager secrets
check / lint (push) Successful in 15s

This commit is contained in:
hektor committed 2026-11-06 16:43:26 +01:00
1 parent 6fa74fead8
commit c2bb81ec7c
11 files changed
+153 -139

No files matched your search

-1
View File
@@ -15,7 +15,6 @@ with pkgs;
parallel parallel
pass pass
ripgrep ripgrep
sops
tldr tldr
tree tree
wget wget
+10 -20
View File
@@ -2,25 +2,18 @@
config, config,
lib, lib,
pkgs, pkgs,
lib',
osConfig ? null,
inputs ? null,
... ...
}: }:
let let
sops = lib'.sopsAvailability config osConfig; authReady = config.secrets.templatePath ? "opencode/auth.json";
standalone = osConfig == null;
in in
{ {
config = lib.mkIf config.ai-tools.opencode.enable ( config = lib.mkIf config.ai-tools.opencode.enable {
lib.optionalAttrs standalone { secrets.files.opencode = [ "api-key" ];
sops = {
secrets = lib'.mkSopsSecrets "${toString inputs.nix-secrets}/secrets" null { secrets.templates."opencode/auth.json" = {
opencode = [ "api-key" ]; path = ".local/share/opencode/auth.json";
};
templates."opencode/auth.json" = {
path = "${config.home.homeDirectory}/.local/share/opencode/auth.json";
content = builtins.toJSON { content = builtins.toJSON {
zai-coding-plan = { zai-coding-plan = {
type = "api"; type = "api";
@@ -28,12 +21,10 @@ in
}; };
}; };
}; };
};
}
// {
warnings = warnings =
lib.optional (!sops.available) lib.optional (!authReady)
"opencode is enabled, but sops templates are not available. the opencode API key will not be configured."; "opencode is enabled but its auth template is unavailable. the opencode API key will not be configured.";
home.packages = [ pkgs.opencode ]; home.packages = [ pkgs.opencode ];
home.file.".config/opencode/opencode.json".text = builtins.toJSON { home.file.".config/opencode/opencode.json".text = builtins.toJSON {
@@ -57,6 +48,5 @@ in
}; };
plugin = [ "@mohak34/opencode-notifier@latest" ]; plugin = [ "@mohak34/opencode-notifier@latest" ];
}; };
} };
);
} }
+10 -19
View File
@@ -2,33 +2,25 @@
config, config,
lib, lib,
pkgs, pkgs,
lib',
osConfig ? null,
inputs ? null,
... ...
}: }:
let let
cfg = config.anki; cfg = config.anki;
sops = lib'.sopsAvailability config osConfig; syncReady = config.secrets.path ? "anki/sync-user" && config.secrets.path ? "anki/sync-key";
standalone = osConfig == null;
in in
{ {
options.anki.enable = lib.mkEnableOption "Anki"; options.anki.enable = lib.mkEnableOption "Anki";
config = lib.mkIf cfg.enable ( config = lib.mkIf cfg.enable {
lib.optionalAttrs standalone { secrets.files.anki = [
sops.secrets = lib'.mkSopsSecrets "${toString inputs.nix-secrets}/secrets" null {
anki = [
"sync-user" "sync-user"
"sync-key" "sync-key"
]; ];
};
}
// {
warnings = lib.optional ( warnings = lib.optional (
!sops.available !syncReady
) "anki is enabled but sops secrets are not available. anki sync will not be configured."; ) "anki is enabled but its secrets are unavailable. anki sync will not be configured.";
programs.anki = { programs.anki = {
enable = true; enable = true;
@@ -48,14 +40,13 @@ in
puppy-reinforcement puppy-reinforcement
review-heatmap review-heatmap
]; ];
profiles."User 1".sync = lib.mkIf sops.available { profiles."User 1".sync = lib.mkIf syncReady {
usernameFile = "${sops.secrets."anki/sync-user".path}"; usernameFile = config.secrets.path."anki/sync-user";
keyFile = "${sops.secrets."anki/sync-key".path}"; keyFile = config.secrets.path."anki/sync-key";
}; };
}; };
# allow Anki to write prefs # allow Anki to write prefs
home.file."${config.xdg.dataHome}/Anki2/prefs21.db".enable = lib.mkForce false; home.file."${config.xdg.dataHome}/Anki2/prefs21.db".enable = lib.mkForce false;
} };
);
} }
+26 -32
View File
@@ -1,22 +1,24 @@
{ {
config, config,
inputs,
lib, lib,
lib',
osConfig ? null,
... ...
}: }:
let let
cfg = config.git; cfg = config.git;
sops = lib'.sopsAvailability config osConfig; identities = [
standalone = osConfig == null; "personal"
"work"
];
personalEmail = sops.templates.".gitconfig.email".path; emailTemplate = key: ".gitconfig.${key}.email";
workEmail = sops.templates.".gitconfig.work.email".path; emailInclude =
key:
lib.optionalAttrs (config.secrets.templatePath ? ${emailTemplate key}) {
include.path = config.secrets.templatePath.${emailTemplate key};
};
workSettings = { workSettings = emailInclude "work" // {
include.path = workEmail;
core.longpaths = true; core.longpaths = true;
user = { user = {
name = "Hektor Misplon"; name = "Hektor Misplon";
@@ -47,29 +49,19 @@ in
./gitlab.nix ./gitlab.nix
]; ];
config = lib.mkIf cfg.enable ( config = lib.mkIf cfg.enable {
lib.optionalAttrs standalone { secrets.files.email = identities;
sops = {
secrets = lib'.mkSopsSecrets "${toString inputs.nix-secrets}/secrets" null {
email = [
"personal"
"work"
];
};
templates = { secrets.templates = lib.genAttrs' identities (
".gitconfig.email".content = '' key:
lib.nameValuePair (emailTemplate key) {
content = ''
[user] [user]
email = ${config.sops.placeholder."email/personal"} email = ${config.sops.placeholder."email/${key}"}
''; '';
".gitconfig.work.email".content = ''
[user]
email = ${config.sops.placeholder."email/work"}
'';
};
};
} }
// { );
warnings = lib.optional ( warnings = lib.optional (
!config.nvim.enable !config.nvim.enable
) "'git.enable' is enabled without 'nvim.enable' (not using 'nvimdiff')"; ) "'git.enable' is enabled without 'nvim.enable' (not using 'nvimdiff')";
@@ -162,8 +154,11 @@ in
}) })
]; ];
includes = [ includes =
{ path = personalEmail; } lib.optional (config.secrets.templatePath ? ${emailTemplate "personal"}) {
path = config.secrets.templatePath.${emailTemplate "personal"};
}
++ [
{ {
condition = "gitdir:~/work/"; condition = "gitdir:~/work/";
contents = workSettings; contents = workSettings;
@@ -176,6 +171,5 @@ in
} }
]; ];
}; };
} };
);
} }
+84 -14
View File
@@ -2,24 +2,94 @@
config, config,
lib, lib,
pkgs, pkgs,
inputs,
lib',
osConfig ? null,
... ...
}: }:
let
cfg = config.secrets;
sops = lib'.sopsAvailability config osConfig;
standalone = !sops.osAvailable;
sopsDir = "${toString inputs.nix-secrets}/secrets";
in
{ {
options.secrets = {
enable = lib.mkEnableOption "secrets";
vault = {
enable = lib.mkEnableOption "vault CLI";
};
};
imports = [ ./vault.nix ]; imports = [ ./vault.nix ];
config = lib.mkIf config.secrets.enable { options.secrets = {
home.packages = with pkgs; [ enable = lib.mkEnableOption "secrets";
age vault.enable = lib.mkEnableOption "vault CLI";
age-plugin-yubikey
sops files = lib.mkOption {
]; type = lib.types.attrsOf (lib.types.listOf lib.types.str);
}; };
templates = lib.mkOption {
type = lib.types.attrsOf (
lib.types.submodule {
options = {
path = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
};
content = lib.mkOption {
type = lib.types.str;
};
};
}
);
};
path = lib.mkOption {
type = lib.types.attrsOf lib.types.str;
readOnly = true;
};
templatePath = lib.mkOption {
type = lib.types.attrsOf lib.types.str;
readOnly = true;
};
};
config = lib.mkMerge [
{
secrets.path = lib.optionalAttrs sops.available (
lib.mapAttrs (_: secret: secret.path) sops.secrets
);
secrets.templatePath = lib.optionalAttrs sops.available (
lib.mapAttrs (_: template: template.path) sops.templates
);
}
(lib.mkIf cfg.enable (
lib.optionalAttrs standalone {
sops = {
secrets = lib'.mkSopsSecrets sopsDir null cfg.files;
templates = lib.mapAttrs (
_: t:
{
inherit (t) content;
}
// lib.optionalAttrs (t.path != null) {
path = "${config.home.homeDirectory}/${t.path}";
}
) cfg.templates;
};
}
// {
home.packages = [
pkgs.age
pkgs.age-plugin-yubikey
pkgs.sops
];
warnings = lib.optional (
!sops.available && (cfg.files != { } || cfg.templates != { })
) "secrets declared, but sops unavailable.";
}
))
];
} }
+10 -23
View File
@@ -2,15 +2,11 @@
config, config,
lib, lib,
pkgs, pkgs,
lib',
osConfig ? null,
inputs ? null,
... ...
}: }:
let let
sops = lib'.sopsAvailability config osConfig; syncReady = config.secrets.templatePath ? "taskrc.d/sync";
standalone = osConfig == null;
syncHook = pkgs.writers.writePython3 "on-exit.sync.py" { flakeIgnore = [ "E501" ]; } '' syncHook = pkgs.writers.writePython3 "on-exit.sync.py" { flakeIgnore = [ "E501" ]; } ''
# Source: <https://gist.github.com/danmou/83079feac22307813178d7f8c456c544> # Source: <https://gist.github.com/danmou/83079feac22307813178d7f8c456c544>
@@ -61,30 +57,22 @@ in
{ {
options.taskwarrior.enable = lib.mkEnableOption "taskwarrior"; options.taskwarrior.enable = lib.mkEnableOption "taskwarrior";
config = lib.mkIf config.taskwarrior.enable ( config = lib.mkIf config.taskwarrior.enable {
lib.optionalAttrs standalone { secrets.files.taskwarrior = [
sops = {
secrets = lib'.mkSopsSecrets "${toString inputs.nix-secrets}/secrets" null {
taskwarrior = [
"sync-server-url" "sync-server-url"
"sync-server-client-id" "sync-server-client-id"
"sync-encryption-secret" "sync-encryption-secret"
]; ];
};
templates."taskrc.d/sync" = { secrets.templates."taskrc.d/sync".content = ''
content = ''
sync.server.url=${config.sops.placeholder."taskwarrior/sync-server-url"} sync.server.url=${config.sops.placeholder."taskwarrior/sync-server-url"}
sync.server.client_id=${config.sops.placeholder."taskwarrior/sync-server-client-id"} sync.server.client_id=${config.sops.placeholder."taskwarrior/sync-server-client-id"}
sync.encryption_secret=${config.sops.placeholder."taskwarrior/sync-encryption-secret"} sync.encryption_secret=${config.sops.placeholder."taskwarrior/sync-encryption-secret"}
''; '';
};
};
}
// {
warnings = warnings =
lib.optional (!sops.available) lib.optional (!syncReady)
"taskwarrior is enabled, but sops templates are not available. taskwarrior sync will not be configured."; "taskwarrior is enabled but its sync template is unavailable. taskwarrior sync will not be configured.";
home.file = { home.file = {
".local/share/task/hooks/on-exit.sync.py".source = syncHook; ".local/share/task/hooks/on-exit.sync.py".source = syncHook;
@@ -162,10 +150,9 @@ in
"recurrence" = "off"; "recurrence" = "off";
"reserved.lines" = "3"; "reserved.lines" = "3";
}; };
extraConfig = lib.optionalString sops.available '' extraConfig = lib.optionalString syncReady ''
include ${sops.templates."taskrc.d/sync".path} include ${config.secrets.templatePath."taskrc.d/sync"}
''; '';
}; };
} };
);
} }
+1 -1
View File
@@ -72,7 +72,7 @@ in
sandboxing.enable = true; sandboxing.enable = true;
secrets = { secrets = {
enable = true; enable = true;
nixSigningKey.enable = true; nix = [ "signing-key" ];
}; };
ssh.enable = true; ssh.enable = true;
storage.enable = true; storage.enable = true;
+1 -1
View File
@@ -74,7 +74,7 @@ in
wol.wakes = [ "andromache" ]; wol.wakes = [ "andromache" ];
zfs.enable = true; zfs.enable = true;
secrets.nixSigningKey.enable = true; secrets.nix = [ "signing-key" ];
restic-backup.enable = true; restic-backup.enable = true;
tailscale.enable = true; tailscale.enable = true;
desktop.ly.enable = true; desktop.ly.enable = true;
+1
View File
@@ -28,6 +28,7 @@
in in
{ {
available = osSopsAvailable || hmSopsAvailable; available = osSopsAvailable || hmSopsAvailable;
osAvailable = osSopsAvailable;
secrets = if osSopsAvailable then osConfig.sops.secrets else config.sops.secrets; secrets = if osSopsAvailable then osConfig.sops.secrets else config.sops.secrets;
templates = if osSopsAvailable then osConfig.sops.templates else config.sops.templates; templates = if osSopsAvailable then osConfig.sops.templates else config.sops.templates;
}; };
+6 -12
View File
@@ -9,21 +9,15 @@ in
options.git.enable = lib.mkEnableOption "git"; options.git.enable = lib.mkEnableOption "git";
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
sops.templates = { sops.templates = lib.genAttrs' [ "personal" "work" ] (
".gitconfig.email" = { key:
lib.nameValuePair ".gitconfig.${key}.email" {
inherit owner; inherit owner;
content = '' content = ''
[user] [user]
email = ${config.sops.placeholder."email/personal"} email = ${config.sops.placeholder."email/${key}"}
''; '';
}; }
".gitconfig.work.email" = { );
inherit owner;
content = ''
[user]
email = ${config.sops.placeholder."email/work"}
'';
};
};
}; };
} }
+4 -16
View File
@@ -10,15 +10,14 @@
let let
cfg = config.secrets; cfg = config.secrets;
inherit (config.host) username; inherit (config.host) username;
inherit (cfg) sopsDir; sopsDir = "${toString inputs.nix-secrets}/secrets";
owner = config.users.users.${username}.name; owner = username;
system = { system = {
email = [ email = [
"personal" "personal"
"work" "work"
]; ];
nix = lib.optional cfg.nixSigningKey.enable "signing-key";
} }
// lib.filterAttrs (_: lib.isList) cfg; // lib.filterAttrs (_: lib.isList) cfg;
in in
@@ -33,11 +32,6 @@ in
options = { options = {
enable = lib.mkEnableOption "secrets management"; enable = lib.mkEnableOption "secrets management";
sopsDir = lib.mkOption {
type = lib.types.str;
default = "${toString inputs.nix-secrets}/secrets";
};
user = lib.mkOption { user = lib.mkOption {
type = lib.types.attrsOf (lib.types.listOf lib.types.str); type = lib.types.attrsOf (lib.types.listOf lib.types.str);
default = { }; default = { };
@@ -48,10 +42,6 @@ in
default = owner; default = owner;
}; };
nixSigningKey = {
enable = lib.mkEnableOption "nix signing key configuration";
};
yubikey = { yubikey = {
enable = lib.mkEnableOption "set up Yubikey"; enable = lib.mkEnableOption "set up Yubikey";
}; };
@@ -60,11 +50,9 @@ in
}; };
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
sops = { sops.secrets = lib'.mkSopsSecrets sopsDir null system // lib'.mkSopsSecrets sopsDir owner cfg.user;
secrets = lib'.mkSopsSecrets sopsDir null system // lib'.mkSopsSecrets sopsDir owner cfg.user;
};
nix.settings.secret-key-files = lib.mkIf cfg.nixSigningKey.enable [ nix.settings.secret-key-files = lib.mkIf (system ? nix) [
config.sops.secrets."nix/signing-key".path config.sops.secrets."nix/signing-key".path
]; ];