docs(nix): record flake conventions
This commit is contained in:
270
docs/nix.md
Normal file
270
docs/nix.md
Normal file
@@ -0,0 +1,270 @@
|
||||
# Nix Conventions
|
||||
|
||||
This document records local Nix style and design conventions.
|
||||
Use these conventions when changing this flake.
|
||||
Read this document with `docs/dictionary.md`.
|
||||
|
||||
## Names
|
||||
|
||||
### Reserve `lib` for `nixpkgs.lib`
|
||||
|
||||
Use `lib` only for the base `nixpkgs.lib` value.
|
||||
Do not use `lib` for project functions.
|
||||
Use `util` for library functions passed through module arguments.
|
||||
Use `flake.mk<Name>` for assembly functions used by flake outputs.
|
||||
|
||||
Avoid:
|
||||
|
||||
```nix
|
||||
specialArgs = {
|
||||
lib = util;
|
||||
};
|
||||
```
|
||||
|
||||
Use:
|
||||
|
||||
```nix
|
||||
specialArgs = {
|
||||
inherit util;
|
||||
};
|
||||
```
|
||||
|
||||
Then call library functions through `util` inside modules:
|
||||
|
||||
```nix
|
||||
{
|
||||
lib,
|
||||
util,
|
||||
...
|
||||
}:
|
||||
{
|
||||
networking.networkmanager.unmanaged = [ "interface-name:${util.bridgeName 10}" ];
|
||||
}
|
||||
```
|
||||
|
||||
### Name project function namespaces by role
|
||||
|
||||
Put pure project functions under `util`.
|
||||
Put functions that create systems or output values under `flake`.
|
||||
This keeps data-only functions separate from functions that carry flake context.
|
||||
|
||||
Avoid:
|
||||
|
||||
```nix
|
||||
util.mkHosts { root = self + "/hosts"; }
|
||||
```
|
||||
|
||||
Use:
|
||||
|
||||
```nix
|
||||
flake.mkHosts { root = self + "/hosts"; }
|
||||
```
|
||||
|
||||
## File Placement
|
||||
|
||||
### Put files in the directory that owns their role
|
||||
|
||||
Choose the file location before writing a Nix file.
|
||||
Put assembly files under `flake/`.
|
||||
Put library files under `lib/`.
|
||||
Put modules under `modules/`.
|
||||
Put host configurations under `hosts/<name>/`.
|
||||
Put host-side guest wiring under `guests/`.
|
||||
Put registry definitions under `registry/`.
|
||||
Keep `flake.nix` focused on inputs and output wiring.
|
||||
Do not add root-level Nix files other than `flake.nix`.
|
||||
|
||||
A module is self-contained configuration under `modules/`.
|
||||
A module configures one program, service, or subsystem.
|
||||
Files under `hosts/`, `guests/`, and `modules/` return NixOS modules.
|
||||
|
||||
### Use `default.nix` for module directories with support files
|
||||
|
||||
Use `default.nix` as the primary module when a module directory owns support files.
|
||||
Keep sibling files for data or code read by that primary module.
|
||||
|
||||
Avoid:
|
||||
|
||||
```text
|
||||
modules/shell/fish/fish.nix
|
||||
modules/shell/fish/config.fish
|
||||
```
|
||||
|
||||
Use:
|
||||
|
||||
```text
|
||||
modules/shell/fish/default.nix
|
||||
modules/shell/fish/config.fish
|
||||
```
|
||||
|
||||
### Use non-module `default.nix` files only for directory assembly
|
||||
|
||||
Outside `modules/`, use `default.nix` to connect files in its directory.
|
||||
Do not define primary assembly functions in `default.nix`.
|
||||
Put primary assembly functions in named files.
|
||||
|
||||
Avoid:
|
||||
|
||||
```text
|
||||
flake/default.nix # defines mkHost
|
||||
```
|
||||
|
||||
Use:
|
||||
|
||||
```text
|
||||
flake/default.nix # imports ./host.nix
|
||||
flake/host.nix # defines mkHosts
|
||||
```
|
||||
|
||||
### Keep assembly files focused on one concept
|
||||
|
||||
Give each assembly file under `flake/` one top-level concept.
|
||||
Keep helper functions private to that file when no other file needs them.
|
||||
Export the constructor for the concept when another assembly file needs it.
|
||||
Name that constructor `mk<Concept>`.
|
||||
|
||||
Avoid:
|
||||
|
||||
```nix
|
||||
{
|
||||
inherit collectNixFiles mkHost mkHosts;
|
||||
}
|
||||
```
|
||||
|
||||
Use:
|
||||
|
||||
```nix
|
||||
{
|
||||
inherit mkHosts;
|
||||
}
|
||||
```
|
||||
|
||||
## Function Arguments
|
||||
|
||||
### Use closed interfaces for assembly files and library files
|
||||
|
||||
Use exact function argument patterns for assembly files and library files.
|
||||
The caller owns the argument set for these files.
|
||||
The imported file names each accepted attribute.
|
||||
The imported file rejects stale or accidental extra attributes.
|
||||
|
||||
Avoid:
|
||||
|
||||
```nix
|
||||
{
|
||||
inputs,
|
||||
lib,
|
||||
self,
|
||||
...
|
||||
}:
|
||||
```
|
||||
|
||||
Use:
|
||||
|
||||
```nix
|
||||
{
|
||||
inputs,
|
||||
lib,
|
||||
self,
|
||||
}:
|
||||
```
|
||||
|
||||
### Pass function arguments explicitly
|
||||
|
||||
Pass only the values an assembly file or library file needs.
|
||||
Bind `lib` to the base `nixpkgs.lib` value at the call site.
|
||||
Use `inherit` only for values that keep the same name.
|
||||
|
||||
Avoid:
|
||||
|
||||
```nix
|
||||
import ./flake inputs
|
||||
```
|
||||
|
||||
Use:
|
||||
|
||||
```nix
|
||||
let
|
||||
inherit (nixpkgs) lib;
|
||||
in
|
||||
import ./flake { inherit lib inputs self; }
|
||||
```
|
||||
|
||||
### Keep NixOS module interfaces open
|
||||
|
||||
Files under `hosts/`, `guests/`, and `modules/` return NixOS modules.
|
||||
`nixosSystem` owns their argument shape.
|
||||
Name each argument the module uses.
|
||||
Keep `...` so the module accepts standard arguments and special arguments.
|
||||
|
||||
Avoid:
|
||||
|
||||
```nix
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
registry,
|
||||
}:
|
||||
```
|
||||
|
||||
Use:
|
||||
|
||||
```nix
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
registry,
|
||||
...
|
||||
}:
|
||||
```
|
||||
|
||||
## `let` Bindings
|
||||
|
||||
### Use role-specific binding names
|
||||
|
||||
A `let` binding name must explain the value's role in the expression.
|
||||
Avoid names that describe only the value's type.
|
||||
|
||||
Avoid:
|
||||
|
||||
```nix
|
||||
let
|
||||
names = lib.attrNames hosts;
|
||||
in
|
||||
lib.genAttrs names mkHost
|
||||
```
|
||||
|
||||
Use:
|
||||
|
||||
```nix
|
||||
let
|
||||
hostNames = lib.attrNames hosts;
|
||||
in
|
||||
lib.genAttrs hostNames mkHost
|
||||
```
|
||||
|
||||
## Standard Library Calls
|
||||
|
||||
### Qualify standard library calls in flake assembly
|
||||
|
||||
Use qualified standard library calls inside assembly files.
|
||||
Use `lib.mapAttrs` instead of inheriting `mapAttrs` from `lib`.
|
||||
This keeps the source of each function visible.
|
||||
|
||||
Avoid:
|
||||
|
||||
```nix
|
||||
let
|
||||
inherit (lib) mapAttrs;
|
||||
in
|
||||
mapAttrs f attrs
|
||||
```
|
||||
|
||||
Use:
|
||||
|
||||
```nix
|
||||
lib.mapAttrs f attrs
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user