flakeModule
Nest ships a flakeModule for flake-parts. It wires nest.* module options, evaluates the DOM pipeline, and routes outputs to flake attributes.
Adding nest to your flake
Section titled “Adding nest to your flake”{ inputs = { nest.url = "github:vic/nest"; flake-parts.url = "github:hercules-ci/flake-parts"; nixpkgs.url = "…"; };
outputs = inputs: inputs.flake-parts.lib.mkFlake { inherit inputs; } { imports = [ inputs.nest.flakeModules.default ]; # … your modules };}Module options
Section titled “Module options”nest.* (freeform)
Section titled “nest.* (freeform)”Everything under nest.* except nest.trait and nest.rules is the DOM. You write your topology here:
nest.prod.system = "x86_64-linux";nest.prod.web = { is = [ nest.host ]; addr = "10.0.0.2"; };nest.trait.*
Section titled “nest.trait.*”Trait definitions. Each key under nest.trait becomes a trait in the processed trait tree:
nest.trait.host.class.nixos = select: cfg: nixpkgs.lib.nixosSystem { … };nest.trait.server.needs = [ nest.nginx nest.ssh ];nest.trait.monitoring.neededBy = nest.server;nest.rules
Section titled “nest.rules”The rules list. Type: listOf raw (preserves functionArgs metadata for callWithArgs):
nest.rules = [ { is = nest.host; nixos = { host, ... }: { networking.hostName = host.name; }; }];The nest module arg
Section titled “The nest module arg”flakeModule passes the processed trait tree + selector constructors as _module.args.nest:
nest = processedTraits // mkSelectorsThis makes all traits and selectors available as nest.host, nest.web, nest.attrs { … }, etc. in any module.
config.flake.nest
Section titled “config.flake.nest”After evaluation, config.flake.nest exposes:
config.flake.nest.evalResult.byClass # keyed by className → { nodeName → output }config.flake.nest.evalResult.outputs # same but flat: { nodeName → output }config.flake.nest.nestCfg # raw nest.* optionsconfig.flake.nest.processedTraits # injectNames resultconfig.flake.nest.lib # nest internals (evalNest, etc.)Routing outputs
Section titled “Routing outputs”byClass maps class names to output attrsets. Route them to flake outputs:
# nixosConfigurationsflake.nixosConfigurations = config.flake.nest.evalResult.byClass.nixos or { };
# homeConfigurationsflake.homeConfigurations = config.flake.nest.evalResult.byClass.homeManager or { };
# darwinConfigurationsflake.darwinConfigurations = config.flake.nest.evalResult.byClass.darwin or { };
# Custom output class (e.g., "terranix")flake.terranix = config.flake.nest.evalResult.byClass.terranix or { };Complete minimal flake
Section titled “Complete minimal flake”{ description = "Minimal Nest flake";
inputs = { nest.url = "github:vic/nest"; flake-parts.url = "github:hercules-ci/flake-parts"; nixpkgs.url = "https://channels.nixos.org/nixpkgs-unstable/nixexprs.tar.xz"; };
outputs = inputs: inputs.flake-parts.lib.mkFlake { inherit inputs; } ({ config, ... }: { imports = [ inputs.nest.flakeModules.default ];
# Route byClass.nixos to nixosConfigurations options.flake.nixosConfigurations = inputs.nixpkgs.lib.mkOption { }; config.flake.nixosConfigurations = config.flake.nest.evalResult.byClass.nixos or { };
# Entity trait nest.trait.host.class.nixos = select: cfg: inputs.nixpkgs.lib.nixosSystem { system = select.node.system; modules = [ cfg ]; };
# DOM nest.prod.system = "x86_64-linux"; nest.prod.web = { is = [ nest.host ]; };
# Rules nest.rules = [ { is = nest.host; nixos.networking.hostName = "web"; } ]; });}Without flake-parts
Section titled “Without flake-parts”You can use Nest without flake-parts by calling evalNest directly:
outputs = inputs: let nestLib = import inputs.nest; result = nestLib.evalNest { trait = { host.class.nixos = select: cfg: nixpkgs.lib.nixosSystem { … }; }; prod.web = { is = [ nestLib.processedTraits.host ]; }; rules = [ { is = nestLib.processedTraits.host; nixos.networking.hostName = "web"; } ]; }; in { nixosConfigurations = result.byClass.nixos; };Or use the default.nix template which wraps evalModules without flake-parts.
Output class naming
Section titled “Output class naming”The class name is determined by the entity trait’s class key name:
nest.trait.host.class.nixos = …; # className = "nixos"nest.trait.home.class.homeManager = …; # className = "homeManager"nest.trait.server.class.terranix = …; # className = "terranix"processNode uses firstMatch — the first non-null class fn result wins, and its key name becomes the className for routing.