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 den,
3 lib,
4 config,
5 inputs,
6 ...
7}:
8let
9 # extends den.schema.host with MicroVM specific options
10 extendHostSchema =
11 { host, ... }:
12 {
13 options.microvm.module = lib.mkOption {
14 description = "MicroVM microvm.nix module";
15 type = lib.types.deferredModule;
16 default = inputs.microvm."${host.class}Modules".microvm;
17 };
18
19 options.microvm.hostModule = lib.mkOption {
20 description = "MicroVM host.nix module";
21 type = lib.types.deferredModule;
22 default = inputs.microvm."${host.class}Modules".host;
23 };
24
25 # Declarative Guest VMs built with Host.
26 options.microvm.guests = lib.mkOption {
27 type = lib.types.listOf lib.types.raw;
28 default = [ ];
29 description = ''
30 Guest MicroVMs.
31 Value is a list of Den hosts: [ den.hosts.x86_64-linux.foo-microvm ]
32
33 When non empty, Host imports <microvm>/host.nix module
34 and starts our Den microvm-host context pipeline.
35
36 See: https://microvm-nix.github.io/microvm.nix/host.html
37 https://microvm-nix.github.io/microvm.nix/declarative.html
38 '';
39 };
40
41 options.microvm.sharedNixStore = lib.mkEnableOption "Auto share nix store from host";
42 config.microvm.sharedNixStore = lib.mkDefault true;
43 };
44
45 # transition a NixOS host into a MicroVM host (only if it has guest microvms)
46 ctx.host.into.microvm-host = { host }: lib.optional (host.microvm.guests != [ ]) { inherit host; };
47
48 # aspect configuring a MicroVM host. imports the microvm host.nix module.
49 ctx.microvm-host.provides.microvm-host =
50 { host }:
51 {
52 ${host.class}.imports = [ host.microvm.hostModule ];
53 };
54
55 # transition from microvm host into each microvm guest
56 ctx.microvm-host.into.microvm-guest = { host }: map (vm: { inherit host vm; }) host.microvm.guests;
57
58 # aspect configuring a guest vm at the host level (Declarative in MicroVM parlance)
59 # See: https://microvm-nix.github.io/microvm.nix/declarative.html
60 ctx.microvm-host.provides.microvm-guest =
61 { host, vm }:
62 {
63 includes =
64 let
65 sharedNixStore = lib.optionalAttrs host.microvm.sharedNixStore {
66 ${host.class}.microvm.vms.${vm.name}.config.microvm.shares = [
67 {
68 source = "/nix/store";
69 mountPoint = "/nix/.ro-store";
70 tag = "ro-store";
71 proto = "virtiofs";
72 }
73 ];
74 };
75
76 # forwards guest nixos configuration into host: microvm.vms.<vm-name>.config
77 osFwd = den.provides.forward {
78 each = lib.singleton true;
79 fromClass = _: vm.class;
80 intoClass = _: host.class;
81 intoPath = _: [
82 "microvm"
83 "vms"
84 vm.name
85 "config"
86 ];
87 # calling host-pipeline ensure all Den features supported on guest
88 fromAspect = _: den.ctx.host { host = vm; };
89 };
90
91 # forwards guest microvm class into host: microvm.vms.<vm-name>
92 microvmClass = den.provides.forward {
93 each = lib.singleton true;
94 fromClass = _: "microvm";
95 intoClass = _: host.class;
96 intoPath = _: [
97 "microvm"
98 "vms"
99 vm.name
100 ];
101 fromAspect = _: den.aspects.${vm.aspect};
102 };
103
104 in
105 [
106 sharedNixStore
107 osFwd
108 microvmClass
109 ];
110 };
111
112in
113{
114 den.ctx = ctx;
115 den.schema.host.imports = [ extendHostSchema ];
116}