Skip to content

Getting Started

  • Nix with flakes enabled
Terminal window
nix flake init -t github:vic/nest#fleet-demo

This gives you a complete multi-environment example. To understand it from first principles, read on.

  1. Add nest to your flake inputs

    flake.nix
    inputs.nest.url = "github:vic/nest";
  2. Define a host entity trait

    The host trait is an entity trait — it has a class that produces a nixosSystem:

    nest.trait.host.class.nixos =
    select: cfg:
    nixpkgs.lib.nixosSystem {
    system = select.node.system;
    modules = [ cfg ];
    };

    select.node is the matched node (the host). cfg is the merged NixOS config from all matching rules.

  3. Declare a node in the DOM

    nest.prod.system = "x86_64-linux";
    nest.prod.web = {
    is = [ nest.host ];
    system = "x86_64-linux";
    };

    nest.prod.web declares a node named web with trait host. The prod namespace passes system down, but the node also declares it explicitly here.

  4. Write a rule

    nest.rules = [
    {
    is = nest.host;
    nixos = {
    networking.hostName = "web";
    nix.settings.experimental-features = [ "nix-command" "flakes" ];
    };
    }
    ];

    Every node matching nest.host gets these NixOS options.

  5. Access the output

    Nest produces nixosConfigurations by routing byClass.nixos to the standard flake output:

    flake.nixosConfigurations = config.flake.nest.evalResult.byClass.nixos;

    nixosConfigurations.web is a ready nixosSystem.

Nest’s evaluation for the web node:

  1. is = [nest.host] — one trait, no dependencies to expand
  2. No neededBy rules match
  3. No synth defined
  4. Rule { is = nest.host; nixos = … } matches — __mergedCfg.nixos = { networking.hostName = "web"; … }
  5. No children to collect from
  6. classFns.nixos select cfg = nixosSystem { system = "x86_64-linux"; modules = [cfg]; } — done

Now add nginx and ssh via a server trait:

nest.trait.nginx = { };
nest.trait.ssh = { };
nest.trait.server.needs = [ nest.nginx nest.ssh ];
nest.trait.web.needs = [ nest.server ];
nest.prod.web = {
is = [ nest.host nest.web ];
system = "x86_64-linux";
};
nest.rules = [
{ is = nest.host; nixos.networking.hostName = "web"; }
{ is = nest.nginx; nixos.services.nginx.enable = true; }
{ is = nest.ssh; nixos.services.openssh.enable = true; }
];

The web node now has is = [host, web, server, nginx, ssh] after expansion. The nginx and ssh rules fire automatically — you never listed them on the node.

Access other nodes from within a rule function:

nest.rules = [
{
is = nest.host;
nixos = { select, host, ... }:
{
networking.hostName = host.name;
};
}
];

The host argument is the matched node. select gives access to siblings, children, ancestors, and filtered queries.

Contribute Community Sponsor