Compare commits

...
Sign in to create a new pull request.

8 commits

Author SHA1 Message Date
d1e661df5d nixosConfiguration: preSwitchCkeck: nvd 2025-11-26 19:51:13 +01:00
01106110fe automatically import ${namespace}.${class(es)} as modules
Allow to specify a list of classes in the host/<hostname>.nix (by
default the class <hostname> is used) that will automatically load
specified outputs of inputs.
2025-11-26 14:12:19 +01:00
d281a23a8a run nix format on this repository 2025-11-26 14:03:13 +01:00
1b5b697dfb nix fmt: automatically expose the default nix formatter 2025-11-26 14:02:30 +01:00
72f2a2ddc0 remove inputs
We actually do not depend on any input here. Only if a
nixosConfiguration should be instantiated, but it is already
expected that the user will provide a (more up-to-date) nixpkgs
flake that we use.
2025-11-26 13:58:56 +01:00
f3f83a56ab bump version 2025-11-26 10:50:10 +01:00
a5dc014e65 make home-manager optional
As the home-manager depends on the actual used nixpkgs version
and is not always used, remove it from the base dependencies but
use still use it implictely if a home-manager input exists.
2025-11-26 03:01:08 +01:00
7585be3dac bump version 2025-11-22 05:01:53 +01:00
19 changed files with 380 additions and 211 deletions

View file

@ -1,3 +1,6 @@
{ ... }@flake: { ... }@inputs: { ... }@imports: { { ... }@flake:
imports = builtins.attrValues (flake.hmModules or {}); { ... }@inputs:
{ ... }@imports:
{
imports = builtins.attrValues (flake.hmModules or { });
} }

View file

