feat: move to single-user config

This commit is contained in:
2026-04-26 18:08:48 +02:00
parent 75ba00929e
commit dba24ce5f3
27 changed files with 160 additions and 300 deletions
+8 -7
View File
@@ -35,18 +35,19 @@ In this repo, `flake.nix` imports `./modules` recursively via `inputs.import-tre
- `modules/hosts/<name>/default.nix`: host features that assemble NixOS aspects into `flake.modules.nixos.<name>`. - `modules/hosts/<name>/default.nix`: host features that assemble NixOS aspects into `flake.modules.nixos.<name>`.
- `modules/secrets/`: secret-related features shared by hosts. - `modules/secrets/`: secret-related features shared by hosts.
- `modules/flake-parts.nix`: flake-parts entrypoint; defines systems, formatter, and `flake.nixosConfigurations`. - `modules/flake-parts.nix`: flake-parts entrypoint; defines systems, formatter, and `flake.nixosConfigurations`.
- `modules/lib.nix`: shared constructors and helpers in `config.meta.lib`, especially `mkHost` and `mkCaddyReverseProxy`. - `modules/lib/`: shared schemas, constructors, and helpers exposed through `repo.helpers`, especially `mkHost` and `mkCaddyReverseProxy`.
- `modules/data.nix`: canonical shared repo data and account attrsets exposed through `meta.lib.repo` and `meta.lib.accounts`. - `modules/data.nix`: canonical shared repo data, including the single `repo.account`, machine inventory, desktop preferences, services, and theme data.
- `modules/features/meta.nix`: shared metadata schema for `meta.host` and `meta.user`. - `modules/lib/schema.nix`: shared metadata schema for `repo.*` and NixOS `meta.machine`.
## How Features Are Applied Here ## How Features Are Applied Here
- Reusable NixOS concerns are published as `flake.modules.nixos.<name>`. - Reusable NixOS concerns are published as `flake.modules.nixos.<name>`.
- Reusable Home Manager concerns are published as `flake.modules.homeManager.<name>`. - Reusable Home Manager concerns are published as `flake.modules.homeManager.<name>`.
- Hosts are aspects too. `orion`, `polaris`, and `zenith` are `nixos` aspects assembled from smaller aspects. - Hosts are aspects too. `orion`, `polaris`, and `zenith` are `nixos` aspects assembled from smaller aspects.
- Host modules should use `config.meta.lib.mkHost` to define `meta.host`, base imports, hostname, and state version. - `flake.nixosConfigurations` instantiates every entry in `repo.machines` with `config.repo.helpers.mkHost`.
- Per-host user declarations should stay inline under `users.<name>` using canonical accounts from `meta.lib.accounts`, so host-local defaults stay close to the host and `mkHost` can wire `meta.host` and `meta.user` into Home Manager consistently. - Hosts define machine data under `repo.machines.<name>` and host-specific NixOS composition under `flake.modules.nixos.<name>`.
- Features may rely on the `meta` contract. Existing modules already read `config.meta.host`, `config.meta.user`, and `config.meta.lib`. - `mkHost` wires the single `repo.account` into `users.users.<name>` and `home-manager.users.<name>`.
- NixOS modules may read `config.meta.machine`; Home Manager modules should read host facts through `osConfig.meta.machine` and user facts through `config.home` or `repo.account`.
## Preferred Aspect Patterns ## Preferred Aspect Patterns
@@ -68,6 +69,6 @@ Use **Collector Aspect** only when composition through imports or shared library
## Practical Heuristics ## Practical Heuristics
- If you are about to edit a host because of a reusable concern, that concern probably wants its own feature. - If you are about to edit a host because of a reusable concern, that concern probably wants its own feature.
- If a Home Manager module needs host or user facts, prefer reading `config.meta.host` or `config.meta.user` instead of duplicating literals. - If a Home Manager module needs host facts, prefer `osConfig.meta.machine`; for user facts, prefer `config.home` or `repo.account` instead of duplicating literals.
- If a concern spans system and user space, keep both aspects in one feature so the behavior stays coherent. - If a concern spans system and user space, keep both aspects in one feature so the behavior stays coherent.
- If imports would need to be conditional, redesign the aspect boundary instead. - If imports would need to be conditional, redesign the aspect boundary instead.
+28 -1
View File
@@ -1,6 +1,33 @@
{ {
repo = { repo = {
contact.email = "mail@jelles.net"; account = {
name = "kiri";
realName = "Jelle Spreeuwenberg";
sourceControl.projectScope = "work";
emails = {
personal = {
address = "mail@jelles.net";
primary = true;
scope = "personal";
type = "mxrouting";
};
old = {
address = "mail@jellespreeuwenberg.nl";
scope = null;
type = "mxrouting";
};
uni = {
address = "j.spreeuwenberg@student.tue.nl";
scope = null;
type = "office365";
};
work = {
address = "jelle.spreeuwenberg@yookr.org";
scope = "work";
type = "office365";
};
};
};
desktop = { desktop = {
browser = { browser = {
+3 -2
View File
@@ -1,4 +1,5 @@
{ {
homeDirectory,
lib, lib,
terminalPackage, terminalPackage,
}: }:
@@ -102,7 +103,7 @@
screenOverrides = [ ]; screenOverrides = [ ];
}; };
general = { general = {
avatarImage = "/home/kiri/.face"; avatarImage = "${homeDirectory}/.face";
dimmerOpacity = 0; dimmerOpacity = 0;
showScreenCorners = false; showScreenCorners = false;
forceBlackScreenCorners = false; forceBlackScreenCorners = false;
@@ -213,7 +214,7 @@
wallpaper = { wallpaper = {
enabled = true; enabled = true;
overviewEnabled = false; overviewEnabled = false;
directory = "/home/kiri/media/images/wallpapers"; directory = "${homeDirectory}/media/images/wallpapers";
monitorDirectories = [ ]; monitorDirectories = [ ];
enableMultiMonitorDirectories = false; enableMultiMonitorDirectories = false;
showHiddenFiles = false; showHiddenFiles = false;
+4 -15
View File
@@ -1,23 +1,12 @@
{ inputs, ... }: { inputs, config, ... }:
let let
account = config.repo.account;
sharedContext = '' sharedContext = ''
# Global Agent Context # Global Agent Context
Be a concise technical thought partner. Check the premise before executing, optimize for the user's actual outcome, and make important assumptions or tradeoffs visible. Be a concise technical thought partner. Check the premise before executing, optimize for the user's actual outcome, and make important assumptions or tradeoffs visible.
## Workflow
- Respect mode words literally: "read-only", "debug", "investigate", or "do not change code" means no edits; "plan" means produce a decision-complete plan; "implement" means make the smallest useful patch and verify it.
- Ask only when the answer cannot be discovered locally and a wrong assumption would materially change the result. Otherwise state the assumption and continue.
- Keep responses dense. Lead with the answer, cause, patch result, or recommendation. Avoid long preambles and generic reassurance.
## Code Changes
- Preserve user work. Never revert or overwrite unrelated changes; read dirty files before editing them.
- Prefer simple, ergonomic code that matches the existing project style. Avoid future-proofing and new abstractions unless the current problem clearly pays for them.
- Before editing, understand the local architecture, dependency manager, formatter, and test commands. After editing, run the narrowest meaningful verification and report what ran.
- Do not install dependencies globally or mutate system configuration unless explicitly asked.
## Machine Environment ## Machine Environment
- This machine is Nix/NixOS-based. Standard Linux assumptions may be wrong: software is usually provided by flakes, dev shells, `devenv`, `direnv`, or the user's NixOS/Home Manager config rather than `apt`, `dnf`, or global installs. - This machine is Nix/NixOS-based. Standard Linux assumptions may be wrong: software is usually provided by flakes, dev shells, `devenv`, `direnv`, or the user's NixOS/Home Manager config rather than `apt`, `dnf`, or global installs.
@@ -93,7 +82,7 @@ in
"context-remaining" "context-remaining"
"five-hour-limit" "five-hour-limit"
]; ];
projects.${config.meta.user.account.nixosConfigurationPath}.trust_level = "trusted"; projects.${account.nixosConfigurationPath}.trust_level = "trusted";
sandbox_mode = "workspace-write"; sandbox_mode = "workspace-write";
personality = "pragmatic"; personality = "pragmatic";
features.undo = true; features.undo = true;
+1 -3
View File
@@ -4,6 +4,7 @@
}: }:
let let
repo = config.repo; repo = config.repo;
account = repo.account;
in in
{ {
flake.modules.homeManager.bitwarden = flake.modules.homeManager.bitwarden =
@@ -12,9 +13,6 @@ in
pkgs, pkgs,
... ...
}: }:
let
account = config.meta.user.account;
in
{ {
programs.rbw = { programs.rbw = {
enable = true; enable = true;
+4 -2
View File
@@ -1,4 +1,7 @@
{ ... }: { config, ... }:
let
account = config.repo.account;
in
{ {
flake.modules.homeManager.email = flake.modules.homeManager.email =
{ {
@@ -7,7 +10,6 @@
... ...
}: }:
let let
account = config.meta.user.account;
mkOffice365Account = mkOffice365Account =
{ {
address, address,
+4 -4
View File
@@ -1,13 +1,13 @@
{ ... }: { config, ... }:
let
account = config.repo.account;
in
{ {
flake.modules.homeManager.git = flake.modules.homeManager.git =
{ {
config, config,
... ...
}: }:
let
account = config.meta.user.account;
in
{ {
programs.git = { programs.git = {
enable = true; enable = true;
-2
View File
@@ -5,7 +5,6 @@
}: }:
let let
nixosModules = config.flake.modules.nixos; nixosModules = config.flake.modules.nixos;
homeModules = config.flake.modules.homeManager;
in in
{ {
flake.modules.nixos.host-base = { flake.modules.nixos.host-base = {
@@ -21,7 +20,6 @@ in
useGlobalPkgs = true; useGlobalPkgs = true;
backupFileExtension = "bak"; backupFileExtension = "bak";
extraSpecialArgs = { inherit inputs; }; extraSpecialArgs = { inherit inputs; };
sharedModules = [ homeModules.meta ];
}; };
security.sudo.extraConfig = '' security.sudo.extraConfig = ''
+4 -2
View File
@@ -1,5 +1,6 @@
{ config, ... }: { config, ... }:
let let
account = config.repo.account;
repoTheme = config.repo.theme.kanagawa; repoTheme = config.repo.theme.kanagawa;
in in
{ {
@@ -8,6 +9,7 @@ in
pkgs, pkgs,
config, config,
inputs, inputs,
osConfig,
... ...
}: }:
{ {
@@ -152,8 +154,8 @@ in
# Hostname/ConfigDir needed for nixd # Hostname/ConfigDir needed for nixd
nixdExtras = { nixdExtras = {
nixpkgs = "import ${pkgs.path} {}"; nixpkgs = "import ${pkgs.path} {}";
nixos_options = ''(builtins.getFlake "path://${config.meta.user.account.nixosConfigurationPath}").nixosConfigurations.${config.meta.machine.name}.options''; nixos_options = ''(builtins.getFlake "path://${account.nixosConfigurationPath}").nixosConfigurations.${osConfig.meta.machine.name}.options'';
home_manager_options = ''(builtins.getFlake "path://${config.meta.user.account.nixosConfigurationPath}").nixosConfigurations.${config.meta.machine.name}.options.home-manager.users.type.getSubOptions []''; home_manager_options = ''(builtins.getFlake "path://${account.nixosConfigurationPath}").nixosConfigurations.${osConfig.meta.machine.name}.options.home-manager.users.type.getSubOptions []'';
}; };
themeSetup = import ./_kanagawa-theme.nix { themeSetup = import ./_kanagawa-theme.nix {
+6 -2
View File
@@ -1,10 +1,14 @@
{ config, ... }:
let
account = config.repo.account;
in
{ {
flake.modules.homeManager.nh = flake.modules.homeManager.nh =
{ config, ... }: { ... }:
{ {
programs.nh = { programs.nh = {
enable = true; enable = true;
flake = config.meta.user.account.nixosConfigurationPath; flake = account.nixosConfigurationPath;
}; };
}; };
} }
+2 -1
View File
@@ -27,6 +27,7 @@ in
{ {
config, config,
lib, lib,
osConfig,
pkgs, pkgs,
... ...
}: }:
@@ -64,7 +65,7 @@ in
; ;
}; };
} }
) config.meta.machine.displays; ) osConfig.meta.machine.displays;
in in
{ {
assertions = [ assertions = [
+17 -29
View File
@@ -9,11 +9,13 @@ let
mkNoctaliaSettings = mkNoctaliaSettings =
{ {
homeDirectory,
lib, lib,
terminalPackage, terminalPackage,
}: }:
import ./_noctalia-config.nix { import ./_noctalia-config.nix {
inherit inherit
homeDirectory
lib lib
terminalPackage terminalPackage
; ;
@@ -21,6 +23,7 @@ let
mkBaseSettings = mkBaseSettings =
{ {
homeDirectory,
lib, lib,
pkgs, pkgs,
}: }:
@@ -34,7 +37,11 @@ let
{ } { }
else else
mkNoctaliaSettings { mkNoctaliaSettings {
inherit lib terminalPackage; inherit
homeDirectory
lib
terminalPackage
;
}; };
mkPortableSettings = mkPortableSettings =
@@ -62,15 +69,23 @@ in
{ {
flake.modules.homeManager.noctalia = flake.modules.homeManager.noctalia =
{ {
config,
inputs, inputs,
lib, lib,
osConfig,
pkgs, pkgs,
... ...
}: }:
let let
baseSettings = mkBaseSettings { baseSettings = mkBaseSettings {
inherit lib pkgs; inherit lib pkgs;
homeDirectory = config.home.homeDirectory;
}; };
settings =
if baseSettings == { } || !osConfig.meta.machine.portable then
baseSettings
else
mkPortableSettings baseSettings;
in in
{ {
imports = [ inputs.noctalia.homeModules.default ]; imports = [ inputs.noctalia.homeModules.default ];
@@ -82,34 +97,7 @@ in
calendarSupport = true; calendarSupport = true;
} }
); );
inherit settings;
settings = baseSettings;
};
};
flake.modules.homeManager.noctalia-portable =
{
inputs,
lib,
pkgs,
...
}:
let
baseSettings = mkBaseSettings {
inherit lib pkgs;
};
in
{
imports = [ inputs.noctalia.homeModules.default ];
programs.noctalia-shell = {
enable = true;
package = lib.mkForce (
inputs.noctalia.packages.${pkgs.stdenv.hostPlatform.system}.default.override {
calendarSupport = true;
}
);
settings = if baseSettings == { } then { } else mkPortableSettings baseSettings;
}; };
}; };
} }
+1 -1
View File
@@ -6,7 +6,7 @@ in
flake.modules.nixos.caddy = { flake.modules.nixos.caddy = {
services.caddy = { services.caddy = {
enable = true; enable = true;
email = repo.contact.email; email = repo.account.primaryEmail.address;
openFirewall = true; openFirewall = true;
}; };
}; };
+6 -6
View File
@@ -1,4 +1,7 @@
{ ... }: { config, ... }:
let
account = config.repo.account;
in
{ {
flake.modules.nixos.ssh-agent-auth = { flake.modules.nixos.ssh-agent-auth = {
security.pam = { security.pam = {
@@ -8,10 +11,7 @@
}; };
flake.modules.nixos.openssh = flake.modules.nixos.openssh =
{ { ... }:
config,
...
}:
{ {
services.openssh.openFirewall = true; services.openssh.openFirewall = true;
@@ -20,7 +20,7 @@
settings = { settings = {
PermitRootLogin = "no"; PermitRootLogin = "no";
PasswordAuthentication = false; PasswordAuthentication = false;
AllowUsers = builtins.attrNames config.meta.machine.users; AllowUsers = [ account.name ];
}; };
}; };
}; };
+6 -10
View File
@@ -1,17 +1,13 @@
{ lib, ... }: { config, ... }:
let
account = config.repo.account;
in
{ {
flake.modules.nixos.sops-password = flake.modules.nixos.sops-password =
{ config, ... }: { config, ... }:
{ {
sops.secrets = lib.mapAttrs' ( sops.secrets.hashed-password.neededForUsers = true;
userName: _:
lib.nameValuePair "hashed-password-${userName}" {
neededForUsers = true;
}
) config.meta.machine.users;
users.users = lib.mapAttrs (userName: _: { users.users.${account.name}.hashedPasswordFile = config.sops.secrets.hashed-password.path;
hashedPasswordFile = config.sops.secrets."hashed-password-${userName}".path;
}) config.meta.machine.users;
}; };
} }
+4 -4
View File
@@ -1,5 +1,6 @@
{ config, lib, ... }: { config, lib, ... }:
let let
account = config.repo.account;
homeModules = config.flake.modules.homeManager; homeModules = config.flake.modules.homeManager;
in in
{ {
@@ -7,15 +8,14 @@ in
{ {
config, config,
lib, lib,
osConfig,
... ...
}: }:
let let
machine = config.meta.machine; machine = osConfig.meta.machine;
user = config.meta.user;
account = user.account;
sourceControl = account.sourceControl; sourceControl = account.sourceControl;
scopeConfig = scope: user.sourceControl.${scope} or null; scopeConfig = scope: machine.sourceControl.${scope} or null;
emailForScope = emailForScope =
scope: scope:
+4 -5
View File
@@ -7,19 +7,18 @@ let
syncthingMesh = lib.listToAttrs ( syncthingMesh = lib.listToAttrs (
lib.concatMap ( lib.concatMap (
machine: machine:
lib.mapAttrsToList ( lib.optional (machine.syncthingId != null) (
userName: user:
let let
name = "${userName}@${machine.name}"; name = "${config.repo.account.name}@${machine.name}";
in in
{ {
inherit name; inherit name;
value = { value = {
inherit name; inherit name;
id = user.syncthingId; id = machine.syncthingId;
}; };
} }
) (lib.filterAttrs (_: user: user.syncthingId != null) machine.users) )
) (builtins.attrValues config.repo.machines) ) (builtins.attrValues config.repo.machines)
); );
in in
+10
View File
@@ -2,10 +2,13 @@
let let
nixosModules = config.flake.modules.nixos; nixosModules = config.flake.modules.nixos;
homeModules = config.flake.modules.homeManager; homeModules = config.flake.modules.homeManager;
account = config.repo.account;
in in
{ {
flake.modules.nixos.workstation-base = { flake.modules.nixos.workstation-base = {
imports = [ imports = [
nixosModules.host-base
nixosModules.audio nixosModules.audio
nixosModules.bluetooth nixosModules.bluetooth
nixosModules.flatpak nixosModules.flatpak
@@ -27,6 +30,10 @@ in
programs.nix-ld.enable = true; programs.nix-ld.enable = true;
environment.localBinInPath = true; environment.localBinInPath = true;
home-manager.users.${account.name}.imports = [
homeModules.workstation-base
];
}; };
flake.modules.homeManager.workstation-base = { flake.modules.homeManager.workstation-base = {
@@ -44,14 +51,17 @@ in
homeModules.nix homeModules.nix
homeModules.pim homeModules.pim
homeModules.podman homeModules.podman
homeModules.qbittorrent-client
homeModules.shell homeModules.shell
homeModules.sops homeModules.sops
homeModules.source-control homeModules.source-control
homeModules.ssh-client homeModules.ssh-client
homeModules.syncthing
homeModules.terminal homeModules.terminal
homeModules.theme homeModules.theme
homeModules.vicinae homeModules.vicinae
homeModules.xdg homeModules.xdg
homeModules.noctalia
]; ];
}; };
} }
+1 -1
View File
@@ -15,7 +15,7 @@
_: machine: _: machine:
inputs.nixpkgs.lib.nixosSystem { inputs.nixpkgs.lib.nixosSystem {
specialArgs = { inherit inputs; }; specialArgs = { inherit inputs; };
modules = [ (machine.buildFunction machine) ]; modules = [ (config.repo.helpers.mkHost machine) ];
} }
) config.repo.machines; ) config.repo.machines;
+4 -8
View File
@@ -5,17 +5,11 @@
}: }:
let let
nixosModules = config.flake.modules.nixos; nixosModules = config.flake.modules.nixos;
accounts = config.repo.accounts; account = config.repo.account;
in in
{ {
repo.machines.orion = { repo.machines.orion = {
buildFunction = config.repo.helpers.mkHost;
module = nixosModules.orion;
users.kiri = {
account = accounts.kiri;
syncthingId = "NNRNQKZ-OWPHSVA-B6KKBHE-SDYLSTV-7SVHGPR-NEWLKPL-4MWNJG4-G5FHUAI"; syncthingId = "NNRNQKZ-OWPHSVA-B6KKBHE-SDYLSTV-7SVHGPR-NEWLKPL-4MWNJG4-G5FHUAI";
};
stateVersion = "24.05"; stateVersion = "24.05";
hmStateVersion = "24.05"; hmStateVersion = "24.05";
@@ -25,6 +19,8 @@ in
{ ... }: { ... }:
{ {
imports = [ imports = [
nixosModules.host-base
nixosModules.sops-host-ssh-key nixosModules.sops-host-ssh-key
nixosModules.openssh nixosModules.openssh
nixosModules.caddy nixosModules.caddy
@@ -38,7 +34,7 @@ in
./_disk.nix ./_disk.nix
]; ];
users.users.kiri = { users.users.${account.name} = {
linger = true; linger = true;
openssh.authorizedKeys.keys = [ openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAU2LydkXRTtNFY7oyX8JQURwXLVhB71DeK8XzrXeFX1 openpgp:0xA490D93A" "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAU2LydkXRTtNFY7oyX8JQURwXLVhB71DeK8XzrXeFX1 openpgp:0xA490D93A"
+3 -16
View File
@@ -5,22 +5,13 @@
}: }:
let let
nixosModules = config.flake.modules.nixos; nixosModules = config.flake.modules.nixos;
homeModules = config.flake.modules.homeManager;
accounts = config.repo.accounts;
in in
{ {
repo.machines.polaris = { repo.machines.polaris = {
buildFunction = config.repo.helpers.mkWorkstationHost; sourceControl.personal.publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEVORk45HKkX7gaGGp90KsVyUy6t+fKhbWN/grjkf3cQ kiri@polaris";
module = nixosModules.polaris; sourceControl.work.publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEVORk45HKkX7gaGGp90KsVyUy6t+fKhbWN/grjkf3cQ kiri@polaris#work";
users = {
kiri = {
account = accounts.kiri;
syncthingId = "6HBAKXB-DB3B4H2-BODCAXF-KD23H5W-6X5LGLC-ZJHZHLG-7U7YMGO-BB6IXQ3"; syncthingId = "6HBAKXB-DB3B4H2-BODCAXF-KD23H5W-6X5LGLC-ZJHZHLG-7U7YMGO-BB6IXQ3";
};
ergon.account = accounts.ergon;
};
stateVersion = "24.05"; stateVersion = "24.05";
hmStateVersion = "24.05"; hmStateVersion = "24.05";
@@ -43,6 +34,7 @@ in
{ ... }: { ... }:
{ {
imports = [ imports = [
nixosModules.workstation-base
nixosModules.qbittorrent-client nixosModules.qbittorrent-client
nixosModules.steam nixosModules.steam
./_hardware.nix ./_hardware.nix
@@ -53,10 +45,5 @@ in
common-cpu-amd common-cpu-amd
common-gpu-amd common-gpu-amd
]); ]);
home-manager.users = {
kiri.imports = [ homeModules.noctalia ];
ergon.imports = [ homeModules.noctalia ];
};
}; };
} }
+4 -14
View File
@@ -5,23 +5,14 @@
}: }:
let let
nixosModules = config.flake.modules.nixos; nixosModules = config.flake.modules.nixos;
homeModules = config.flake.modules.homeManager;
accounts = config.repo.accounts;
in in
{ {
repo.machines.zenith = { repo.machines.zenith = {
buildFunction = config.repo.helpers.mkWorkstationHost; portable = true;
module = nixosModules.zenith;
users = {
kiri.account = accounts.kiri;
ergon = {
account = accounts.ergon;
sourceControl = { sourceControl = {
personal.publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPdR3KP2U84i7f7MlRqcML/3YyMw8JL3hdm637SkMUwO ergon@zenith#personal"; personal.publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEVORk45HKkX7gaGGp90KsVyUy6t+fKhbWN/grjkf3cQ kiri@polaris";
work.publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIHJz5uHKm0/TiMNh/cmzrODHNZ8NgEEZe+47XnJwQGk ergon@zenith#work"; work.publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIHJz5uHKm0/TiMNh/cmzrODHNZ8NgEEZe+47XnJwQGk kiri@zenith#work";
};
};
}; };
displays = { displays = {
@@ -42,6 +33,7 @@ in
{ ... }: { ... }:
{ {
imports = [ imports = [
nixosModules.workstation-base
nixosModules.qbittorrent-client nixosModules.qbittorrent-client
nixosModules.laptop-power nixosModules.laptop-power
{ {
@@ -51,7 +43,5 @@ in
./_hardware.nix ./_hardware.nix
inputs.nixos-hardware.nixosModules.lenovo-yoga-7-14ARH7-amdgpu inputs.nixos-hardware.nixosModules.lenovo-yoga-7-14ARH7-amdgpu
]; ];
home-manager.sharedModules = [ homeModules.noctalia-portable ];
}; };
} }
+8 -34
View File
@@ -1,7 +1,6 @@
{ lib, config, ... }: { lib, config, ... }:
let let
nixosModules = config.flake.modules.nixos; nixosModules = config.flake.modules.nixos;
hmModules = config.flake.modules.homeManager;
resolvePackagePath = resolvePackagePath =
{ {
@@ -40,6 +39,9 @@ let
mkHost = mkHost =
machine: machine:
{ pkgs, ... }: { pkgs, ... }:
let
account = config.repo.account;
in
{ {
imports = [ imports = [
nixosModules.host-base nixosModules.host-base
@@ -53,50 +55,23 @@ let
programs.zsh.enable = true; programs.zsh.enable = true;
users.users = lib.mapAttrs (_: user: { users.users.${account.name} = {
isNormalUser = true; isNormalUser = true;
home = user.account.homeDirectory; home = account.homeDirectory;
extraGroups = [ extraGroups = [
"wheel" "wheel"
"networkmanager" "networkmanager"
]; ];
shell = pkgs.zsh; shell = pkgs.zsh;
}) machine.users;
home-manager.users = lib.mapAttrs (name: user: {
imports = [ user.account.baseModule ];
meta = {
inherit machine user;
}; };
home-manager.users.${account.name} = {
home = { home = {
username = name; username = account.name;
homeDirectory = user.account.homeDirectory; homeDirectory = account.homeDirectory;
stateVersion = machine.hmStateVersion; stateVersion = machine.hmStateVersion;
}; };
}) machine.users;
}; };
mkWorkstationHost =
machine:
{ ... }:
{
imports = [
(mkHost machine)
nixosModules.workstation-base
];
users.users = lib.mapAttrs (_: _: {
extraGroups = [ "networkmanager" ];
}) machine.users;
home-manager.users = lib.mapAttrs (_: user: {
imports = [
hmModules.workstation-base
user.account.workstationModule
];
}) machine.users;
}; };
in in
{ {
@@ -110,7 +85,6 @@ in
inherit inherit
mkCaddyReverseProxy mkCaddyReverseProxy
mkHost mkHost
mkWorkstationHost
resolvePackagePath resolvePackagePath
; ;
}; };
+20 -63
View File
@@ -1,5 +1,7 @@
{ lib, ... }: { lib, config, ... }:
let let
nixosModules = config.flake.modules.nixos;
sourceControlScopeType = lib.types.enum [ sourceControlScopeType = lib.types.enum [
"personal" "personal"
"work" "work"
@@ -46,12 +48,11 @@ let
); );
accountType = lib.types.submodule ( accountType = lib.types.submodule (
{ name, config, ... }: { config, ... }:
{ {
options = { options = {
name = lib.mkOption { name = lib.mkOption {
type = lib.types.str; type = lib.types.str;
default = name;
}; };
realName = lib.mkOption { realName = lib.mkOption {
@@ -73,16 +74,6 @@ let
default = { }; default = { };
}; };
baseModule = lib.mkOption {
type = lib.types.deferredModule;
default = { };
};
workstationModule = lib.mkOption {
type = lib.types.deferredModule;
default = { };
};
sourceControl = lib.mkOption { sourceControl = lib.mkOption {
type = sourceControlAccountType; type = sourceControlAccountType;
default = { }; default = { };
@@ -160,7 +151,7 @@ let
} }
); );
sourceControlMachineUserType = lib.types.submodule ( sourceControlMachineType = lib.types.submodule (
{ ... }: { ... }:
{ {
options = { options = {
@@ -177,27 +168,6 @@ let
} }
); );
machineUserType = lib.types.submodule (
{ ... }:
{
options = {
account = lib.mkOption {
type = accountType;
};
sourceControl = lib.mkOption {
type = sourceControlMachineUserType;
default = { };
};
syncthingId = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
};
};
}
);
machineType = lib.types.submodule ( machineType = lib.types.submodule (
{ name, config, ... }: { name, config, ... }:
{ {
@@ -209,11 +179,7 @@ let
module = lib.mkOption { module = lib.mkOption {
type = lib.types.deferredModule; type = lib.types.deferredModule;
default = { }; default = nixosModules.${name};
};
buildFunction = lib.mkOption {
type = lib.types.functionTo lib.types.deferredModule;
}; };
stateVersion = lib.mkOption { stateVersion = lib.mkOption {
@@ -230,19 +196,28 @@ let
default = { }; default = { };
}; };
users = lib.mkOption { sourceControl = lib.mkOption {
type = lib.types.attrsOf machineUserType; type = sourceControlMachineType;
default = { }; default = { };
}; };
syncthingId = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
};
portable = lib.mkOption {
type = lib.types.bool;
default = false;
};
}; };
} }
); );
in in
{ {
options.repo = { options.repo = {
accounts = lib.mkOption { account = lib.mkOption {
type = lib.types.attrsOf accountType; type = accountType;
default = { };
}; };
machines = lib.mkOption { machines = lib.mkOption {
@@ -250,11 +225,6 @@ in
default = { }; default = { };
}; };
contact = lib.mkOption {
type = lib.types.raw;
default = { };
};
desktop = lib.mkOption { desktop = lib.mkOption {
type = lib.types.raw; type = lib.types.raw;
default = { }; default = { };
@@ -279,17 +249,4 @@ in
}; };
}; };
config.flake.modules.homeManager.meta =
{ ... }:
{
options.meta = {
machine = lib.mkOption {
type = machineType;
};
user = lib.mkOption {
type = machineUserType;
};
};
};
} }
+3 -4
View File
@@ -2,11 +2,10 @@ radicale-pass: ENC[AES256_GCM,data:3CpCnSibLWeZUJRBMuc=,iv:3J9x4ejcsYXCjRRGP5lOe
university-calendar-url: ENC[AES256_GCM,data:oGP1BdF3YxdRRr061LaC4HaaiPXoyZq7ZALqU+cv8wb2GgYT+jgshgx9LRjM3jsIjPXolkG5bCZi46r/rpEk3mWSskQ3YnCXcwM1BN+PPVapdtQgkRSWriAOUXPnRpaZzpMs5WaJTnkOrJJqfAoy+jGIE0Nhul/CRw5tOeRkwPbDxfA/dY9MT80ciHWHscHb1w9R,iv:1JqN80OnrIjOl4LGmk99LsJMmoT3hGjlCet6mYeRb5o=,tag:9GhVQIa1BXAEjdOxswHH/A==,type:str] university-calendar-url: ENC[AES256_GCM,data:oGP1BdF3YxdRRr061LaC4HaaiPXoyZq7ZALqU+cv8wb2GgYT+jgshgx9LRjM3jsIjPXolkG5bCZi46r/rpEk3mWSskQ3YnCXcwM1BN+PPVapdtQgkRSWriAOUXPnRpaZzpMs5WaJTnkOrJJqfAoy+jGIE0Nhul/CRw5tOeRkwPbDxfA/dY9MT80ciHWHscHb1w9R,iv:1JqN80OnrIjOl4LGmk99LsJMmoT3hGjlCet6mYeRb5o=,tag:9GhVQIa1BXAEjdOxswHH/A==,type:str]
ssh-config-orion: ENC[AES256_GCM,data:8vrbtuHCLlMDtMAfnJuf+DcWmPZwFFpyGag8l32JAFUMmWyEEEvDctNDHNahw8fiQzwN0+9atjY=,iv:UKWqjZ4D3+McASovEaE5jt4TAkmlwR26chFvWblgc1k=,tag:oZJKwLDPQEbfa4CPHn9lVQ==,type:str] ssh-config-orion: ENC[AES256_GCM,data:8vrbtuHCLlMDtMAfnJuf+DcWmPZwFFpyGag8l32JAFUMmWyEEEvDctNDHNahw8fiQzwN0+9atjY=,iv:UKWqjZ4D3+McASovEaE5jt4TAkmlwR26chFvWblgc1k=,tag:oZJKwLDPQEbfa4CPHn9lVQ==,type:str]
orion-ip: ENC[AES256_GCM,data:S6fpCWnD8dvchvrHlEo=,iv:72+oRxHUEJ7imJ+sWjGbG+TUrSqYL8hbyHl3ChwFYwA=,tag:Rj6msje87+Ve+M6kcZd4Jw==,type:str] orion-ip: ENC[AES256_GCM,data:S6fpCWnD8dvchvrHlEo=,iv:72+oRxHUEJ7imJ+sWjGbG+TUrSqYL8hbyHl3ChwFYwA=,tag:Rj6msje87+Ve+M6kcZd4Jw==,type:str]
hashed-password-kiri: ENC[AES256_GCM,data:xubN5stH4RPlHYl+Jzcu2BCepz3Hra3TxjiSspktzjgpEWrU79h3NbcPMrYC0MSjsv3oaWio/S7nBV3Tes3WBlI9EC9vq+6tyTVPynUqpB7c9CvvYSmqc9bAHOnIOBb+gP2RR6JB395UoQ==,iv:uN83RNTfCJdBDhFhywV5NbVBp4xcptqzoKVAoAnaiQk=,tag:x9yufiPdSJwBADT6QymExA==,type:str] hashed-password: ENC[AES256_GCM,data:mhYvALF/VrPMFFYEIGiML1MoRxdOI/J9akZPD+OF5drDTR4J5LBn3EejlbzP8CTCRsyoIF6tigMBxF8ZLz9W7hOVwT70Hr/yXfLWJ2lfBsf7l/SPZ+6NglKppCeQQktm4QKIHTVj7CkbRw==,iv:0RxXkb+vz/QK9dvecCZpWCWCsoPhi2F3OCt6CwUDqX4=,tag:j7QO8xUfWUnSpk4mMQUYmA==,type:str]
gemini-api-key-neovim: ENC[AES256_GCM,data:B8FeFt45FsU3aagyLDKXiwmx0mRrsw4C8RQ3EWXwZ+YfWLMvwJad,iv:1HqBD6vc07Ke/PMYXfHqFrWDGw/UMjiiBjLRN33/xHI=,tag:czcrYGbJFi41rYtIPM4qTQ==,type:str] gemini-api-key-neovim: ENC[AES256_GCM,data:B8FeFt45FsU3aagyLDKXiwmx0mRrsw4C8RQ3EWXwZ+YfWLMvwJad,iv:1HqBD6vc07Ke/PMYXfHqFrWDGw/UMjiiBjLRN33/xHI=,tag:czcrYGbJFi41rYtIPM4qTQ==,type:str]
booklore-db-pass: ENC[AES256_GCM,data:dlPGXQ24itEaBRJSJ9WOogWCdF3atFQ2ZtlLGyGq8Tin5OmSZI6lZUzSE+femBW5SBTIlKQvzHEPCs9MT5tyMIqetzGLm+mMN3FDW7si684Cuv9z9Uq5gjAZWh14KQMWYPI=,iv:oLnqu2EDFBVcBpswVRXXeF617YolPxOUx9CscHRRn/8=,tag:Si6gF1EXhcHalk11D3Exlw==,type:str] booklore-db-pass: ENC[AES256_GCM,data:dlPGXQ24itEaBRJSJ9WOogWCdF3atFQ2ZtlLGyGq8Tin5OmSZI6lZUzSE+femBW5SBTIlKQvzHEPCs9MT5tyMIqetzGLm+mMN3FDW7si684Cuv9z9Uq5gjAZWh14KQMWYPI=,iv:oLnqu2EDFBVcBpswVRXXeF617YolPxOUx9CscHRRn/8=,tag:Si6gF1EXhcHalk11D3Exlw==,type:str]
deluge-auth-file: ENC[AES256_GCM,data:uJME7CAC5OOJZLPdu9MNkg8ZDZZ64Wsytg==,iv:5l4eTSbdSKtOwjXGr7D1Teud5TON1+lcjWeI8W4bCuQ=,tag:ND8+cOUef1fwAGjmvWXEUQ==,type:str] deluge-auth-file: ENC[AES256_GCM,data:uJME7CAC5OOJZLPdu9MNkg8ZDZZ64Wsytg==,iv:5l4eTSbdSKtOwjXGr7D1Teud5TON1+lcjWeI8W4bCuQ=,tag:ND8+cOUef1fwAGjmvWXEUQ==,type:str]
hashed-password-ergon: ENC[AES256_GCM,data:ZmqrOb9dGNzZe5rJRHTImgPkNDFzNlyMLRrnz1KgUsIyh3/VsiIB/pPa98vli83FBrRFWdB/KPjEt1/V71qalTcA7seMccPiCQ==,iv:Fzkjfz+T3F18b5nqjZ986kx28HrqQaJqq8Ng419TnRA=,tag:xIenh0oOlrFog9Hon+nsDQ==,type:str]
sops: sops:
age: age:
- recipient: age122w85pqj508ukv0rd388mahecgfckmpgnsgz0zcyec37ljae2epsdnvxpl - recipient: age122w85pqj508ukv0rd388mahecgfckmpgnsgz0zcyec37ljae2epsdnvxpl
@@ -27,7 +26,7 @@ sops:
aW8vM0IwQ243TnNPdnlkeHE4bTFLR00KaJhbOxdbIUJSzn4lOt2OO1HOTNaOoiSE aW8vM0IwQ243TnNPdnlkeHE4bTFLR00KaJhbOxdbIUJSzn4lOt2OO1HOTNaOoiSE
+pKjsYZZQBdcYFPREjffEL+oiyxHwoLi95noHad9AGmygLqwboUkWg== +pKjsYZZQBdcYFPREjffEL+oiyxHwoLi95noHad9AGmygLqwboUkWg==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
lastmodified: "2026-04-17T00:35:34Z" lastmodified: "2026-04-26T15:37:24Z"
mac: ENC[AES256_GCM,data:pjtjsc9uATZo7GnauAguMwVCDnSnoZhkxAShuUrDT6/enURYp4UB9tIwPH54PAc2UpU23vgv5XJNJ2ah4nAgOse2iyfm84b0S+bOfXKCd5gQTf8beOFCOT+xrQmURMN9q/RAA47RBT7qZFu4J/b+EkNeY9lJM1rmYjcOygxXd58=,iv:2IYY0GmCQOZnwsnPHsAmC4CBjyS6e/DNTCQa3AkSTxc=,tag:ZtBvvMDqb851Tzg26p7NhQ==,type:str] mac: ENC[AES256_GCM,data:AR1PRP/zFzCoggCoUUCM5ZzIsOh0DSPJoAgkeZTaJAgFq9QbAI1cHPuk4qVPGyY7HZYDabhtvDSADbsbgkQOavct1Z/fFW6Sow1rLW3tkv1ENKv2lPiM2I8BK2olgH/blEa86vBE24jCS7qE0j2/ak69hWYH/bkKnyUrOCC/AUE=,iv:U0Q1jGlzY/WxbV3eNPtlMhVGiWXTOG9ft5j8U1ZacCQ=,tag:YpNUkifz0b6aoxv33pq1pw==,type:str]
unencrypted_suffix: _unencrypted unencrypted_suffix: _unencrypted
version: 3.12.2 version: 3.12.2
-20
View File
@@ -1,20 +0,0 @@
{ config, ... }:
{
repo.accounts.ergon = {
realName = "Jelle Spreeuwenberg";
sourceControl.projectScope = "work";
emails = {
personal = {
address = "mail@jelles.net";
scope = "personal";
type = "mxrouting";
};
work = {
address = "jelle.spreeuwenberg@yookr.org";
primary = true;
scope = "work";
type = "office365";
};
};
};
}
-39
View File
@@ -1,39 +0,0 @@
{ config, ... }:
let
hmModules = config.flake.modules.homeManager;
in
{
repo.accounts.kiri = {
realName = "Jelle Spreeuwenberg";
workstationModule = {
imports = [
hmModules.syncthing
hmModules.qbittorrent-client
];
};
emails = {
personal = {
address = "mail@jelles.net";
primary = true;
scope = "personal";
type = "mxrouting";
};
old = {
address = "mail@jellespreeuwenberg.nl";
scope = null;
type = "mxrouting";
};
uni = {
address = "j.spreeuwenberg@student.tue.nl";
scope = null;
type = "office365";
};
work = {
address = "jelle.spreeuwenberg@yookr.org";
scope = "work";
type = "office365";
};
};
};
}