···38383939### `den.provides.mutual-provider`
40404141-Allows hosts and users to contribute configuration **to each other** through `provides`:
4141+Allows hosts and users to contribute configuration **to each other** through `.provides.`:
42424343```nix
4444den.hosts.x86_64-linux.igloo.users.tux = { };
4545-den.default.includes = [ den._.mutual-provider ];
4545+den.ctx.user.includes = [ den._.mutual-provider ];
4646```
47474848-This is not the same as the built-in bidirectionality:
4949-5048```nix
5149# contributes to ALL users of this host
5252-den.aspects.my-host.homeManager = { ... }
5050+den.aspects.my-host.provides.to-users.homeManager = { ... }
53515452# contributes to ALL hosts of where my-user exist
5555-den.aspects.my-user.nixos = { ... }
5353+den.aspects.my-user.provides.to-hosts.nixos = { ... }
5654```
57555858-The difference is that this allows you to wire bidirectionality between
5959-explictly-named hosts/users pairs.
6060-6161-A user providing config TO the host:
5656+A `tux` user providing config to **specific host** `igloo`:
62576358```nix
6459den.aspects.tux = {
···6863};
6964```
70657171-A host providing config TO the user:
6666+A host providing config to **specific user** `tux`:
72677368```nix
7469den.aspects.igloo = {
-280
docs/src/content/docs/guides/bidirectional.mdx
···11----
22-title: Host<->User Bidirectionality
33-description: How to configure bidirectional behavior in Den.
44----
55-66-import { Aside } from '@astrojs/starlight/components';
77-88-<Aside title="Source" icon="github">
99-[`context/user.nix`](https://github.com/vic/den/blob/main/modules/context/user.nix) ·
1010-[`context/host.nix`](https://github.com/vic/den/blob/main/modules/context/host.nix) ·
1111-[`bidirectional.nix`](https://github.com/vic/den/blob/main/modules/aspects/provides/bidirectional.nix) ·
1212-[`mutual-provider.nix`](https://github.com/vic/den/blob/main/modules/aspects/provides/mutual-provider.nix)
1313-</Aside>
1414-1515-## What Bidirectionality Means
1616-1717-__Bidirectionality__ means that not only a User contributes
1818-configuration to a Host, but **also** that a Host contributes
1919-configurations to a User.
2020-2121-<Aside title="When is bidirectionality needed?" icon="comment-alt">
2222-Only when you wish for a Host-aspect to provide common _home settings_
2323-(`homeManager`, etc) for **all** its users.
2424-2525-And even then there are much simpler and better ways:
2626-2727-```nix
2828-# an aspect with all common stuff for everybody
2929-den.aspects.user-base = { nixos = ...; homeManager = ...; hjem = ...; };
3030-3131-# include it in all users
3232-den.ctx.user.includes = [ den.aspects.user-base ];
3333-```
3434-3535-> _Now you can skip the rest of this page_.
3636-</Aside>
3737-3838-3939-There are at least two (built-in) ways to achieve this in Den.
4040-The `den._.bidirectional` and `den._.mutual-provider` batteries. The
4141-first one was extracted from den-core and the second started
4242-life as an **aspect routing** example, but made it to become
4343-proper battery itself and even safer than the first.
4444-4545-4646-## Default, *unidirectional* OS configuration
4747-4848-Den framework is built around **context pipeline** transformations.
4949-In order to create a full OS configuration, everything starts with a host definition:
5050-5151-```nix "igloo" "tux"
5252-den.hostx.x86_64-linux.igloo.users.tux = {}
5353-```
5454-5555-We need to build the `nixos` Nix module that will later be used by `lib.nixosSystem`.
5656-To do so, Den invokes the `den.ctx.host` pipeline like this:
5757-5858-> `Tip: Zoom diagrams using your mouse wheel or drag to move.`
5959-6060-```mermaid
6161-sequenceDiagram
6262- participant Den
6363- participant host as den.ctx.host
6464- participant user as den.ctx.user
6565- participant igloo as den.aspects.igloo
6666- participant tux as den.aspects.tux
6767-6868- Den ->> host : {host = igloo}
6969-7070- host ->> igloo : request nixos class
7171- igloo -->> igloo : each .includes takes { host }
7272- igloo -->> host : { nixos = ... } owned and parametric results
7373-7474- host ->> user : fan-outs for each user: { host, user }
7575-7676- user ->> tux : request nixos class
7777- tux -->> tux : home classes forwarded as nixos class
7878- tux -->> tux : each .includes takes { host, user }
7979- tux -->> user : { nixos = ... } owned and parametric results
8080-8181- user -->> host : { nixos = ... } all user contributions
8282-8383- host -->> Den : complete nixos module for lib.nixosSystem
8484-8585-```
8686-8787-This is the normal NixOS pipeline an __Not Bidirectional__. All OS contributions come from
8888-the host itself and from each of its user.
8989-9090-9191-9292-## `den.provides.bidirectional`
9393-9494-Bidirectionality is enabled __per-user__ or for _all_ of them.
9595-9696-```nix
9797-# only tux takes configurations from its hosts
9898-den.aspects.tux.includes = [ den._.bidirectional ];
9999-100100-# for ALL users
101101-den.ctx.user.includes = [ den._.bidirectional ];
102102-```
103103-104104-When Bidirectionality is enabled, the interaction looks like this:
105105-106106-> `Tip: Zoom diagrams using your mouse wheel or drag to move.`
107107-108108-```mermaid
109109-sequenceDiagram
110110- participant Den
111111- participant host as den.ctx.host
112112- participant user as den.ctx.user
113113- participant igloo as den.aspects.igloo
114114- participant tux as den.aspects.tux
115115-116116- Den ->> host : {host = igloo}
117117-118118- host ->> igloo : request nixos class
119119- igloo -->> igloo : each .includes takes { host }
120120- igloo -->> host : { nixos = ... } owned and parametric results
121121-122122- host ->> user : fan-outs for each user: { host, user }
123123-124124- user ->> tux : request nixos class
125125-126126- tux ->> igloo : request home class
127127- igloo -->> igloo : each .includes takes { host, user }
128128- igloo -->> tux : { hjem = ... } owned and parametric results
129129-130130- tux -->> tux : home classes forwarded as nixos class
131131-132132- tux -->> tux : each .includes takes { host, user }
133133- tux -->> user : { nixos = ... } owned and parametric results
134134-135135- user -->> host : { nixos = ... } all user contributions
136136-137137- host -->> Den : complete nixos module for lib.nixosSystem
138138-139139-```
140140-141141-<Aside title="Potential Duplicates by Host Aspect" type="caution">
142142-**Under Bidirectionality**, the igloo aspect is activated more than once!
143143-144144-Notice that `den.aspects.igloo.includes` functions are called **with** `{ host }` and **later with** `{ host, user }` **per-user**.
145145-146146-Because the list of functions at `igloo.includes` get invoked more than once, with different contexts,
147147-they must take care of the following:
148148-149149-```nix
150150-# avoid being called with `{host, user}`
151151-den.lib.perHost ({ host }: ...)
152152-153153-# avoid being called with `{host}`
154154-den.lib.perUser ({ host, user }: ...)
155155-```
156156-157157-Static aspects (plain-attrsets) or host-owned classes at a Host-aspect
158158-have **no way** to distinguish when the calling context is
159159-`{host}` or `{host,user}`, **only functions** are context-aware.
160160-161161-```
162162-# Lists, packages, options at host-level would cause duplicates
163163-# den.aspects.igloo.nixos.options.foo = lib.mkOption {};
164164-165165-# Instead, use perHost to define unique values:
166166-den.aspects.igloo.includes = [
167167- (perHost { nixos.options.foo = lib.mkOption {}; })
168168-];
169169-```
170170-171171-Read the documentation at [`context/user.nix`](https://github.com/vic/den/blob/main/modules/context/user.nix) for all the details.
172172-</Aside>
173173-174174-<Aside title="Avoid dups with host-only module pattern" icon="rocket">
175175-Here's a pattern you can use to avoid duplication while `bidirectional` is enabled:
176176-177177-```nix
178178-den.aspects.igloo.includes = [
179179- # wrap an aspect with perHost
180180- (den.lib.perHost igloo-only)
181181-182182- # any other aspect can contribute to users
183183- shells
184184- music-production
185185-];
186186-187187-# Use this aspect for host-only stuff, anything that would
188188-# lead to duplicates is safe in this list
189189-den.aspects.igloo-only = {
190190- includes = with den.aspects; [ facter disko ];
191191- nixos = { pkgs, ... }: {
192192- environment.systemPackages = [ pkgs.hello ];
193193- };
194194-}
195195-```
196196-197197-> Tip inspired by `@drupol`.
198198-</Aside>
199199-200200-## `den.provides.mutual-provider`
201201-202202-An alternative to bidirectionality is [`den.provides.mutual-provider`](https://github.com/vic/den/blob/main/modules/aspects/provides/mutual-provider.nix).
203203-204204-This battery is safer, instead of using the host aspect directly, it requires you to define other named aspects under `.provides.` to create an explicit relationship between users and hosts.
205205-206206-```nix
207207-# mutual-provider is activated at a `{host,user}` context
208208-den.ctx.user.includes = [ den._.mutual-provider ];
209209-210210-# user aspect provides to specific host or to all where it lives
211211-den.aspects.tux = {
212212- provides.igloo.nixos.programs.emacs.enable = true;
213213- provides.to-hosts = { host, ... }: {
214214- nixos.programs.nh.enable = host.name == "igloo";
215215- };
216216-};
217217-218218-# host aspect provides to specific user or to all its users
219219-den.aspects.igloo = {
220220- provides.alice.homeManager.programs.vim.enable = true;
221221- provides.to-users = { user, ... }: {
222222- homeManager.programs.helix.enable = user.name == "alice";
223223- };
224224-};
225225-```
226226-227227-> `Tip: Zoom diagrams using your mouse wheel or drag to move.`
228228-229229-```mermaid
230230-sequenceDiagram
231231- participant Den
232232- participant host as den.ctx.host
233233- participant user as den.ctx.user
234234- participant igloo as den.aspects.igloo
235235- participant igloo-users as den.aspects.igloo.provides.to-users
236236- participant igloo-tux as den.aspects.igloo.provides.tux
237237- participant tux as den.aspects.tux
238238- participant tux-hosts as den.aspects.tux.provides.to-hosts
239239- participant tux-igloo as den.aspects.tux.provides.igloo
240240-241241- Den ->> host : {host = igloo}
242242-243243- host ->> igloo : request nixos class
244244- igloo -->> igloo : each .includes takes { host }
245245- igloo -->> host : { nixos = ... } owned and parametric results
246246-247247- host ->> user : fan-outs for each user: { host, user }
248248-249249- user ->> tux : request nixos class
250250- tux -->> tux : home classes forwarded as nixos class
251251- tux -->> tux : each .includes takes { host, user }
252252- tux -->> user : { nixos = ... } owned and parametric results
253253-254254- user ->> igloo-users : host configs its users: { host, user }
255255- igloo-users -->> igloo-users : home classes forwarded as nixos class
256256- igloo-users -->> igloo-users : each .includes takes { host, user }
257257- igloo-users -->> user : { nixos = ... }
258258-259259- user ->> igloo-tux : host configs tux: { host, user }
260260- igloo-tux -->> igloo-tux : home classes forwarded as nixos class
261261- igloo-tux -->> igloo-tux : each .includes takes { host, user }
262262- igloo-tux -->> user : { nixos = ... }
263263-264264- user ->> tux-hosts : user configs its hosts: { host, user }
265265- tux-hosts -->> tux-hosts : home classes forwarded as nixos class
266266- tux-hosts -->> tux-hosts : each .includes takes { host, user }
267267- tux-hosts -->> user : { nixos = ... }
268268-269269- user ->> tux-igloo : user configs igloo: { host, user }
270270- tux-igloo -->> tux-igloo : home classes forwarded as nixos class
271271- tux-igloo -->> tux-igloo : each .includes takes { host, user }
272272- tux-igloo -->> user : { nixos = ... }
273273-274274-275275- user -->> host : { nixos = ... } all user contributions
276276-277277- host -->> Den : complete nixos module for lib.nixosSystem
278278-279279-```
280280-
+144
docs/src/content/docs/guides/mutual.mdx
···11+---
22+title: Host<->User Mutual Providers
33+description: How to configure mutual configs in Den.
44+---
55+66+import { Aside } from '@astrojs/starlight/components';
77+88+<Aside title="Source" icon="github">
99+[`context/user.nix`](https://github.com/vic/den/blob/main/modules/context/user.nix) ·
1010+[`context/host.nix`](https://github.com/vic/den/blob/main/modules/context/host.nix) ·
1111+[`mutual-provider.nix`](https://github.com/vic/den/blob/main/modules/aspects/provides/mutual-provider.nix)
1212+</Aside>
1313+1414+## What Mutual-Config Mean
1515+1616+__Mutual Configs__ means that not only a User contributes
1717+configuration to a Host, but **also** that a Host contributes
1818+configurations to a User.
1919+2020+2121+## Default, *unidirectional* OS configuration
2222+2323+Den framework is built around **context pipeline** transformations.
2424+In order to create a full OS configuration, everything starts with a host definition:
2525+2626+```nix "igloo" "tux"
2727+den.hostx.x86_64-linux.igloo.users.tux = {}
2828+```
2929+3030+We need to build the `nixos` Nix module that will later be used by `lib.nixosSystem`.
3131+To do so, Den invokes the `den.ctx.host` pipeline like this:
3232+3333+> `Tip: Zoom diagrams using your mouse wheel or drag to move.`
3434+3535+```mermaid
3636+sequenceDiagram
3737+ participant Den
3838+ participant host as den.ctx.host
3939+ participant user as den.ctx.user
4040+ participant igloo as den.aspects.igloo
4141+ participant tux as den.aspects.tux
4242+4343+ Den ->> host : {host = igloo}
4444+4545+ host ->> igloo : request nixos class
4646+ igloo -->> igloo : each .includes takes { host }
4747+ igloo -->> host : { nixos = ... } owned and parametric results
4848+4949+ host ->> user : fan-outs for each user: { host, user }
5050+5151+ user ->> tux : request nixos class
5252+ tux -->> tux : home classes forwarded as nixos class
5353+ tux -->> tux : each .includes takes { host, user }
5454+ tux -->> user : { nixos = ... } owned and parametric results
5555+5656+ user -->> host : { nixos = ... } all user contributions
5757+5858+ host -->> Den : complete nixos module for lib.nixosSystem
5959+6060+```
6161+6262+This is the normal `den.ctx.host` pipeline. All OS contributions come from the host itself and from each of its user.
6363+6464+6565+## `den.provides.mutual-provider`
6666+6767+The [`den.provides.mutual-provider`](https://github.com/vic/den/blob/main/modules/aspects/provides/mutual-provider.nix) battery allows you to define mutual congigurations by letting you to define named aspects under `.provides.` to create explicit relationship between users and hosts.
6868+6969+```nix
7070+# mutual-provider is activated at a `{host,user}` context
7171+# either per-user or for all of them.
7272+den.ctx.user.includes = [ den._.mutual-provider ];
7373+7474+# user aspect provides to specific host or to all where it lives
7575+den.aspects.tux = {
7676+ provides.igloo.nixos.programs.emacs.enable = true;
7777+ provides.to-hosts = { host, ... }: {
7878+ nixos.programs.nh.enable = host.name == "igloo";
7979+ };
8080+};
8181+8282+# host aspect provides to specific user or to all its users
8383+den.aspects.igloo = {
8484+ provides.alice.homeManager.programs.vim.enable = true;
8585+ provides.to-users = { user, ... }: {
8686+ homeManager.programs.helix.enable = user.name == "alice";
8787+ };
8888+};
8989+```
9090+9191+> `Tip: Zoom diagrams using your mouse wheel or drag to move.`
9292+9393+```mermaid
9494+sequenceDiagram
9595+ participant Den
9696+ participant host as den.ctx.host
9797+ participant user as den.ctx.user
9898+ participant igloo as den.aspects.igloo
9999+ participant igloo-users as den.aspects.igloo.provides.to-users
100100+ participant igloo-tux as den.aspects.igloo.provides.tux
101101+ participant tux as den.aspects.tux
102102+ participant tux-hosts as den.aspects.tux.provides.to-hosts
103103+ participant tux-igloo as den.aspects.tux.provides.igloo
104104+105105+ Den ->> host : {host = igloo}
106106+107107+ host ->> igloo : request nixos class
108108+ igloo -->> igloo : each .includes takes { host }
109109+ igloo -->> host : { nixos = ... } owned and parametric results
110110+111111+ host ->> user : fan-outs for each user: { host, user }
112112+113113+ user ->> tux : request nixos class
114114+ tux -->> tux : home classes forwarded as nixos class
115115+ tux -->> tux : each .includes takes { host, user }
116116+ tux -->> user : { nixos = ... } owned and parametric results
117117+118118+ user ->> igloo-users : host configs its users: { host, user }
119119+ igloo-users -->> igloo-users : home classes forwarded as nixos class
120120+ igloo-users -->> igloo-users : each .includes takes { host, user }
121121+ igloo-users -->> user : { nixos = ... }
122122+123123+ user ->> igloo-tux : host configs tux: { host, user }
124124+ igloo-tux -->> igloo-tux : home classes forwarded as nixos class
125125+ igloo-tux -->> igloo-tux : each .includes takes { host, user }
126126+ igloo-tux -->> user : { nixos = ... }
127127+128128+ user ->> tux-hosts : user configs its hosts: { host, user }
129129+ tux-hosts -->> tux-hosts : home classes forwarded as nixos class
130130+ tux-hosts -->> tux-hosts : each .includes takes { host, user }
131131+ tux-hosts -->> user : { nixos = ... }
132132+133133+ user ->> tux-igloo : user configs igloo: { host, user }
134134+ tux-igloo -->> tux-igloo : home classes forwarded as nixos class
135135+ tux-igloo -->> tux-igloo : each .includes takes { host, user }
136136+ tux-igloo -->> user : { nixos = ... }
137137+138138+139139+ user -->> host : { nixos = ... } all user contributions
140140+141141+ host -->> Den : complete nixos module for lib.nixosSystem
142142+143143+```
144144+
+1-4
docs/src/content/docs/reference/batteries.mdx
···40404141### `den._.mutual-provider`
42424343-Allows the user and host to contribute configuration to each other via
4444-`provides`. This is not the same as the built-in bidirectionality. The
4545-difference is that this allows you to wire bidirectionality between
4646-explictly-named hosts/users pairs.
4343+Allows the user and host to contribute configuration to each other via `.provides.`.
47444845### `den._.tty-autologin`
4946
···11-{ den, ... }:
22-let
33- description = ''
44- Enable Den bidirectionality: User takes configuration from Host.
55-66- **REALLY** IMPORTANT: Read the documentation for den.ctx.user
77-88- Consider as alternative den.provides.mutual-provider.
99- '';
1010-in
1111-{
1212- den.provides.bidirectional = {
1313- inherit description;
1414- includes = [ den.ctx.user.provides.bidirectional ];
1515- };
1616-}
+1-6
modules/aspects/provides/mutual-provider.nix
···991010 This battery implements an aspect "routing" pattern.
11111212- This is not the same as `den._.bidirectional` battery, but provides a
1313- **safer** alternative to `den._.bidirectional`.
1414- The reason is that this battery does not re-invoke the `host-aspect.includes`,
1515- instead it relies on you defining provides.
1616-1712 Be sure to read diagrams for the Host context pipeline:
1818- https://den.oeiuwq.com/guides/bidirectional
1313+ https://den.oeiuwq.com/guides/mutual
19142015 ## Usage
2116
-47
modules/context/user.nix
···2323 - static includes like { nixos.foo = ... } or ({ class, aspect-chain }: { nixos.foo = ...; })
2424 - atLeast{host,user} parametric includes like ({ host,user }: { nixos.foo = ...; })
25252626- ## Bidirectionality
2727-2828- Battery `den.provides.bidirectional` can be included on each user that needs to take configuration from the Host.
2929-3030- Enable per user:
3131- den.aspects.tux.includes = [ den._.bidirectional ];
3232-3333- Enable for all users:
3434- den.ctx.user.includes = [ den._.bidirectional ];
3535-3636- IMPORTANT: Enabling bidirectionality means that the following pipeline is enabled:
3737-3838- host-aspect{host} => user-aspect{host,user} => host-aspect{host,user}
3939-4040- Notice that the host-aspect is being activated more than once!
4141-4242- This means that host configurations are obtained
4343- - once when the host is obtaining its own configuration with context {host}
4444- - once PER user that has bidirectionality enabled with context {host,user}
4545-4646- Due to Nix `lib.functionArgs` not distinguishing between `{host}` and `{host, ...}`,
4747- Den provides these utilities built upon `den.lib.take.exactly`:
4848-4949- # Do this to prevent being invoked with `{host,user}`
5050- den.lib.perHost ({host}: ...)
5151-5252- # Do this to prevent being invoked with `{host}`
5353- den.lib.perUser ({host,user}: ...)
5454-5555- Static aspects (plain-attrsets) or host-owned classes at a Host-aspect
5656- have **no way** to distinguish when the calling context is
5757- `{host}` or `{host,user}`, only functions are context-aware.
5858-5959- Because of this, a host-aspect might produce duplicate values on list,
6060- package types, or unique values like options:
6161-6262- # lists, packages and options need to be unique.
6363- # this line would produce duplicate errors IF bidirectional enabled
6464- den.aspects.igloo.nixos.options.foo = lib.mkOption {};
6565-6666- # Instead, wrap in perHost things that must be unique
6767- den.aspects.igloo.includes = [
6868- (den.lib.perHost { nixos.options.foo = lib.mkOption {}; })
6969- ]
7026 '';
71277228 ctx.user.into.default = lib.singleton;
7329 ctx.user.provides.user = take.exactly from-user;
7474- ctx.user.provides.bidirectional = take.exactly from-host;
75307631 from-user = { host, user }: fixedTo { inherit host user; } den.aspects.${user.aspect};
7777-7878- from-host = { host, user }: fixedTo { inherit host user; } den.aspects.${host.aspect};
79328033in
8134{