From 055a139fd2a7cc3c7592b2b9c38217061ea21d09 Mon Sep 17 00:00:00 2001 From: Jelle Spreeuwenberg Date: Tue, 21 Apr 2026 22:10:11 +0200 Subject: [PATCH] refactor: centralize workstation HM base and derive terminal from user metadata --- modules/features/_noctalia-config.nix | 6 +- modules/features/cli-base.nix | 18 ------ modules/features/ergon-workstation.nix | 9 +-- modules/features/kiri-server.nix | 12 ---- modules/features/kiri-workstation.nix | 7 +-- modules/features/meta.nix | 4 ++ modules/features/niri/_bindings.nix | 6 +- modules/features/niri/default.nix | 30 ++++++++- modules/features/noctalia.nix | 87 ++++++++++++++++++++++---- modules/features/terminal.nix | 41 +++++++++++- modules/features/workstation-base.nix | 19 ++++++ modules/hosts/orion/default.nix | 38 +++++++++-- modules/users.nix | 2 + 13 files changed, 213 insertions(+), 66 deletions(-) delete mode 100644 modules/features/cli-base.nix delete mode 100644 modules/features/kiri-server.nix diff --git a/modules/features/_noctalia-config.nix b/modules/features/_noctalia-config.nix index c19f6bc..d086813 100644 --- a/modules/features/_noctalia-config.nix +++ b/modules/features/_noctalia-config.nix @@ -1,3 +1,7 @@ +{ + lib, + terminalPackage, +}: { settingsVersion = 53; bar = { @@ -255,7 +259,7 @@ pinnedApps = [ ]; useApp2Unit = false; sortByMostUsed = true; - terminalCommand = "kitty -e"; + terminalCommand = "${lib.getExe terminalPackage} -e"; customLaunchPrefixEnabled = false; customLaunchPrefix = ""; viewMode = "grid"; diff --git a/modules/features/cli-base.nix b/modules/features/cli-base.nix deleted file mode 100644 index d2cdcfb..0000000 --- a/modules/features/cli-base.nix +++ /dev/null @@ -1,18 +0,0 @@ -{ config, ... }: -let - homeModules = config.flake.modules.homeManager; -in -{ - flake.modules.homeManager.cli-base = { - imports = [ - homeModules.terminal - homeModules.shell - homeModules.neovim - homeModules.nh - homeModules.git - homeModules.dev-tools - homeModules.podman - homeModules.ai - ]; - }; -} diff --git a/modules/features/ergon-workstation.nix b/modules/features/ergon-workstation.nix index 946621b..63acca9 100644 --- a/modules/features/ergon-workstation.nix +++ b/modules/features/ergon-workstation.nix @@ -4,13 +4,6 @@ let in { flake.modules.homeManager.ergon-workstation = { - imports = [ - homeModules.cli-base - homeModules.desktop-session - homeModules.personal-productivity - homeModules.ssh-client - homeModules.sops - homeModules.nix - ]; + imports = [ homeModules.workstation-base ]; }; } diff --git a/modules/features/kiri-server.nix b/modules/features/kiri-server.nix deleted file mode 100644 index 17baa88..0000000 --- a/modules/features/kiri-server.nix +++ /dev/null @@ -1,12 +0,0 @@ -{ config, ... }: -let - homeModules = config.flake.modules.homeManager; -in -{ - flake.modules.homeManager.kiri-server = { - imports = [ - homeModules.cli-base - homeModules.syncthing - ]; - }; -} diff --git a/modules/features/kiri-workstation.nix b/modules/features/kiri-workstation.nix index 95c4c1c..731c033 100644 --- a/modules/features/kiri-workstation.nix +++ b/modules/features/kiri-workstation.nix @@ -5,12 +5,7 @@ in { flake.modules.homeManager.kiri-workstation = { imports = [ - homeModules.cli-base - homeModules.desktop-session - homeModules.personal-productivity - homeModules.ssh-client - homeModules.sops - homeModules.nix + homeModules.workstation-base homeModules.syncthing homeModules.qbittorrent-client ]; diff --git a/modules/features/meta.nix b/modules/features/meta.nix index 96a36af..16d4458 100644 --- a/modules/features/meta.nix +++ b/modules/features/meta.nix @@ -35,6 +35,10 @@ let type = lib.types.str; }; + terminalPackageAttr = lib.mkOption { + type = lib.types.str; + }; + nixosConfigurationPath = lib.mkOption { type = lib.types.str; default = "${config.homeDirectory}/.config/nixos"; diff --git a/modules/features/niri/_bindings.nix b/modules/features/niri/_bindings.nix index 2d9a72f..4f82b09 100644 --- a/modules/features/niri/_bindings.nix +++ b/modules/features/niri/_bindings.nix @@ -1,6 +1,10 @@ +{ + lib, + terminalPackage, +}: { "Mod+Return" = { - action.spawn = "kitty"; + action.spawn = "${lib.getExe terminalPackage}"; hotkey-overlay.title = "Terminal"; }; "Mod+B" = { diff --git a/modules/features/niri/default.nix b/modules/features/niri/default.nix index 453ac48..87468e8 100644 --- a/modules/features/niri/default.nix +++ b/modules/features/niri/default.nix @@ -41,8 +41,27 @@ inherit (display) mode; } ) config.meta.host.displays; + rawTerminalAttrPath = lib.splitString "." config.meta.user.terminalPackageAttr; + terminalAttrPath = + if rawTerminalAttrPath != [ ] && builtins.head rawTerminalAttrPath == "pkgs" then + builtins.tail rawTerminalAttrPath + else + rawTerminalAttrPath; + terminalPackage = lib.attrByPath terminalAttrPath null pkgs; + hasMainProgram = terminalPackage != null && terminalPackage ? meta.mainProgram; in { + assertions = [ + { + assertion = terminalPackage != null; + message = "Unknown terminal package `${config.meta.user.terminalPackageAttr}` for user `${config.meta.user.name}`."; + } + { + assertion = hasMainProgram; + message = "Terminal package `${config.meta.user.terminalPackageAttr}` must define `meta.mainProgram`."; + } + ]; + home.sessionVariables.NIXOS_OZONE_WL = "1"; dconf.settings = { @@ -123,7 +142,16 @@ mouse.accel-speed = 0.4; }; - binds = import ./_bindings.nix; + binds = + if hasMainProgram then + import ./_bindings.nix { + inherit + lib + terminalPackage + ; + } + else + { }; }; }; } diff --git a/modules/features/noctalia.nix b/modules/features/noctalia.nix index 0a6ea52..ddf141c 100644 --- a/modules/features/noctalia.nix +++ b/modules/features/noctalia.nix @@ -5,26 +5,59 @@ }: let homeModules = config.flake.modules.homeManager; - baseSettings = import ./_noctalia-config.nix; - portableSettings = lib.recursiveUpdate baseSettings { - bar.widgets.right = baseSettings.bar.widgets.right ++ [ - { - id = "Battery"; - } - ]; - }; + mkPortableSettings = + baseSettings: + lib.recursiveUpdate baseSettings { + bar.widgets.right = baseSettings.bar.widgets.right ++ [ + { + id = "Battery"; + } + ]; + }; in { flake.modules.homeManager.noctalia = { inputs, + config, lib, pkgs, ... }: + let + rawTerminalAttrPath = lib.splitString "." config.meta.user.terminalPackageAttr; + terminalAttrPath = + if rawTerminalAttrPath != [ ] && builtins.head rawTerminalAttrPath == "pkgs" then + builtins.tail rawTerminalAttrPath + else + rawTerminalAttrPath; + terminalPackage = lib.attrByPath terminalAttrPath null pkgs; + hasMainProgram = terminalPackage != null && terminalPackage ? meta.mainProgram; + baseSettings = + if hasMainProgram then + import ./_noctalia-config.nix { + inherit + lib + terminalPackage + ; + } + else + { }; + in { imports = [ inputs.noctalia.homeModules.default ]; + assertions = [ + { + assertion = terminalPackage != null; + message = "Unknown terminal package `${config.meta.user.terminalPackageAttr}` for user `${config.meta.user.name}`."; + } + { + assertion = hasMainProgram; + message = "Terminal package `${config.meta.user.terminalPackageAttr}` must define `meta.mainProgram`."; + } + ]; + programs.noctalia-shell = { enable = true; package = lib.mkForce ( @@ -37,9 +70,37 @@ in }; }; - flake.modules.homeManager.noctalia-portable = { - imports = [ homeModules.noctalia ]; - - programs.noctalia-shell.settings = lib.mkForce portableSettings; - }; + flake.modules.homeManager.noctalia-portable = + { + config, + lib, + pkgs, + ... + }: + let + rawTerminalAttrPath = lib.splitString "." config.meta.user.terminalPackageAttr; + terminalAttrPath = + if rawTerminalAttrPath != [ ] && builtins.head rawTerminalAttrPath == "pkgs" then + builtins.tail rawTerminalAttrPath + else + rawTerminalAttrPath; + terminalPackage = lib.attrByPath terminalAttrPath null pkgs; + hasMainProgram = terminalPackage != null && terminalPackage ? meta.mainProgram; + baseSettings = + if hasMainProgram then + import ./_noctalia-config.nix { + inherit + lib + terminalPackage + ; + } + else + { }; + in + { + imports = [ homeModules.noctalia ]; + programs.noctalia-shell.settings = lib.mkForce ( + if hasMainProgram then mkPortableSettings baseSettings else { } + ); + }; } diff --git a/modules/features/terminal.nix b/modules/features/terminal.nix index 3d93508..1f9286b 100644 --- a/modules/features/terminal.nix +++ b/modules/features/terminal.nix @@ -1,10 +1,47 @@ { flake.modules.homeManager.terminal = - { pkgs, ... }: { + config, + lib, + pkgs, + ... + }: + let + rawTerminalAttrPath = lib.splitString "." config.meta.user.terminalPackageAttr; + terminalAttrPath = + if rawTerminalAttrPath != [ ] && builtins.head rawTerminalAttrPath == "pkgs" then + builtins.tail rawTerminalAttrPath + else + rawTerminalAttrPath; + terminalPackage = lib.attrByPath terminalAttrPath null pkgs; + hasTerminalPackage = terminalPackage != null; + hasMainProgram = hasTerminalPackage && terminalPackage ? meta.mainProgram; + terminalDesktopId = + if hasMainProgram then "${terminalPackage.meta.mainProgram}.desktop" else null; + in + { + assertions = [ + { + assertion = hasTerminalPackage; + message = "Unknown terminal package `${config.meta.user.terminalPackageAttr}` for user `${config.meta.user.name}`."; + } + { + assertion = hasMainProgram; + message = "Terminal package `${config.meta.user.terminalPackageAttr}` must define `meta.mainProgram`."; + } + { + assertion = hasMainProgram && builtins.pathExists "${terminalPackage}/share/applications/${terminalDesktopId}"; + message = "Terminal package `${config.meta.user.terminalPackageAttr}` must provide `${terminalDesktopId}`."; + } + { + assertion = hasMainProgram && terminalPackage.meta.mainProgram == "kitty"; + message = "The terminal feature currently only supports kitty-specific Home Manager configuration."; + } + ]; + xdg.terminal-exec = { enable = true; - settings.default = [ "kitty.desktop" ]; + settings.default = lib.optional (terminalDesktopId != null) terminalDesktopId; }; programs.kitty = { diff --git a/modules/features/workstation-base.nix b/modules/features/workstation-base.nix index 684b3f2..c1d249e 100644 --- a/modules/features/workstation-base.nix +++ b/modules/features/workstation-base.nix @@ -1,6 +1,7 @@ { config, ... }: let nixosModules = config.flake.modules.nixos; + homeModules = config.flake.modules.homeManager; in { flake.modules.nixos.workstation-base = { @@ -26,4 +27,22 @@ in programs.nix-ld.enable = true; environment.localBinInPath = true; }; + + flake.modules.homeManager.workstation-base = { + imports = [ + homeModules.terminal + homeModules.shell + homeModules.neovim + homeModules.nh + homeModules.git + homeModules.dev-tools + homeModules.podman + homeModules.ai + homeModules.desktop-session + homeModules.personal-productivity + homeModules.ssh-client + homeModules.sops + homeModules.nix + ]; + }; } diff --git a/modules/hosts/orion/default.nix b/modules/hosts/orion/default.nix index 2ea6940..adc97f8 100644 --- a/modules/hosts/orion/default.nix +++ b/modules/hosts/orion/default.nix @@ -10,8 +10,33 @@ let in { flake.modules.nixos.orion-admin = - { pkgs, ... }: { + config, + lib, + pkgs, + ... + }: + let + rawTerminalAttrPath = lib.splitString "." config.meta.host.users.kiri.terminalPackageAttr; + terminalAttrPath = + if rawTerminalAttrPath != [ ] && builtins.head rawTerminalAttrPath == "pkgs" then + builtins.tail rawTerminalAttrPath + else + rawTerminalAttrPath; + terminalPackage = lib.attrByPath terminalAttrPath null pkgs; + in + { + assertions = [ + { + assertion = terminalPackage != null; + message = "Unknown terminal package `${config.meta.host.users.kiri.terminalPackageAttr}` for user `kiri`."; + } + { + assertion = terminalPackage != null && lib.elem "terminfo" terminalPackage.outputs; + message = "Terminal package `${config.meta.host.users.kiri.terminalPackageAttr}` must provide a `terminfo` output for `orion`."; + } + ]; + users.users.kiri = { linger = true; openssh.authorizedKeys.keys = [ @@ -20,8 +45,9 @@ in }; environment.systemPackages = [ - pkgs.kitty - ]; + ] ++ lib.optional (terminalPackage != null && lib.elem "terminfo" terminalPackage.outputs) ( + lib.getOutput "terminfo" terminalPackage + ); }; flake.modules.nixos.orion = metaLib.mkHost { @@ -45,7 +71,11 @@ in (metaLib.mkHostUser { account = metaLib.users.kiri; needsPassword = false; - homeImports = [ homeModules.kiri-server ]; + homeImports = [ + homeModules.shell + homeModules.git + homeModules.syncthing + ]; }) ./_hardware.nix ./_disk.nix diff --git a/modules/users.nix b/modules/users.nix index 0ca11e8..60f6029 100644 --- a/modules/users.nix +++ b/modules/users.nix @@ -4,6 +4,7 @@ let name = "kiri"; realName = "Jelle Spreeuwenberg"; homeDirectory = "/home/kiri"; + terminalPackageAttr = "kitty"; emails = { main = { address = "mail@jelles.net"; @@ -32,6 +33,7 @@ let name = "ergon"; realName = "Jelle Spreeuwenberg"; homeDirectory = "/home/ergon"; + terminalPackageAttr = "kitty"; emails = { work = { address = "jelle.spreeuwenberg@yookr.org";