refactor: compose hosts and home-manager features explicitly

This commit is contained in:
2026-04-21 16:04:06 +02:00
parent 8c254f2eb1
commit a73cefb9df
28 changed files with 322 additions and 303 deletions
+17
View File
@@ -0,0 +1,17 @@
{ config, ... }:
let
homeModules = config.flake.modules.homeManager;
in
{
flake.modules.homeManager.cli-base = {
imports = [
homeModules.terminal
homeModules.shell
homeModules.neovim
homeModules.git
homeModules.dev-tools
homeModules.podman
homeModules.gemini
];
};
}
-50
View File
@@ -1,50 +0,0 @@
{ config, ... }:
let
nixosModules = config.flake.modules.nixos;
in
{
flake.modules.nixos."core-base" = {
imports = [
nixosModules."meta-host"
nixosModules."home-manager-base"
nixosModules.nix
nixosModules."region-nl"
nixosModules."sops-host"
];
};
flake.modules.nixos."server-base" = {
imports = [
nixosModules."core-base"
nixosModules.openssh
];
};
flake.modules.nixos."workstation-base" = {
imports = [
nixosModules."core-base"
nixosModules."standard-boot"
nixosModules.sddm
nixosModules.niri
nixosModules.audio
nixosModules.bluetooth
nixosModules.flatpak
nixosModules.fonts
nixosModules.networking
nixosModules.printing
nixosModules."qbittorrent-client"
];
users.mutableUsers = false;
services.dbus.implementation = "broker";
programs.nix-ld.enable = true;
environment.localBinInPath = true;
};
flake.modules.nixos."portable-host" = {
hardware.enableRedistributableFirmware = true;
services.fwupd.enable = true;
};
}
+17
View File
@@ -0,0 +1,17 @@
{ config, ... }:
let
homeModules = config.flake.modules.homeManager;
in
{
flake.modules.homeManager.desktop-session = {
imports = [
homeModules.niri
homeModules.clipboard
homeModules.local-apps
homeModules.mpv
homeModules.vicinae
homeModules.xdg
homeModules.theme
];
};
}
+1 -1
View File
@@ -1,5 +1,5 @@
{
flake.modules.homeManager."dev-tools" =
flake.modules.homeManager.dev-tools =
{ config, ... }:
{
home.sessionVariables.CARGO_HOME = "${config.xdg.dataHome}/cargo";
+9 -2
View File
@@ -3,7 +3,14 @@ let
homeModules = config.flake.modules.homeManager;
in
{
flake.modules.homeManager."ergon-workstation" = {
imports = [ homeModules.nix ];
flake.modules.homeManager.ergon-workstation = {
imports = [
homeModules.cli-base
homeModules.desktop-session
homeModules.personal-productivity
homeModules.ssh-client
homeModules.sops
homeModules.nix
];
};
}
-26
View File
@@ -1,26 +0,0 @@
{
inputs,
config,
...
}:
let
homeModules = config.flake.modules.homeManager;
in
{
flake.modules.nixos."home-manager-base" =
{ ... }:
{
imports = [ inputs.home-manager.nixosModules.home-manager ];
home-manager = {
useGlobalPkgs = true;
backupFileExtension = "bak";
extraSpecialArgs = { inherit inputs; };
sharedModules = [ homeModules."meta-context" ];
};
security.sudo.extraConfig = ''
Defaults env_keep+=SSH_AUTH_SOCK
'';
};
}
+30
View File
@@ -0,0 +1,30 @@
{
config,
inputs,
...
}:
let
nixosModules = config.flake.modules.nixos;
homeModules = config.flake.modules.homeManager;
in
{
flake.modules.nixos.host-base = {
imports = [
nixosModules.meta
inputs.home-manager.nixosModules.home-manager
nixosModules.nix
nixosModules.region-nl
];
home-manager = {
useGlobalPkgs = true;
backupFileExtension = "bak";
extraSpecialArgs = { inherit inputs; };
sharedModules = [ homeModules.meta ];
};
security.sudo.extraConfig = ''
Defaults env_keep+=SSH_AUTH_SOCK
'';
};
}
+12
View File
@@ -0,0 +1,12 @@
{ config, ... }:
let
homeModules = config.flake.modules.homeManager;
in
{
flake.modules.homeManager.kiri-server = {
imports = [
homeModules.cli-base
homeModules.syncthing
];
};
}
+8 -13
View File
@@ -3,21 +3,16 @@ let
homeModules = config.flake.modules.homeManager;
in
{
flake.modules.homeManager."kiri-workstation" = {
flake.modules.homeManager.kiri-workstation = {
imports = [
homeModules.cli-base
homeModules.desktop-session
homeModules.personal-productivity
homeModules.ssh-client
homeModules.sops
homeModules.nix
homeModules.bitwarden
homeModules.email
homeModules.pim
homeModules.mpv
homeModules.niri
homeModules.clipboard
homeModules."local-apps"
homeModules."qbittorrent-client"
homeModules.vicinae
homeModules.xdg
homeModules.theme
homeModules.noctalia
homeModules.syncthing
homeModules.qbittorrent-client
];
};
}
+1 -1
View File
@@ -1,5 +1,5 @@
{
flake.modules.homeManager."local-apps" =
flake.modules.homeManager.local-apps =
{ pkgs, ... }:
{
home.sessionVariables.BROWSER = "vivaldi";
+2 -14
View File
@@ -99,18 +99,6 @@ let
type = lib.types.str;
};
kind = lib.mkOption {
type = lib.types.enum [
"server"
"workstation"
];
};
traits = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
};
displays = lib.mkOption {
type = lib.types.attrsOf displayType;
default = { };
@@ -125,13 +113,13 @@ let
);
in
{
flake.modules.nixos."meta-host" = {
flake.modules.nixos.meta = {
options.meta.host = lib.mkOption {
type = hostType;
};
};
flake.modules.homeManager."meta-context" = {
flake.modules.homeManager.meta = {
options.meta = {
host = lib.mkOption {
type = lib.types.nullOr hostType;
+1 -1
View File
@@ -1,5 +1,5 @@
{
flake.modules.nixos."server-firewall" = {
flake.modules.nixos.server-firewall = {
networking = {
firewall.enable = true;
firewall.allowPing = false;
+23 -1
View File
@@ -1,3 +1,19 @@
{
config,
lib,
...
}:
let
homeModules = config.flake.modules.homeManager;
baseSettings = import ./_noctalia-config.nix;
portableSettings = lib.recursiveUpdate baseSettings {
bar.widgets.right = baseSettings.bar.widgets.right ++ [
{
id = "Battery";
}
];
};
in
{
flake.modules.homeManager.noctalia =
{
@@ -17,7 +33,13 @@
}
);
settings = import ./_noctalia-config.nix;
settings = baseSettings;
};
};
flake.modules.homeManager.noctalia-portable = {
imports = [ homeModules.noctalia ];
programs.noctalia-shell.settings = lib.mkForce portableSettings;
};
}
@@ -0,0 +1,13 @@
{ config, ... }:
let
homeModules = config.flake.modules.homeManager;
in
{
flake.modules.homeManager.personal-productivity = {
imports = [
homeModules.bitwarden
homeModules.email
homeModules.pim
];
};
}
+2 -2
View File
@@ -1,12 +1,12 @@
{
flake.modules.nixos."qbittorrent-client" = {
flake.modules.nixos.qbittorrent-client = {
networking.firewall = {
allowedTCPPorts = [ 43864 ];
allowedUDPPorts = [ 43864 ];
};
};
flake.modules.homeManager."qbittorrent-client" =
flake.modules.homeManager.qbittorrent-client =
{ pkgs, ... }:
{
home.packages = [ pkgs.qbittorrent ];
+1 -1
View File
@@ -1,6 +1,6 @@
{ ... }:
{
flake.modules.nixos."region-nl" = {
flake.modules.nixos.region-nl = {
time.timeZone = "Europe/Amsterdam";
i18n.defaultLocale = "en_US.UTF-8";
+2 -2
View File
@@ -1,5 +1,5 @@
{
flake.modules.nixos."deluge-service" =
flake.modules.nixos.deluge-service =
{ ... }:
{
sops.secrets.deluge-auth-file = { };
@@ -10,7 +10,7 @@
};
};
flake.modules.homeManager."deluge-client" =
flake.modules.homeManager.deluge-client =
{ pkgs, ... }:
{
home.packages = [ pkgs.deluge ];
+4 -7
View File
@@ -1,6 +1,6 @@
{ ... }:
{
flake.modules.nixos."ssh-agent-auth" = {
flake.modules.nixos.ssh-agent-auth = {
security.pam = {
sshAgentAuth.enable = true;
services.sudo.sshAgentAuth = true;
@@ -12,18 +12,15 @@
config,
...
}:
let
isServer = config.meta.host.kind == "server";
hostUserNames = builtins.attrNames config.meta.host.users;
in
{
services.openssh.openFirewall = true;
services.openssh = {
enable = true;
openFirewall = isServer;
settings = {
PermitRootLogin = "no";
PasswordAuthentication = false;
AllowUsers = hostUserNames;
AllowUsers = builtins.attrNames config.meta.host.users;
};
};
};
+1 -1
View File
@@ -1,5 +1,5 @@
{
flake.modules.homeManager."ssh-client" =
flake.modules.homeManager.ssh-client =
{ config, ... }:
{
programs.ssh = {
+1 -1
View File
@@ -1,6 +1,6 @@
{ ... }:
{
flake.modules.nixos."standard-boot" =
flake.modules.nixos.standard-boot =
{ config, pkgs, ... }:
{
boot = {
-29
View File
@@ -1,29 +0,0 @@
{ config, ... }:
let
homeModules = config.flake.modules.homeManager;
in
{
flake.modules.homeManager."common-user-base" = {
imports = [
homeModules.terminal
homeModules.shell
homeModules.neovim
homeModules.git
homeModules."dev-tools"
homeModules.podman
homeModules.gemini
];
};
flake.modules.homeManager."server-user-base" = {
imports = [ homeModules."common-user-base" ];
};
flake.modules.homeManager."workstation-user-base" = {
imports = [
homeModules."common-user-base"
homeModules."ssh-client"
homeModules."sops-admin"
];
};
}
+29
View File
@@ -0,0 +1,29 @@
{ config, ... }:
let
nixosModules = config.flake.modules.nixos;
in
{
flake.modules.nixos.workstation-base = {
imports = [
nixosModules.host-base
nixosModules.sops-admin-key-file
nixosModules.standard-boot
nixosModules.sddm
nixosModules.niri
nixosModules.audio
nixosModules.bluetooth
nixosModules.flatpak
nixosModules.fonts
nixosModules.networking
nixosModules.printing
nixosModules.qbittorrent-client
];
users.mutableUsers = false;
services.dbus.implementation = "broker";
programs.nix-ld.enable = true;
environment.localBinInPath = true;
};
}
+18 -8
View File
@@ -1,10 +1,15 @@
{ config, ... }:
{
inputs,
config,
...
}:
let
nixosModules = config.flake.modules.nixos;
homeModules = config.flake.modules.homeManager;
metaLib = config.meta.lib;
in
{
flake.modules.nixos."orion-admin" =
flake.modules.nixos.orion-admin =
{ pkgs, ... }:
{
users.users.kiri = {
@@ -21,22 +26,27 @@ in
flake.modules.nixos.orion = metaLib.mkHost {
name = "orion";
kind = "server";
users = {
inherit (metaLib.users) kiri;
};
imports = [
nixosModules."server-base"
nixosModules.host-base
nixosModules.sops-host-ssh-key
nixosModules.openssh
nixosModules.caddy
nixosModules."server-firewall"
nixosModules."ssh-agent-auth"
nixosModules."orion-admin"
nixosModules.server-firewall
nixosModules.ssh-agent-auth
nixosModules.orion-admin
nixosModules.vaultwarden
nixosModules.radicale
nixosModules.actual
nixosModules.gitea
nixosModules."user-kiri"
(metaLib.mkHostUser {
account = metaLib.users.kiri;
needsPassword = false;
homeImports = [ homeModules.kiri-server ];
})
./_hardware.nix
./_disk.nix
];
+18 -4
View File
@@ -5,12 +5,12 @@
}:
let
nixosModules = config.flake.modules.nixos;
homeModules = config.flake.modules.homeManager;
metaLib = config.meta.lib;
in
{
flake.modules.nixos.polaris = metaLib.mkHost {
name = "polaris";
kind = "workstation";
displays = {
"LG Electronics LG ULTRAGEAR 103NTYT8R290" = {
@@ -33,10 +33,24 @@ in
};
imports = [
nixosModules."workstation-base"
nixosModules.workstation-base
nixosModules.steam
nixosModules."user-kiri"
nixosModules."user-ergon"
(metaLib.mkHostUser {
account = metaLib.users.kiri;
needsPassword = true;
homeImports = [
homeModules.kiri-workstation
homeModules.noctalia
];
})
(metaLib.mkHostUser {
account = metaLib.users.ergon;
needsPassword = true;
homeImports = [
homeModules.ergon-workstation
homeModules.noctalia
];
})
./_hardware.nix
]
++ (with inputs.nixos-hardware.nixosModules; [
+22 -6
View File
@@ -5,13 +5,12 @@
}:
let
nixosModules = config.flake.modules.nixos;
homeModules = config.flake.modules.homeManager;
metaLib = config.meta.lib;
in
{
flake.modules.nixos.zenith = metaLib.mkHost {
name = "zenith";
kind = "workstation";
traits = [ "portable" ];
displays = {
"California Institute of Technology 0x1410 Unknown" = {
@@ -35,10 +34,27 @@ in
};
imports = [
nixosModules."workstation-base"
nixosModules."portable-host"
nixosModules."user-kiri"
nixosModules."user-ergon"
nixosModules.workstation-base
(metaLib.mkHostUser {
account = metaLib.users.kiri;
needsPassword = true;
homeImports = [
homeModules.kiri-workstation
homeModules.noctalia-portable
];
})
(metaLib.mkHostUser {
account = metaLib.users.ergon;
needsPassword = true;
homeImports = [
homeModules.ergon-workstation
homeModules.noctalia-portable
];
})
{
hardware.enableRedistributableFirmware = true;
services.fwupd.enable = true;
}
./_hardware.nix
inputs.nixos-hardware.nixosModules.lenovo-yoga-7-14ARH7-amdgpu
];
+69 -7
View File
@@ -7,8 +7,6 @@ let
mkHost =
{
name,
kind,
traits ? [ ],
displays ? { },
users ? { },
imports ? [ ],
@@ -18,9 +16,7 @@ let
meta.host = {
inherit
displays
kind
name
traits
users
;
};
@@ -52,11 +48,69 @@ let
"reverse_proxy :${toString port}"
else
''
reverse_proxy :${toString port} {
${body}
}
reverse_proxy :${toString port} {
${body}
}
'';
};
mkHostUser =
{
account,
homeImports,
needsPassword ? false,
stateVersion ? "24.05",
}:
{
config,
pkgs,
...
}:
let
name = account.name;
primaryEmails = lib.filter (email: email.primary) (builtins.attrValues account.emails);
in
{
assertions = [
{
assertion = builtins.length primaryEmails == 1;
message = "User ${name} must define exactly one primary email entry.";
}
];
programs.zsh.enable = true;
sops.secrets = lib.optionalAttrs needsPassword {
"hashed-password-${name}".neededForUsers = true;
};
users.users.${name} = {
name = account.name;
home = account.homeDirectory;
isNormalUser = true;
shell = pkgs.zsh;
extraGroups = [
"wheel"
"networkmanager"
];
}
// lib.optionalAttrs needsPassword {
hashedPasswordFile = config.sops.secrets."hashed-password-${name}".path;
};
home-manager.users.${name} = {
imports = homeImports;
meta = {
host = config.meta.host;
user = account;
};
home = {
username = account.name;
homeDirectory = account.homeDirectory;
inherit stateVersion;
};
};
};
in
{
options.meta.lib.mkHost = lib.mkOption {
@@ -73,6 +127,13 @@ in
readOnly = true;
};
options.meta.lib.mkHostUser = lib.mkOption {
type = lib.types.raw;
description = "Internal helper for explicit per-host user assembly.";
internal = true;
readOnly = true;
};
options.meta.lib.users = lib.mkOption {
type = lib.types.attrs;
description = "Canonical user attrsets shared by host definitions.";
@@ -84,6 +145,7 @@ in
inherit
mkCaddyReverseProxy
mkHost
mkHostUser
;
};
}
+20 -21
View File
@@ -1,43 +1,42 @@
{
inputs,
config,
...
}:
let
nixosModules = config.flake.modules.nixos;
sopsAdminKeyPath = "/var/lib/sops/keys.txt";
in
{
flake.modules.nixos."sops-host" =
{
config,
lib,
...
}:
flake.modules.nixos.sops = {
imports = [ inputs.sops-nix.nixosModules.sops ];
sops.defaultSopsFile = ./secrets.yaml;
};
flake.modules.nixos.sops-admin-key-file =
{ lib, ... }:
let
useHostSshKey = config.meta.host.kind == "server";
useAdminKeyFile = config.meta.host.kind != "server";
adminKeyDir = builtins.dirOf sopsAdminKeyPath;
in
{
imports = [ inputs.sops-nix.nixosModules.sops ];
imports = [ nixosModules.sops ];
sops = {
defaultSopsFile = ./secrets.yaml;
age =
lib.optionalAttrs useHostSshKey {
sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
}
// lib.optionalAttrs useAdminKeyFile {
keyFile = sopsAdminKeyPath;
};
};
sops.age.keyFile = sopsAdminKeyPath;
systemd.tmpfiles.rules = lib.optionals useAdminKeyFile [
systemd.tmpfiles.rules = [
"d ${adminKeyDir} 0750 root wheel -"
"z ${sopsAdminKeyPath} 0640 root wheel -"
];
};
flake.modules.homeManager."sops-admin" =
flake.modules.nixos.sops-host-ssh-key = {
imports = [ nixosModules.sops ];
sops.age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
};
flake.modules.homeManager.sops =
{
pkgs,
...
+1 -105
View File
@@ -1,11 +1,5 @@
{
config,
lib,
...
}:
{ ... }:
let
homeModules = config.flake.modules.homeManager;
kiri = {
name = "kiri";
realName = "Jelle Spreeuwenberg";
@@ -46,98 +40,6 @@ let
};
};
};
mkUserModules =
{
name,
extraHomeImports ? [ ],
}:
let
userModuleName = "user-${name}";
workstationModuleName = "${name}-workstation";
in
{
nixos =
{
config,
pkgs,
...
}:
let
account = config.meta.host.users.${name};
primaryEmails = lib.filter (email: email.primary) (builtins.attrValues account.emails);
isWorkstation = config.meta.host.kind == "workstation";
hasWorkstationModule = builtins.hasAttr workstationModuleName homeModules;
baseModuleName = if isWorkstation then "workstation-user-base" else "server-user-base";
in
{
assertions = [
{
assertion = builtins.length primaryEmails == 1;
message = "User ${name} must define exactly one primary email entry.";
}
];
programs.zsh.enable = true;
sops.secrets = lib.optionalAttrs isWorkstation {
"hashed-password-${name}".neededForUsers = true;
};
users.users.${name} = {
name = account.name;
home = account.homeDirectory;
isNormalUser = true;
shell = pkgs.zsh;
extraGroups = [
"wheel"
"networkmanager"
];
}
// lib.optionalAttrs isWorkstation {
hashedPasswordFile = config.sops.secrets."hashed-password-${name}".path;
};
home-manager.users.${name} = {
imports = [
homeModules.${baseModuleName}
homeModules.${userModuleName}
]
++ extraHomeImports
++ lib.optionals (isWorkstation && hasWorkstationModule) [
homeModules.${workstationModuleName}
];
meta = {
host = config.meta.host;
user = account;
};
};
};
homeManager =
{ config, ... }:
let
account = config.meta.user;
in
{
home = {
username = account.name;
homeDirectory = account.homeDirectory;
stateVersion = "24.05";
};
};
};
kiriModules = mkUserModules {
name = "kiri";
extraHomeImports = [
homeModules.syncthing
];
};
ergonModules = mkUserModules {
name = "ergon";
};
in
{
meta.lib.users = {
@@ -146,10 +48,4 @@ in
kiri
;
};
flake.modules.nixos."user-kiri" = kiriModules.nixos;
flake.modules.nixos."user-ergon" = ergonModules.nixos;
flake.modules.homeManager."user-kiri" = kiriModules.homeManager;
flake.modules.homeManager."user-ergon" = ergonModules.homeManager;
}