Skip to content

Host<->User Mutual Providers

Mutual Configs means that not only a User contributes configuration to a Host, but also that a Host contributes configurations to a User.

Den’s resolution pipeline starts with a host definition:

den.hosts.x86_64-linux.igloo.users.tux = {}

We need to build the nixos Nix module that will later be used by lib.nixosSystem. Policies drive entity topology — the built-in host-to-users policy fans out from each host to its users:

Tip: Zoom diagrams using your mouse wheel or drag to move.

sequenceDiagram
   participant Den
   participant host as host resolution
   participant user as user resolution
   participant igloo as den.aspects.igloo
   participant tux as den.aspects.tux

   Den  ->>  host  :  {host = igloo}

   host ->> igloo : request nixos class
   igloo -->> igloo : each .includes takes { host }
   igloo -->> host : { nixos = ... } owned and parametric results

   host ->> user : policy fans out for each user: { host, user }

   user ->> tux : request nixos class
   tux -->> tux : home classes forwarded as nixos class
   tux -->> tux : each .includes takes { host, user }
   tux -->> user : { nixos = ... } owned and parametric results

   user -->> host : { nixos = ... } all user contributions

   host -->> Den : complete nixos module for lib.nixosSystem

This is the normal host resolution pipeline. All OS contributions come from the host itself and from each of its users.

To define mutual configurations, declare named aspects under an aspect’s provides namespace. Each provides.<target> key creates an explicit relationship between a user and a host:

  • provides.<name> delivers to the host or user named <name>.
  • provides.to-hosts delivers to every host the user lives on.
  • provides.to-users delivers to every user on the host.
# user aspect provides to a specific host or to all hosts where it lives
den.aspects.tux = {
provides.igloo.nixos.programs.emacs.enable = true;
provides.to-hosts = { host, ... }: {
nixos.programs.nh.enable = host.name == "igloo";
};
};
# host aspect provides to a specific user or to all its users
den.aspects.igloo = {
provides.alice.homeManager.programs.vim.enable = true;
provides.to-users = { user, ... }: {
homeManager.programs.helix.enable = user.name == "alice";
};
};

Tip: Zoom diagrams using your mouse wheel or drag to move.

sequenceDiagram
   participant Den
   participant host as host resolution
   participant user as user resolution
   participant igloo as den.aspects.igloo
   participant igloo-users as den.aspects.igloo.to-users
   participant igloo-tux as den.aspects.igloo.tux
   participant tux as den.aspects.tux
   participant tux-hosts as den.aspects.tux.to-hosts
   participant tux-igloo as den.aspects.tux.igloo

   Den  ->>  host  :  {host = igloo}

   host ->> igloo : request nixos class
   igloo -->> igloo : each .includes takes { host }
   igloo -->> host : { nixos = ... } owned and parametric results

   host ->> user : policy fans out for each user: { host, user }

   user ->> tux : request nixos class
   tux -->> tux : home classes forwarded as nixos class
   tux -->> tux : each .includes takes { host, user }
   tux -->> user : { nixos = ... } owned and parametric results

   user ->> igloo-users : host configs its users: { host, user }
   igloo-users -->> igloo-users : home classes forwarded as nixos class
   igloo-users -->> igloo-users : each .includes takes { host, user }
   igloo-users -->> user : { nixos = ... }

   user ->> igloo-tux : host configs tux: { host, user }
   igloo-tux -->> igloo-tux : home classes forwarded as nixos class
   igloo-tux -->> igloo-tux : each .includes takes { host, user }
   igloo-tux -->> user : { nixos = ... }

   user ->> tux-hosts : user configs its hosts: { host, user }
   tux-hosts -->> tux-hosts : home classes forwarded as nixos class
   tux-hosts -->> tux-hosts : each .includes takes { host, user }
   tux-hosts -->> user : { nixos = ... }

   user ->> tux-igloo : user configs igloo: { host, user }
   tux-igloo -->> tux-igloo : home classes forwarded as nixos class
   tux-igloo -->> tux-igloo : each .includes takes { host, user }
   tux-igloo -->> user : { nixos = ... }


   user -->> host : { nixos = ... } all user contributions

   host -->> Den : complete nixos module for lib.nixosSystem

A provides key registered on a user aspect is subtree-scoped: it reaches that user (and the hosts it lives on), but never sibling users on the same host. To configure several users — or to select per-user — register the provides on the host aspect, whose subtree spans every user on it:

den.aspects.igloo = {
# all users except tux get vim
provides.to-users = { user, ... }: {
homeManager.programs.vim.enable = user.name != "tux";
};
# only alice gets tmux
provides.alice.homeManager.programs.tmux.enable = true;
};

Standalone HomeManager - Host Specific Configuration

Section titled “Standalone HomeManager - Host Specific Configuration”

If you have two standalone homes sharing same user aspect, you can provide host specific configuration even if the Host is not a NixOS system managed by you.

den.homes.x86_64-linux."tux@igloo" = {};
den.homes.x86_64-linux."tux@iceberg" = {};
den.aspects.tux = {
homeManager.programs.vim.enable = true; # tux on ALL homes and hosts.
provides.igloo = {
homeManager.programs.helix.enable = true; # ONLY at igloo
};
provides.iceberg = {
homeManager.programs.emacs.enable = true; # ONLY at iceberg
};
};
Contribute Community Sponsor