@ -1,4 +1,8 @@
flake: { ... }@inputs: { ... }@imports: let flake:
{ ... }@inputs:
{ ... }@imports:
let
module' = name: imports: builtins.trace "user module: ${name}" { inherit imports; }; module' = name: imports: builtins.trace "user module: ${name}" { inherit imports; };
modules = builtins.mapAttrs module' imports."user/module"; modules = builtins.mapAttrs module' imports."user/module";
in { default = module' "default" (builtins.attrValues modules); } // modules in
{ default = module' "default" (builtins.attrValues modules); } // modules

View file

@ -1,4 +1,7 @@
{ ... }@flake: { ... }@inputs: { profile, ... }@imports: let { ... }@flake:
{ ... }@inputs:
{ profile, ... }@imports:
let
profile' = name: snippets: builtins.trace "home-manager: profile: ${name}" { imports = snippets; }; profile' = name: snippets: builtins.trace "home-manager: profile: ${name}" { imports = snippets; };
in builtins.mapAttrs profile' profile in
builtins.mapAttrs profile' profile

View file

@ -1,15 +1,30 @@
{ nixosUsers ? {}, nixosGroups ? {}, nixosModules, hmModules ? { default = {}; }, ...}@flake: { ... }@inputs: { host, ... }@imports: let {
host' = name: snippets: let nixosUsers ? { },
nixosGroups ? { },
nixosModules,
hmModules ? {
default = { };
},
...
}@flake:
{ ... }@inputs:
{ host, ... }@imports:
let
host' =
name: snippets:
let
overlay = self: super: { overlay = self: super: {
makeModulesClosure = x: super.makeModulesClosure (x // { allowMissing = true; }); makeModulesClosure = x: super.makeModulesClosure (x // { allowMissing = true; });
}; };
common = { modulesPath, lib, ... }: { common =
{ modulesPath, lib, ... }:
{
config.nixpkgs.overlays = [ overlay ]; config.nixpkgs.overlays = [ overlay ];
config.networking.hostName = lib.mkForce name; config.networking.hostName = lib.mkForce name;
config.home-manager = { config.home-manager = {
sharedModules = [ hmModules.default ] ; sharedModules = [ hmModules.default ];
}; };
imports = [ imports = [
@ -21,12 +36,15 @@
system = inputs.nixpkgs.lib.nixosSystem { system = inputs.nixpkgs.lib.nixosSystem {
specialArgs = { inherit inputs flake; }; specialArgs = { inherit inputs flake; };
modules = [ common ] modules = [
common
]
++ snippets ++ snippets
++ builtins.attrValues nixosUsers ++ builtins.attrValues nixosUsers
++ builtins.attrValues nixosGroups ++ builtins.attrValues nixosGroups;
;
}; };
in system.config.system.build.isoImage; in
system.config.system.build.isoImage;
in builtins.mapAttrs host' host in
builtins.mapAttrs host' host

View file

@ -1,19 +1,67 @@
{ nixosUsers ? {}, nixosGroups ? {}, nixosModules, hmModules ? { default = {}; }, ...}@flake: { ... }@inputs: { host, ... }@imports: let {
host' = name: snippets: let nixosUsers ? { },
system = { namespace?"fbs42", nixpkgs?"nixpkgs" }: inputs.${nixpkgs}.lib.nixosSystem { nixosGroups ? { },
specialArgs = { inherit inputs flake namespace; }; nixosModules,
modules = builtins.concatLists (map (base: builtins.attrValues (flake.lib.scan { base = "${base}/host/${name}"; })) flake.lib.schema.base) hmModules ? {
++ [ { config.networking.hostName = name; } ] default = { };
++ [ nixosModules.default ] },
++ [ inputs.home-manager.nixosModules.default ] ...
++ [ { config.home-manager.sharedModules = [ hmModules.default ]; } ] }@flake:
++ [ { config.home-manager.extraSpecialArgs = { inherit flake namespace; }; } ] { ... }@inputs:
++ builtins.attrValues nixosUsers { host, ... }@imports:
++ builtins.attrValues nixosGroups let
; pre-switch-check =
{ pkgs, lib, config, ... }:
{
config.system.preSwitchChecks.nvd = ''
nvd_check=y
if [[ -d /run/current-system ]]
then
${lib.getExe pkgs.nvd} --nix-bin-dir ${config.nix.package}/bin diff /run/current-system "''${1}"
if [[ -t 0 ]]; then
printf 'really %s to %s? [y]es/[N]o ' "''${2}" "''${1}"
read -r nvd_check
fi
fi
[[ "''${nvd_check}" == y ]]
'';
}; };
cfg = assert builtins.length snippets == 1; builtins.head snippets; system =
in system cfg; hostname:
{
namespace ? "fbs42",
nixpkgs ? "nixpkgs",
classes ? [ hostname ],
}:
inputs.${nixpkgs}.lib.nixosSystem {
specialArgs = { inherit inputs flake namespace; };
modules =
builtins.concatLists (
map (
base: builtins.attrValues (flake.lib.scan { base = "${base}/host/${hostname}"; })
) flake.lib.schema.base
)
++ map (class: {
imports = map (input: input.${namespace}.${class} or { }) (builtins.attrValues inputs);
}) classes
++ [ pre-switch-check ]
++ [ { config.networking.hostName = hostname; } ]
++ [ nixosModules.default ]
++ inputs.${nixpkgs}.lib.optional (inputs ? home-manager) {
imports = [ inputs.home-manager.nixosModules.default ];
config.home-manager = {
sharedModules = [ hmModules.default ];
extraSpecialArgs = { inherit flake namespace; };
};
}
++ builtins.attrValues nixosUsers
++ builtins.attrValues nixosGroups;
};
in builtins.mapAttrs host' host in
builtins.mapAttrs (
name: value:
assert builtins.length value == 1;
system name (builtins.head value)
) host

View file

@ -1,10 +1,25 @@
flake: { ... }@inputs: { group, ... }@imports: let flake:
group' = name: snippets: { pkgs, lib, options, config, ... }@args: let { ... }@inputs:
{ group, ... }@imports:
let
group' =
name: snippets:
{
pkgs,
lib,
options,
config,
...
}@args:
let
invoke = x: if builtins.isFunction x then x args else x; invoke = x: if builtins.isFunction x then x args else x;
in { in
{
options.fbs42.group.${name} = lib.mkEnableOption name; options.fbs42.group.${name} = lib.mkEnableOption name;
config.users.groups.${name} = lib.mkIf config.users.groups.${name} = lib.mkIf (
(config.fbs42.group.${name} || builtins.any (usr: usr.group == name) (builtins.attrValues config.users.users)) config.fbs42.group.${name}
(lib.mkMerge (map invoke snippets)); || builtins.any (usr: usr.group == name) (builtins.attrValues config.users.users)
) (lib.mkMerge (map invoke snippets));
}; };
in builtins.mapAttrs group' group in
builtins.mapAttrs group' group

View file

@ -1,3 +1,14 @@
flake: { ... }@inputs: { module, ... }@imports: let flake:
modules = builtins.mapAttrs (name: imports: builtins.trace "module: ${name}" { inherit imports; }) module; { ... }@inputs:
in { default = { imports = builtins.attrValues modules; }; } // modules { module, ... }@imports:
let
modules = builtins.mapAttrs (
name: imports: builtins.trace "module: ${name}" { inherit imports; }
) module;
in
{
default = {
imports = builtins.attrValues modules;
};
}
// modules

View file

@ -1,2 +1,4 @@
{ ... }@flake: { ... }@inputs: { profile, ... }@imports: { ... }@flake:
builtins.mapAttrs (name: imports: builtins.trace "profile: ${name}" { inherit imports; }) profile { ... }@inputs:
{ profile, ... }@imports:
builtins.mapAttrs (name: imports: builtins.trace "profile: ${name}" { inherit imports; }) profile

View file

@ -1,5 +1,15 @@
self: { ... }@inputs: { user, ... }@imports: let self:
user' = name: snippets: { pkgs, lib, config, ... }@args: { ... }@inputs:
{ user, ... }@imports:
let
user' =
name: snippets:
{
pkgs,
lib,
config,
...
}@args:
builtins.trace "user: ${name}" { builtins.trace "user: ${name}" {
options.fbs42.user.${name} = lib.mkEnableOption name; options.fbs42.user.${name} = lib.mkEnableOption name;
## no longer with nixos-24.11 ## no longer with nixos-24.11
@ -7,11 +17,15 @@ self: { ... }@inputs: { user, ... }@imports: let
# group = lib.mkDefault name; # group = lib.mkDefault name;
#}; #};
imports = map ({ user, home-manager}: { imports = map (
{ user, home-manager }:
{
config = lib.mkIf config.fbs42.user.${name} { config = lib.mkIf config.fbs42.user.${name} {
users.users.${name} = (user args); users.users.${name} = (user args);
home-manager.users.${name} = home-manager; home-manager.users.${name} = home-manager;
}; };
}) snippets; }
) snippets;
}; };
in builtins.mapAttrs user' user in
builtins.mapAttrs user' user

View file

@ -1,15 +1,30 @@
{ nixosUsers ? {}, nixosGroups ? {}, nixosModules, hmModules ? { default = {}; }, ...}@flake: { ... }@inputs: { host, ... }@imports: let {
host' = name: snippets: let nixosUsers ? { },
nixosGroups ? { },
nixosModules,
hmModules ? {
default = { };
},
...
}@flake:
{ ... }@inputs:
{ host, ... }@imports:
let
host' =
name: snippets:
let
overlay = self: super: { overlay = self: super: {
makeModulesClosure = x: super.makeModulesClosure (x // { allowMissing = true; }); makeModulesClosure = x: super.makeModulesClosure (x // { allowMissing = true; });
}; };
common = { modulesPath, lib, ... }: { common =
{ modulesPath, lib, ... }:
{
config.nixpkgs.overlays = [ overlay ]; config.nixpkgs.overlays = [ overlay ];
config.networking.hostName = lib.mkForce name; config.networking.hostName = lib.mkForce name;
config.home-manager = { config.home-manager = {
sharedModules = [ hmModules.default ] ; sharedModules = [ hmModules.default ];
}; };
imports = [ imports = [
@ -23,12 +38,15 @@
system = inputs.nixpkgs.lib.nixosSystem { system = inputs.nixpkgs.lib.nixosSystem {
specialArgs = { inherit inputs flake; }; specialArgs = { inherit inputs flake; };
modules = [ common ] modules = [
common
]
++ snippets ++ snippets
++ builtins.attrValues nixosUsers ++ builtins.attrValues nixosUsers
++ builtins.attrValues nixosGroups ++ builtins.attrValues nixosGroups;
;
}; };
in system.config.system.build.sdImage; in
system.config.system.build.sdImage;
in builtins.mapAttrs host' host in
builtins.mapAttrs host' host

46
flake.lock generated
View file

@ -1,61 +1,23 @@
{ {
"nodes": { "nodes": {
"hardware": {
"locked": {
"lastModified": 1753122741,
"narHash": "sha256-nFxE8lk9JvGelxClCmwuJYftbHqwnc01dRN4DVLUroM=",
"owner": "nixos",
"repo": "nixos-hardware",
"rev": "cc66fddc6cb04ab479a1bb062f4d4da27c936a22",
"type": "github"
},
"original": {
"owner": "nixos",
"repo": "nixos-hardware",
"type": "github"
}
},
"home-manager": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1747688870,
"narHash": "sha256-ypL9WAZfmJr5V70jEVzqGjjQzF0uCkz+AFQF7n9NmNc=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "d5f1f641b289553927b3801580598d200a501863",
"type": "github"
},
"original": {
"owner": "nix-community",
"ref": "release-24.11",
"repo": "home-manager",
"type": "github"
}
},
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1751274312, "lastModified": 1763966396,
"narHash": "sha256-/bVBlRpECLVzjV19t5KMdMFWSwKLtb5RyXdjz3LJT+g=", "narHash": "sha256-6eeL1YPcY1MV3DDStIDIdy/zZCDKgHdkCmsrLJFiZf0=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "50ab793786d9de88ee30ec4e4c24fb4236fc2674", "rev": "5ae3b07d8d6527c42f17c876e404993199144b6a",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "nixos", "owner": "nixos",
"ref": "nixos-24.11", "ref": "nixos-unstable",
"repo": "nixpkgs", "repo": "nixpkgs",
"type": "github" "type": "github"
} }
}, },
"root": { "root": {
"inputs": { "inputs": {
"hardware": "hardware",
"home-manager": "home-manager",
"nixpkgs": "nixpkgs" "nixpkgs": "nixpkgs"
} }
} }

View file

@ -1,12 +1,6 @@
{ {
inputs = { # only used for nixfmt-tree
nixpkgs.url = "github:nixos/nixpkgs/nixos-24.11"; inputs.nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
hardware.url = "github:nixos/nixos-hardware";
home-manager = {
url = "github:nix-community/home-manager/release-24.11";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = { self, ... }@inputs: import ./lib/flake.nix inputs ./.; outputs = { self, ... }@inputs: import ./lib/flake.nix inputs ./.;
} }

View file

@ -1 +1 @@
{} { }

View file

@ -1,21 +1,34 @@
let let
function = name: value: let function =
result = if builtins.isAttrs value then {...}: value else value; name: value:
let
result = if builtins.isAttrs value then { ... }: value else value;
result' = builtins.trace "result ${name}=${builtins.typeOf result}" result; result' = builtins.trace "result ${name}=${builtins.typeOf result}" result;
in in
assert builtins.isFunction result'; assert builtins.isFunction result';
result; result;
config = { user?{}, home-manager?{} }@set: config =
{
user ? { },
home-manager ? { },
}@set:
builtins.mapAttrs function { inherit user home-manager; }; builtins.mapAttrs function { inherit user home-manager; };
in name: value: let in
result = if builtins.isFunction value name: value:
then let
result =
if builtins.isFunction value then
config { user = value; } config { user = value; }
else if builtins.any (attr: builtins.hasAttr attr value) [ "user" "home-manager" ] else if
builtins.any (attr: builtins.hasAttr attr value) [
"user"
"home-manager"
]
then then
config value config value
else else
config { user = value; }; config { user = value; };
in result in
result

View file

@ -1,2 +1 @@
name: profile: profile name: profile: profile

View file

@ -1,34 +1,81 @@
let let
scan = import ./scan.nix; scan = import ./scan.nix;
flake' = self: { imports, exports , base }@schema: { ... }@inputs: { ... }@imports: let flake' =
self:
{
imports,
exports,
base,
}@schema:
{ ... }@inputs:
{ ... }@imports:
let
lib = { lib = {
inherit scan schema inputs imports; inherit
scan
schema
inputs
imports
;
extend = flake schema inputs imports; extend = flake schema inputs imports;
new = flake {} {} {}; new = flake { } { } { };
# TODO: override # TODO: override
}; };
convert = attr: value: value self inputs imports; convert = attr: value: value self inputs imports;
result = (builtins.mapAttrs convert schema.exports); result = (builtins.mapAttrs convert schema.exports);
in result // { lib = lib // (result.lib or {}); }; in
{
flake = { imports?{}, exports?{}, base?[] }@schema'old: { ... }@inputs'old: { ... }@imports'old: { ... }@inputs'new: base: let formatter = builtins.mapAttrs (_: pkgs: pkgs.nixfmt-tree) inputs.nixpkgs.legacyPackages;
schema = { }
imports = (schema'old.imports or {}) // scan { base = base + "/import"; recursive = true; }; // result
exports = (schema'old.exports or {}) // scan { base = base + "/export"; }; // {
base = [ base ] ++ (schema'old.base or []); lib = lib // (result.lib or { });
}; };
merge = attr: let flake =
old = imports'old.${attr} or {}; {
new = imports'new.${attr} or {}; imports ? { },
in builtins.mapAttrs (attr: _: (old.${attr} or []) ++ (new.${attr} or [])) (old//new); exports ? { },
base ? [ ],
}@schema'old:
{ ... }@inputs'old:
{ ... }@imports'old:
{ ... }@inputs'new:
base:
let
schema = {
imports =
(schema'old.imports or { })
// scan {
base = base + "/import";
recursive = true;
};
exports = (schema'old.exports or { }) // scan { base = base + "/export"; };
base = [ base ] ++ (schema'old.base or [ ]);
};
imports'new = builtins.mapAttrs (name: value: scan { base = base + "/${name}"; convert = name: content: [ (value name content) ]; }) schema.imports; merge =
result = flake' result schema attr:
(inputs'old // (builtins.removeAttrs inputs'new ["self"])) let
(builtins.mapAttrs (attr: _: merge attr) schema.imports); old = imports'old.${attr} or { };
in result; new = imports'new.${attr} or { };
in
builtins.mapAttrs (attr: _: (old.${attr} or [ ]) ++ (new.${attr} or [ ])) (old // new);
in flake {} {} {} imports'new = builtins.mapAttrs (
name: value:
scan {
base = base + "/${name}";
convert = name: content: [ (value name content) ];
}
) schema.imports;
result = flake' result schema (inputs'old // (builtins.removeAttrs inputs'new [ "self" ])) (
builtins.mapAttrs (attr: _: merge attr) schema.imports
);
in
result;
in
flake { } { } { }

View file

@ -1 +0,0 @@
self:

View file

@ -1,23 +1,42 @@
{ base, convert ? name: value: value, recursive ? false }: {
base,
convert ? name: value: value,
recursive ? false,
}:
let let
scan = sub: let scan =
sub:
let
all = builtins.readDir (base + "/${builtins.concatStringsSep "/" sub}"); all = builtins.readDir (base + "/${builtins.concatStringsSep "/" sub}");
names = filter: builtins.filter filter (builtins.attrNames all); names = filter: builtins.filter filter (builtins.attrNames all);
nix = name: all.${name} == "regular" && builtins.stringLength name > 4 && builtins.substring (builtins.stringLength name - 4) 4 name == ".nix"; nix =
name:
all.${name} == "regular"
&& builtins.stringLength name > 4
&& builtins.substring (builtins.stringLength name - 4) 4 name == ".nix";
dir = name: all.${name} == "directory"; dir = name: all.${name} == "directory";
files = map (name: sub ++ [ (builtins.substring 0 (builtins.stringLength name - 4) name) ]) (names nix); files = map (name: sub ++ [ (builtins.substring 0 (builtins.stringLength name - 4) name) ]) (
dirs = builtins.concatLists (map (name: scan (sub ++ [name])) (names dir)); names nix
in if recursive then files ++ dirs else files; );
dirs = builtins.concatLists (map (name: scan (sub ++ [ name ])) (names dir));
in
if recursive then files ++ dirs else files;
root = scan []; root = scan [ ];
item = relative: let item =
relative:
let
name = builtins.concatStringsSep "/" relative; name = builtins.concatStringsSep "/" relative;
absolute = base + "/${name}.nix"; absolute = base + "/${name}.nix";
content = import absolute; content = import absolute;
value = convert name content; value = convert name content;
in { inherit name value; }; in
{
inherit name value;
};
items = map item root; items = map item root;
in if builtins.pathExists base then builtins.listToAttrs (map item root) else {} in
if builtins.pathExists base then builtins.listToAttrs (map item root) else { }

View file

@ -1 +1 @@
{} { }