1
Fork 0
mirror of https://github.com/RGBCube/hjem synced 2025-10-31 13:42:44 +00:00
hjem/modules/nixos/default.nix
NotAShelf 0e3eb7d2fd
modules: platform-independent module
Drops excessve reliance on Nixpkgs modules inside the module options, and prepares for further platform support.
2024-12-28 02:46:10 +03:00

112 lines
3.2 KiB
Nix

{
config,
pkgs,
lib,
...
}: let
inherit (lib.modules) mkIf mkMerge;
inherit (lib.options) mkOption;
inherit (lib.lists) filter map flatten concatLists;
inherit (lib.attrsets) filterAttrs mapAttrs' attrValues mapAttrsToList;
inherit (lib.trivial) flip;
inherit (lib.types) bool attrsOf submoduleWith listOf raw;
hjemModule = submoduleWith {
description = "Hjem NixOS module";
class = "hjem";
specialArgs = {inherit pkgs lib;};
modules = concatLists [
[
({name, ...}: {
imports = [../common.nix];
config = {
user = config.users.users.${name}.name;
directory = config.users.users.${name}.home;
};
})
]
# Evaluate additional modules under 'hjem.users.<name>' so that
# module systems built on Hjem are more ergonomic.
cfg.extraModules
];
};
cfg = config.hjem;
in {
imports = [
# This should be removed in the future, since 'homes' is a very vague
# namespace to occupy. Added 2024-12-27, remove 2025-01-27 to allow
# sufficient time to migrate.
(lib.mkRenamedOptionModule ["homes"] ["hjem" "users"])
];
options.hjem = {
clobberByDefault = mkOption {
type = bool;
default = false;
description = ''
The default override behaviour for files managed by Hjem.
While `true`, existing files will be overriden with new
files on rebuild.
'';
};
users = mkOption {
default = {};
type = attrsOf hjemModule;
description = "Home configurations to be managed";
};
extraModules = mkOption {
type = listOf raw;
default = [];
description = ''
Additional modules to be evaluated as a part of the users module
inside {option}`config.hjem.users.<name>`. This can be used to
extend each user configuration with additional options.
'';
};
};
config = mkMerge [
{
users.users = mapAttrs' (name: {packages, ...}: {
inherit name;
value.packages = packages;
}) (filterAttrs (_: u: u.packages != []) cfg.users);
systemd.user.tmpfiles.users = mapAttrs' (name: {files, ...}: {
inherit name;
value.rules = map (
file: let
# L+ will recreate, i.e., clobber existing files.
mode =
if file.clobber
then "L+"
else "L";
in
# Constructed rule string that consists of the type, target, and source
# of a tmpfile. Files with 'null' sources are filtered before the rule
# is constructed.
"${mode} '${file.target}' - - - - ${file.source}"
) (filter (f: f.enable && f.source != null) (attrValues files));
}) (filterAttrs (_: u: u.files != {}) cfg.users);
}
(mkIf (cfg.users != {}) {
warnings = flatten (flip mapAttrsToList cfg.users (user: config:
flip map config.warnings (
warning: "${user} profile: ${warning}"
)));
assertions = flatten (flip mapAttrsToList cfg.users (user: config:
flip map config.assertions (assertion: {
inherit (assertion) assertion;
message = "${user} profile: ${assertion.message}";
})));
})
];
}