Modular, context-aware and aspect-oriented dendritic Nix configurations.
Discussions: https://oeiuwq.zulipchat.com/join/nqp26cd4kngon6mo3ncgnuap/
den.oeiuwq.com
configurations
den
dendritic
nix
aspect
oriented
1{
2 inputs,
3 lib,
4 den,
5 ...
6}:
7let
8 hostsOption = lib.mkOption {
9 description = "den hosts definition";
10 default = { };
11 type = lib.types.attrsOf systemType;
12 };
13
14 systemType = lib.types.submodule (
15 { name, ... }:
16 {
17 freeformType = lib.types.attrsOf (hostType name);
18 }
19 );
20
21 hostType =
22 system:
23 lib.types.submodule (
24 { name, config, ... }:
25 {
26 freeformType = lib.types.attrsOf lib.types.anything;
27 imports = [ den.schema.host ];
28 config._module.args.host = config;
29 options = {
30 name = strOpt "host configuration name" name;
31 hostName = strOpt "Network hostname" config.name;
32 system = strOpt "platform system" system;
33 class = strOpt "os-configuration nix class for host" (
34 if lib.hasSuffix "darwin" config.system then "darwin" else "nixos"
35 );
36 aspect = strOpt "main aspect name of <class>" config.name;
37 description = strOpt "host description" "${config.class}.${config.hostName}@${config.system}";
38 users = lib.mkOption {
39 description = "user accounts";
40 default = { };
41 type = lib.types.attrsOf userType;
42 };
43 instantiate = lib.mkOption {
44 description = ''
45 Function used to instantiate the OS configuration.
46
47 Depending on class, defaults to:
48 `darwin`: inputs.darwin.lib.darwinSystem
49 `nixos`: inputs.nixpkgs.lib.nixosSystem
50 `systemManager`: inputs.system-manager.lib.makeSystemConfig
51
52 Set explicitly if you need:
53
54 - a custom input name, eg, nixos-unstable.
55 - adding specialArgs when absolutely required.
56 '';
57 example = lib.literalExpression "inputs.nixpkgs.lib.nixosSystem";
58 type = lib.types.raw;
59 default =
60 {
61 nixos = inputs.nixpkgs.lib.nixosSystem;
62 darwin = inputs.darwin.lib.darwinSystem;
63 systemManager = inputs.system-manager.lib.makeSystemConfig;
64 }
65 .${config.class};
66 };
67 intoAttr = lib.mkOption {
68 description = ''
69 Flake attr where to add the named result of this configuration.
70 flake.<intoAttr>.<name>
71
72 Depending on class, defaults to:
73 `darwin`: darwinConfigurations
74 `nixos`: nixosConfigurations
75 `systemManager`: systemConfigs
76 '';
77 example = lib.literalExpression ''[ "nixosConfigurations" hostName ]'';
78 type = lib.types.listOf lib.types.str;
79 default =
80 {
81 nixos = [
82 "nixosConfigurations"
83 config.name
84 ];
85 darwin = [
86 "darwinConfigurations"
87 config.name
88 ];
89 systemManager = [
90 "systemConfigs"
91 config.name
92 ];
93 }
94 .${config.class};
95 };
96 mainModule = lib.mkOption {
97 internal = true;
98 visible = false;
99 readOnly = true;
100 type = lib.types.deferredModule;
101 default = mainModule config den.ctx.host "host";
102 };
103 };
104 }
105 );
106
107 userType = lib.types.submodule (
108 { name, config, ... }:
109 {
110 freeformType = lib.types.attrsOf lib.types.anything;
111 imports = [ den.schema.user ];
112 config._module.args.user = config;
113 options = {
114 name = strOpt "user configuration name" name;
115 userName = strOpt "user account name" config.name;
116 classes = lib.mkOption {
117 type = lib.types.listOf lib.types.str;
118 description = "home management nix classes";
119 default = [ "user" ];
120 };
121 aspect = strOpt "main aspect name" config.name;
122 };
123 }
124 );
125
126 strOpt =
127 description: default:
128 lib.mkOption {
129 type = lib.types.str;
130 inherit description default;
131 };
132
133 homesOption = lib.mkOption {
134 description = "den standalone home-manager configurations";
135 default = { };
136 type = lib.types.attrsOf homeSystemType;
137 };
138
139 homeSystemType = lib.types.submodule (
140 { name, ... }:
141 {
142 freeformType = lib.types.attrsOf (homeType name);
143 }
144 );
145
146 homeType =
147 system:
148 lib.types.submodule (
149 { name, config, ... }:
150 {
151 freeformType = lib.types.attrsOf lib.types.anything;
152 imports = [ den.schema.home ];
153 config._module.args.home = config;
154 options = {
155 name = strOpt "home configuration name" name;
156 userName = strOpt "user account name" config.name;
157 system = strOpt "platform system" system;
158 class = strOpt "home management nix class" "homeManager";
159 aspect = strOpt "main aspect name" config.name;
160 description = strOpt "home description" "home.${config.userName}@${config.system}";
161 pkgs = lib.mkOption {
162 description = ''
163 nixpkgs instance used to build the home configuration.
164 '';
165 example = lib.literalExpression ''inputs.nixpkgs.legacyPackages.''${home.system}'';
166 type = lib.types.raw;
167 default = inputs.nixpkgs.legacyPackages.${config.system};
168 };
169 instantiate = lib.mkOption {
170 description = ''
171 Function used to instantiate the home configuration.
172
173 Depending on class, defaults to:
174 `homeManager`: inputs.home-manager.lib.homeManagerConfiguration
175
176 Set explicitly if you need:
177
178 - a custom input name, eg, home-manager-unstable.
179 - adding extraSpecialArgs when absolutely required.
180 '';
181 example = lib.literalExpression "inputs.home-manager.lib.homeManagerConfiguration";
182 type = lib.types.raw;
183 default =
184 {
185 homeManager = inputs.home-manager.lib.homeManagerConfiguration;
186 }
187 .${config.class};
188 };
189 intoAttr = lib.mkOption {
190 description = ''
191 Flake attr where to add the named result of this configuration.
192 flake.<intoAttr>.<name>
193
194 Depending on class, defaults to:
195 `homeManager`: homeConfigurations
196 '';
197 example = lib.literalExpression ''[ "homeConfigurations" userName ]'';
198 type = lib.types.listOf lib.types.str;
199 default =
200 {
201 homeManager = [
202 "homeConfigurations"
203 config.name
204 ];
205 }
206 .${config.class};
207 };
208 mainModule = lib.mkOption {
209 internal = true;
210 visible = false;
211 readOnly = true;
212 type = lib.types.deferredModule;
213 default = mainModule config den.ctx.home "home";
214 };
215 };
216 }
217 );
218
219 mainModule =
220 from: intent: name:
221 let
222 asp = intent { ${name} = from; };
223 in
224 den.lib.aspects.resolve (from.class) [ ] asp;
225in
226{
227 inherit hostsOption homesOption;
228}