# Snowfall Lib — Comprehensive Reference > Unified configuration for systems, packages, modules, shells, templates, and more with Nix Flakes. > Built on top of [flake-utils-plus](https://github.com/gytis-ivaskevicius/flake-utils-plus). --- ## Table of Contents 1. [Overview](#overview) 2. [Flake Inputs & Outputs](#flake-inputs--outputs) 3. [Getting Started](#getting-started) 4. [Library Bootstrap (`snowfall-lib/default.nix`)](#library-bootstrap) 5. [Library Modules](#library-modules) - [attrs](#attrs) - [checks](#checks) - [flake](#flake) - [fp (Functional Programming)](#fp-functional-programming) - [fs (Filesystem)](#fs-filesystem) - [home](#home) - [internal](#internal) - [module](#module) - [overlay](#overlay) - [package](#package) - [path](#path) - [shell](#shell) - [system](#system) - [template](#template) 6. [NixOS / Darwin / Home Modules](#nixos--darwin--home-modules) - [NixOS User Module](#nixos-user-module) - [Darwin User Module](#darwin-user-module) - [Home-Manager User Module](#home-manager-user-module) 7. [Directory Conventions](#directory-conventions) 8. [Special Arguments Injected by Snowfall Lib](#special-arguments-injected-by-snowfall-lib) 9. [Virtual Systems](#virtual-systems) 10. [Version History](#version-history) --- ## Overview Snowfall Lib is a Nix Flakes library that provides a **convention-over-configuration** approach to managing: - NixOS, nix-darwin, and virtual system configurations - Home-Manager user configurations - Reusable NixOS/darwin/home-manager modules - Nixpkgs overlays - Custom packages - Development shells - CI checks - Flake templates - User library extensions It works by scanning well-known directory layouts inside your flake, automatically wiring everything into flake outputs while giving you full override capability. ### Design Principles - **File-system driven**: directories under `systems/`, `homes/`, `packages/`, `modules/`, `overlays/`, `shells/`, `checks/`, and `templates/` are discovered automatically. - **Composable library**: every sub-library is a plain attribute set merged into `lib.snowfall.*`. - **Namespace isolation**: all user packages are placed under a configurable namespace attribute in nixpkgs (e.g. `pkgs.myorg`). - **Functional style**: heavy use of `pipe`, point-free composition, and higher-order helpers. --- ## Flake Inputs & Outputs ### Inputs (`flake.nix`) | Input | URL | |---|---| | `nixpkgs` | `github:nixos/nixpkgs/release-25.11` | | `flake-utils-plus` | `github:gytis-ivaskevicius/flake-utils-plus/master` | ### Outputs ``` snowfall-lib ├── mkLib # function: create the extended lib ├── mkFlake # function: convenience wrapper (mkLib + lib.mkFlake) ├── nixosModules │ └── user # ./modules/nixos/user/default.nix ├── darwinModules │ └── user # ./modules/darwin/user/default.nix ├── homeModules │ └── user # ./modules/home/user/default.nix ├── formatter # nixfmt-tree for x86_64-linux, aarch64-linux, x86_64-darwin, aarch64-darwin └── snowfall # internal config & lib exposed for documentation tooling ├── config # { root, src, namespace, lib-dir, meta } ├── raw-config └── internal-lib ``` --- ## Getting Started ### Creating the Library ```nix # In your flake.nix { inputs.snowfall-lib.url = "github:snowfallorg/lib"; inputs.nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; outputs = inputs: inputs.snowfall-lib.lib.mkFlake { inherit inputs; src = ./.; snowfall = { namespace = "myorg"; # optional, default: "internal" meta = { name = "my-flake"; title = "My Flake"; }; }; }; } ``` ### Using `mkLib` Directly ```nix let lib = inputs.snowfall-lib.lib.mkLib { inherit inputs; src = ./.; snowfall.namespace = "myorg"; }; in lib.mkFlake { ... } ``` ### `mkLib` Signature ``` mkLib : { inputs, src, snowfall? } -> lib ``` `mkLib` returns the merged nixpkgs lib extended with: - all `lib` attributes from every input that exposes one (accessible as `lib..*`) - the `snowfall.*` sub-library namespace - the user's own `lib/` modules (merged under `lib..*`) ### `mkFlake` Signature ``` mkFlake : { inputs, src, snowfall?, systems?, homes?, modules?, overlays?, packages?, shells?, checks?, templates?, channels?, channels-config?, outputs-builder?, alias?, extra-exported-overlays?, } -> ``` All options are optional; only `inputs` and `src` are required. | Option | Type | Description | |---|---|---| | `inputs` | `Attrs` | Flake inputs (must include `self`) | | `src` | `Path` | Root of the user's flake | | `snowfall` | `Attrs` | Snowfall-specific config (namespace, meta, root) | | `systems` | `Attrs` | Overrides/extra modules for system configs | | `homes` | `Attrs` | Overrides/extra modules for home configs | | `modules` | `Attrs` | Override maps for `nixos`, `darwin`, `home` module sets | | `overlays` | `[Overlay]` | Extra overlays applied to channels | | `packages` | `Attrs` | Additional packages merged over discovered ones | | `shells` | `Attrs` | Additional dev shells merged over discovered ones | | `checks` | `Attrs` | Additional checks merged over discovered ones | | `templates` | `Attrs` | Additional templates merged over discovered ones | | `channels` | `Attrs` | Per-channel nixpkgs configuration | | `channels-config` | `Attrs` | Global nixpkgs config applied to all channels | | `outputs-builder` | `channels -> Attrs` | Additional per-system outputs | | `alias` | `Attrs` | Alias maps for packages, shells, checks, modules, templates | | `extra-exported-overlays` | `Attrs` | Extra overlays to include in the `overlays` output | --- ## Library Bootstrap **File**: `snowfall-lib/default.nix` This is the entry point. It accepts `core-inputs` (Snowfall Lib's own inputs) and `user-options` (`{ inputs, src, snowfall? }`), then: 1. **Builds `snowfall-config`** from user options with defaults: - `namespace` defaults to `"internal"` - `root` defaults to `src` - `meta.name` / `meta.title` default to `null` 2. **Collects library inputs**: gathers the `.lib` attribute from every input that has one (both from core inputs and user inputs). 3. **Bootstraps the Snowfall sub-library** (`snowfall-lib`): uses `fix` to lazily load every subdirectory of `snowfall-lib/` as a Nix file, passing a shared `attrs` set containing `{ snowfall-lib, snowfall-config, core-inputs, user-inputs }`. All resulting attribute sets are deep-merged. 4. **Builds `base-lib`**: shallow-merges `nixpkgs.lib`, input libs, top-level (non-attrset) snowfall lib values, and `{ snowfall = snowfall-lib; }`. 5. **Loads the user's `lib/` modules**: discovers all `default.nix` files under `/lib/`, calls each with `{ inputs, snowfall-inputs, namespace, lib }`, and deep-merges the results into `user-lib`. 6. **Returns the final `lib`**: `merge-deep [ base-lib user-lib ]`. --- ## Library Modules Each module file exports an attribute set that is deep-merged into the top-level `snowfall-lib`. The modules are accessed as `lib.snowfall..`. --- ### attrs **File**: `snowfall-lib/attrs/default.nix` Attribute set utilities. #### `attrs.map-concat-attrs-to-list` ``` (a -> b -> [c]) -> Attrs -> [c] ``` Map over an attribute set and flatten the result into a single list. ```nix attrs.map-concat-attrs-to-list (name: value: [name value]) { x = 1; y = 2; } # => [ "x" 1 "y" 2 ] ``` #### `attrs.merge-deep` ``` [Attrs] -> Attrs ``` Recursively merge a list of attribute sets (later entries win at every level). ```nix attrs.merge-deep [{ a.b = 1; } { a.c = 2; }] # => { a = { b = 1; c = 2; }; } ``` #### `attrs.merge-shallow` ``` [Attrs] -> Attrs ``` Merge a list of attribute sets at the top level only (later entries win; sub-attrs are replaced, not merged). ```nix attrs.merge-shallow [{ a = { x = 1; }; } { a = { y = 2; }; }] # => { a = { y = 2; }; } ``` #### `attrs.merge-shallow-packages` ``` [Attrs] -> Attrs ``` Merge package attribute sets: derivations are kept as-is; nested attribute sets (e.g. `some.value`) are merged one level deep. ```nix attrs.merge-shallow-packages [ { vim = ; some.value = true; } { some.value = false; } ] # => { vim = ; some.value = false; } ``` #### `attrs.merge-with-aliases` ``` (Attrs -> Attrs -> Attrs) -> [Attrs] -> Attrs -> Attrs ``` Fold a list of items using a merge function, then apply aliases so that `alias.default = "vim"` adds `result.default = result.vim`. #### `attrs.apply-aliases-and-overrides` ``` Attrs -> Attrs -> Attrs -> Attrs ``` Given a pre-built attribute set, apply aliases and then overlay overrides on top. ```nix attrs.apply-aliases-and-overrides packages-set { default = "vim"; } { extra = ...; } ``` --- ### checks **File**: `snowfall-lib/checks/default.nix` #### `check.create-checks` ``` { channels, src?, pkgs?, overrides?, alias? } -> Attrs ``` Discover all `default.nix` files under `/checks/`, build them as derivations, apply aliases and overrides, and filter by the current system. Each check's `default.nix` receives via `callPackageWith`: - All `pkgs` attributes - `channels` — all nixpkgs channel sets - `lib` — the full Snowfall-extended lib - `inputs` — user inputs (without `src`) - `namespace` — the configured namespace string ```nix # checks/my-check/default.nix { pkgs, lib, ... }: pkgs.runCommand "my-check" {} "echo ok > $out" ``` --- ### flake **File**: `snowfall-lib/flake/default.nix` Utilities for working with flake inputs, plus the central `mkFlake` function. #### `flake.without-self` ``` Attrs -> Attrs ``` Remove the `self` key from an attribute set of flake inputs. #### `flake.without-src` ``` Attrs -> Attrs ``` Remove the `src` key from an attribute set. #### `flake.without-snowfall-inputs` ``` Attrs -> Attrs ``` Remove both `self` and `src` (composed from the two above). #### `flake.without-snowfall-options` ``` Attrs -> Attrs ``` Remove all Snowfall-specific top-level `mkFlake` options so the remainder can be forwarded safely to `flake-utils-plus.lib.mkFlake`. Removed keys: `systems`, `modules`, `overlays`, `packages`, `outputs-builder`, `outputsBuilder`, `packagesPrefix`, `hosts`, `homes`, `channels-config`, `templates`, `checks`, `alias`, `snowfall`. #### `flake.get-libs` ``` Attrs -> Attrs ``` Transform an attribute set of inputs into an attribute set of their `.lib` attributes; entries without a `lib` attrset are dropped. ```nix flake.get-libs { nixpkgs = nixpkgs; empty = {}; } # => { nixpkgs = nixpkgs.lib; } ``` #### `mkFlake` (the main entry point) See [Getting Started](#getting-started) for the full signature. Internally it: 1. Creates system configurations via `system.create-systems` 2. Creates home-manager configurations via `home.create-homes` 3. Creates NixOS, Darwin, and Home modules via `module.create-modules` 4. Creates overlays via `overlay.create-overlays` 5. Creates packages, shells, and checks inside `outputs-builder` 6. Merges everything and delegates to `flake-utils-plus.lib.mkFlake` 7. Post-processes `packages` output to include home-manager activation packages (as `homeConfigurations-`) --- ### fp (Functional Programming) **File**: `snowfall-lib/fp/default.nix` Small functional programming helpers. #### `fp.compose` ``` (b -> c) -> (a -> b) -> a -> c ``` Compose two functions right-to-left. ```nix fp.compose (x: x + 2) (x: x + 1) # equivalent to x: (x+1)+2 ``` #### `fp.compose-all` ``` [(x -> y)] -> a -> b ``` Compose a list of functions right-to-left. ```nix fp.compose-all [ add-two add-one ] # equivalent to fp.compose add-two add-one ``` #### `fp.call` ``` (a -> b) -> a -> b ``` Apply a function to an argument (identity combinator, useful for point-free pipelines). #### `fp.apply` ``` a -> (a -> b) -> b ``` Flip of `call` — apply an argument to a function. --- ### fs (Filesystem) **File**: `snowfall-lib/fs/default.nix` All filesystem helpers are safe: operations on non-existent paths return `{}` or `[]`. #### Kind predicates ``` fs.is-file-kind : String -> Bool -- kind == "regular" fs.is-symlink-kind : String -> Bool -- kind == "symlink" fs.is-directory-kind : String -> Bool -- kind == "directory" fs.is-unknown-kind : String -> Bool -- kind == "unknown" ``` Used with `builtins.readDir` results. #### `fs.get-file` ``` String -> String ``` Resolve a path relative to the **user's flake source** (`user-inputs.src`). ```nix fs.get-file "systems" # => "/path/to/user-flake/systems" ``` #### `fs.get-snowfall-file` ``` String -> String ``` Resolve a path relative to `snowfall-config.root` (the root of the Snowfall-configured portion of the flake, which may differ from `src`). ```nix fs.get-snowfall-file "modules/nixos" # => "/path/to/user-flake/modules/nixos" ``` #### `fs.internal-get-file` ``` String -> String ``` Resolve a path relative to the Snowfall Lib flake itself (internal use). #### `fs.safe-read-directory` ``` Path -> Attrs ``` `builtins.readDir` that returns `{}` if the path does not exist. #### `fs.get-entries-by-kind` ``` (String -> Bool) -> Path -> [Path] ``` Return all entries in a directory whose kind satisfies the predicate. Returns full paths. #### `fs.get-directories` ``` Path -> [Path] ``` Return all subdirectories of a path. #### `fs.get-directories-with-default` ``` Path -> [Path] ``` Return all subdirectories that contain a `default.nix` file. ```nix fs.get-directories-with-default ./systems/x86_64-linux # => [ "./systems/x86_64-linux/my-host" ] ``` #### `fs.get-files` ``` Path -> [Path] ``` Return all regular files (non-recursive) in a directory. #### `fs.get-files-recursive` ``` Path -> [Path] ``` Return all regular files recursively under a directory. #### `fs.filter-files` ``` (Path -> Bool) -> Path -> [Path] ``` Filter the non-recursive file listing by a predicate. #### `fs.filter-files-recursive` ``` (Path -> Bool) -> Path -> [Path] ``` Filter the recursive file listing by a predicate. #### `fs.get-nix-files` ``` Path -> [Path] ``` All `*.nix` files (non-recursive) in a directory. #### `fs.get-nix-files-recursive` ``` Path -> [Path] ``` All `*.nix` files recursively under a directory. #### `fs.get-default-nix-files` ``` Path -> [Path] ``` All files named exactly `default.nix` (non-recursive). #### `fs.get-default-nix-files-recursive` ``` Path -> [Path] ``` All `default.nix` files recursively. This is the primary function used to discover packages, modules, overlays, etc. #### `fs.get-non-default-nix-files` ``` Path -> [Path] ``` All `*.nix` files whose name is **not** `default.nix` (non-recursive). #### `fs.get-non-default-nix-files-recursive` ``` Path -> [Path] ``` All `*.nix` files recursively whose name is **not** `default.nix`. --- ### home **File**: `snowfall-lib/home/default.nix` Home-Manager configuration management. > **Requires** the `home-manager` flake input. #### `home.split-user-and-host` ``` String -> { user: String, host: String } ``` Parse a `"user@host"` string. If no `@` is present, `host` is `""`. ```nix home.split-user-and-host "alice@my-machine" # => { user = "alice"; host = "my-machine"; } ``` #### `home.create-home` ``` { path, name?, modules?, specialArgs?, channelName?, system?, } -> Attrs ``` Create a single home-manager configuration. `name` defaults to the parent directory name of `path`. If the name contains no `@`, the system is appended automatically: `"alice@x86_64-linux"`. The configuration is built using `home-manager.lib.homeManagerConfiguration` and automatically includes: - The Snowfall home user module (`modules/home/user/default.nix`) - A nix-registry patch module that disables the flake-utils-plus options module (incompatible with standalone home-manager) - Default `snowfallorg.user.enable = true` and `snowfallorg.user.name` Special args injected into modules: | Arg | Value | |---|---| | `system` | The target system string | | `name` | The unique `user@system` name | | `user` | Parsed username | | `host` | Parsed hostname (may be `""`) | | `format` | `"home"` | | `inputs` | User flake inputs (without `src`) | | `namespace` | Snowfall namespace string | | `pkgs` | The nixpkgs package set for the system | | `lib` | The Snowfall-extended lib with `hm` attribute | #### `home.get-target-homes-metadata` ``` Path -> [{ system: String, name: String, path: Path }] ``` Scan a directory (e.g. `homes/x86_64-linux`) for subdirectories that contain `default.nix` and return metadata for each. #### `home.create-homes` ``` { users?, modules?, } -> Attrs ``` Discover and create all home-manager configurations. Scans `/homes///default.nix`. Applies per-user overrides from `homes.users.` and shared modules from `homes.modules`. Auto-discovered home modules from `modules/home/` are injected into every home. #### `home.create-home-system-modules` ``` Attrs -> [Module] ``` When home-manager is used **inside** a NixOS or Darwin system (not standalone), this produces the list of NixOS/Darwin modules that integrate each home into the system. It handles: - Passing `extraSpecialArgs` to home-manager - Injecting `home-manager.sharedModules` - Per-user `home-manager.users.` configuration scoped to the correct host - `home-manager.useGlobalPkgs = true` by default --- ### internal **File**: `snowfall-lib/internal/default.nix` Internal helpers not intended for direct user consumption. #### `internal.system-lib` The complete library as seen by system and module evaluation contexts. Shallow-merges `nixpkgs.lib`, all input libs, and `{ = user-lib; }`. #### `internal.user-lib` The user's own library loaded from `/lib/`. Deep-merges all discovered `default.nix` files. Each file can be a function accepting `{ inputs, snowfall-inputs, namespace, lib }` or a plain attribute set. #### `internal.create-simple-derivations` ``` { type, channels, src?, pkgs?, overrides?, alias?, } -> Attrs ``` Generic helper used by both `shell.create-shells` and `check.create-checks`. Discovers `default.nix` files under `src` (defaults to `/`), builds them with `callPackageWith`, and filters by the current system. Each derivation receives `{ channels, lib, inputs, namespace }`. --- ### module **File**: `snowfall-lib/module/default.nix` #### `module.create-modules` ``` { src?, overrides?, alias?, } -> Attrs ``` Discover all `default.nix` files recursively under `src` and expose them as a set keyed by their relative path (e.g. `"networking/firewall"`). `src` defaults to `/modules/nixos`. Each module wrapper: 1. Derives `system`, `target`, `format`, and `virtual` from module arguments. 2. Injects `lib`, `inputs`, `namespace` into module arguments. 3. Calls the module with the enriched args. 4. Attaches `_file` for error attribution. Modules are keyed by their **relative path** from `src`, without the trailing `/default.nix`, e.g. `"hardware/nvidia"`. ```nix # modules/nixos/hardware/nvidia/default.nix { lib, pkgs, config, namespace, ... }: { options.${namespace}.hardware.nvidia.enable = lib.mkEnableOption "NVIDIA support"; config = lib.mkIf config.${namespace}.hardware.nvidia.enable { ... }; } ``` --- ### overlay **File**: `snowfall-lib/overlay/default.nix` #### `overlay.create-overlays-builder` ``` { src?, namespace?, extra-overlays?, } -> channels -> [Overlay] ``` Produce the `overlaysBuilder` function expected by `flake-utils-plus`. Returns a list of overlays that: 1. Expose all user packages under `pkgs.`. 2. Apply any overlays discovered under `src` (defaults to `/overlays`). 3. Append any extra overlays. Each discovered overlay `default.nix` receives `user-inputs // { channels, namespace, inputs, lib }`. #### `overlay.create-overlays` ``` { src?, packages-src?, namespace?, extra-overlays?, } -> Attrs ``` Create the exported `overlays` flake output. Returns a set containing: - `"package/"` — a per-package overlay for each discovered package. - `""` — each discovered overlay from `overlays/`. - `"default"` — a combined overlay that applies all packages and overlays. - Any extra overlays passed in. Overlays that set `__dontExport = true` are excluded from the exported set. --- ### package **File**: `snowfall-lib/package/default.nix` #### `package.create-packages` ``` { channels, src?, pkgs?, overrides?, alias?, namespace?, } -> Attrs ``` Discover all `default.nix` files recursively under `src` (defaults to `/packages`), build each with `callPackageWith`, apply aliases and overrides, and filter by the current system. Each package's `default.nix` receives via `callPackageWith`: - All standard `pkgs` attributes - `pkgs.` pointing to the currently-building package set (enables packages to depend on sibling packages) - `channels` — all nixpkgs channel sets - `lib` — the full Snowfall-extended lib - `inputs` — user inputs - `namespace` — the namespace string Packages are keyed by the **parent directory name** of their `default.nix`, e.g. `packages/my-tool/default.nix` → `"my-tool"`. A `meta.snowfall.path` attribute is attached to every built derivation for traceability. --- ### path **File**: `snowfall-lib/path/default.nix` File path manipulation utilities. #### `path.split-file-extension` ``` String -> [String] ``` Split `"my-file.md"` into `[ "my-file" "md" ]`. Asserts that the file has an extension. #### `path.has-any-file-extension` ``` String -> Bool ``` Return `true` if the string/path has any file extension. #### `path.get-file-extension` ``` String -> String ``` Return the extension of a file name (e.g. `"txt"` from `"my-file.final.txt"`). Returns `""` if none. #### `path.has-file-extension` ``` String -> String -> Bool ``` `has-file-extension "nix" "foo.nix"` → `true`. Curried for use with `filter`. #### `path.get-parent-directory` ``` Path -> String ``` Return the **name** (not full path) of the parent directory. ```nix path.get-parent-directory "/a/b/c/default.nix" # => "c" ``` Composed from `baseNameOf ∘ dirOf`. #### `path.get-file-name-without-extension` ``` Path -> String ``` Return the file name without its extension. ```nix path.get-file-name-without-extension ./some-dir/my-file.pdf # => "my-file" ``` #### `path.get-output-name` ``` Path -> String ``` Convenience for package/shell/check output naming. Discards the Nix path string context (required when using a path as an attrset key) and returns the parent directory name. ```nix path.get-output-name ./foo/bar/default.nix # => "bar" ``` Composed from `unsafeDiscardStringContext ∘ get-parent-directory`. #### `path.get-directory-name` ``` Path -> String ``` Return the base name of a directory path, discarding string context. ```nix path.get-directory-name /templates/foo # => "foo" ``` #### `path.get-relative-module-path` ``` String -> Path -> String ``` Strip the `src` prefix and the trailing `/default.nix` from a module path, yielding the relative module key used in `module.create-modules`. ```nix path.get-relative-module-path "/modules/nixos" "/modules/nixos/foo/bar/default.nix" # => "foo/bar" ``` --- ### shell **File**: `snowfall-lib/shell/default.nix` #### `shell.create-shells` ``` { channels, src?, pkgs?, overrides?, alias? } -> Attrs ``` Discover all `default.nix` files under `/shells/`, build them as derivations, apply aliases and overrides, and filter by the current system. Each shell's `default.nix` receives the same arguments as checks (see [checks](#checks)). ```nix # shells/dev/default.nix { pkgs, lib, ... }: pkgs.mkShell { packages = with pkgs; [ git curl ]; } ``` --- ### system **File**: `snowfall-lib/system/default.nix` System configuration management for NixOS, nix-darwin, and virtual (nixos-generators) targets. #### `system.get-inferred-system-name` ``` Path -> String ``` Return the system name from a file path. For `*.nix` files returns the parent directory name; for directories returns `baseNameOf`. #### `system.is-darwin` ``` String -> Bool ``` True if the system target string contains `"darwin"` (e.g. `"aarch64-darwin"`). #### `system.is-linux` ``` String -> Bool ``` True if the system target string contains `"linux"`. #### `system.is-virtual` ``` String -> Bool ``` True if the target corresponds to a nixos-generators virtual format (e.g. `"x86_64-iso"`). #### `system.get-virtual-system-type` ``` String -> String ``` Return the virtual system format string embedded in the target, or `""` if not virtual. See [Virtual Systems](#virtual-systems) for the full list. ```nix system.get-virtual-system-type "x86_64-iso" # => "iso" system.get-virtual-system-type "x86_64-linux" # => "" ``` #### `system.get-target-systems-metadata` ``` Path -> [{ target: String, name: String, path: Path }] ``` For a given target directory (e.g. `systems/x86_64-linux`), enumerate subdirectories containing `default.nix` and return metadata for each. #### `system.get-system-builder` ``` String -> (Attrs -> Attrs) ``` Return the appropriate system builder function for a target: | Target | Builder | |---|---| | Virtual (any format) | `nixos-generators.nixosGenerate` with `format` set | | `*-darwin` | `darwin.lib.darwinSystem` | | `*-linux` | `nixpkgs.lib.nixosSystem` | All builders automatically include the corresponding Snowfall user module. > **Note**: Virtual systems require the `nixos-generators` input. Darwin systems require the `darwin` input. #### `system.get-system-output` ``` String -> String ``` Return the flake output attribute name for configurations: | Target | Output | |---|---| | Virtual | `"Configurations"` | | Darwin | `"darwinConfigurations"` | | Linux | `"nixosConfigurations"` | #### `system.get-resolved-system-target` ``` String -> String ``` For virtual targets, replace the format with `"linux"` to get the real CPU architecture target. For real targets, returns unchanged. ```nix system.get-resolved-system-target "x86_64-iso" # => "x86_64-linux" ``` #### `system.create-system` ``` { target?, system?, path, name?, modules?, specialArgs?, channelName?, builder?, output?, systems?, homes?, } -> Attrs ``` Create a single system configuration. All optional fields default from the target string. Special args injected into system modules: | Arg | Value | |---|---| | `target` | The original target string (e.g. `"x86_64-iso"`) | | `system` | The resolved system (e.g. `"x86_64-linux"`) | | `format` | `"linux"`, `"darwin"`, or the virtual format string | | `virtual` | `Bool` | | `host` | The system name | | `systems` | Attribute set of all created systems (for cross-system references) | | `lib` | The Snowfall-extended lib | | `inputs` | User inputs (without `src`) | | `namespace` | Snowfall namespace | If the `home-manager` input exists, home-manager modules are automatically added. #### `system.create-systems` ``` { systems?, homes?, } -> Attrs ``` Discover and create all system configurations. Scans `/systems///default.nix`. - Applies per-host overrides from `systems.hosts.` - Applies shared NixOS modules from `systems.modules.nixos` - Applies shared Darwin modules from `systems.modules.darwin` - Auto-discovers and injects user modules from `modules/nixos/` or `modules/darwin/` - All created systems are passed back as the `systems` special arg (enables cross-host references) --- ### template **File**: `snowfall-lib/template/default.nix` #### `template.create-templates` ``` { src?, overrides?, alias?, } -> Attrs ``` Discover all **directories** under `/templates/` and expose them as flake templates. If the template directory contains a `flake.nix`, its `description` field is automatically extracted and attached to the template metadata. ```nix # templates/my-template/flake.nix { description = "A minimal NixOS configuration template"; # ... } ``` --- ## NixOS / Darwin / Home Modules These modules are part of the flake's `nixosModules`, `darwinModules`, and `homeModules` outputs, and are also automatically injected by Snowfall Lib into every created system/home. --- ### NixOS User Module **File**: `modules/nixos/user/default.nix` **Output**: `nixosModules.user` Provides `snowfallorg.users.` options for declarative NixOS user management. > **Migration note**: `snowfallorg.user` (singular) is a renamed alias for `snowfallorg.users` (plural). #### Options ``` snowfallorg.users. ├── create Bool (default: true) — whether to create the OS user ├── admin Bool (default: true) — whether to add the user to the wheel group └── home ├── enable Bool (default: true) ├── path String (default: "/home/") └── config Submodule — home-manager-compatible configuration ``` When `create = true`, a corresponding `users.users.` entry is created with: - `isNormalUser = true` - `name = ` - `home = ` - `group = "users"` - `extraGroups = [ "wheel" ]` if `admin = true` The `home.config` submodule accepts full home-manager configuration if `home-manager` is available as a flake input. --- ### Darwin User Module **File**: `modules/darwin/user/default.nix` **Output**: `darwinModules.user` Same concept as the NixOS module but for nix-darwin. The `admin` option is absent (macOS user management works differently). #### Options ``` snowfallorg.users. ├── create Bool (default: true) └── home ├── enable Bool (default: true) ├── path String (default: "/Users/") └── config Submodule ``` When `create = true`, creates a `users.users.` entry with `home` and `isHidden = false`. --- ### Home-Manager User Module **File**: `modules/home/user/default.nix` **Output**: `homeModules.user` Provides `snowfallorg.user` options for a home-manager configuration. #### Options ``` snowfallorg.user ├── enable Bool (default: false) — enable automatic home configuration ├── name String — the username └── home.directory String — the home directory path ``` When `enable = true`: - `home.username` is set to `snowfallorg.user.name` - `home.homeDirectory` is set to `snowfallorg.user.home.directory` The default `home.directory` is determined in order: 1. `osConfig.users.users..home` if available (NixOS/darwin integration) 2. `/Users/` on Darwin 3. `/home/` on Linux --- ## Directory Conventions Snowfall Lib auto-discovers files in the following directories relative to `snowfall-config.root` (defaults to your flake's `src`): ``` / ├── systems/ │ └── / # e.g. x86_64-linux, aarch64-darwin, x86_64-iso │ └── / │ └── default.nix │ ├── homes/ │ └── / # e.g. x86_64-linux │ └── / # or @ for host-scoped homes │ └── default.nix │ ├── modules/ │ ├── nixos/ │ │ └── / │ │ └── default.nix │ ├── darwin/ │ │ └── / │ │ └── default.nix │ └── home/ │ └── / │ └── default.nix │ ├── packages/ │ └── / │ └── default.nix │ ├── overlays/ │ └── / │ └── default.nix │ ├── shells/ │ └── / │ └── default.nix │ ├── checks/ │ └── / │ └── default.nix │ ├── templates/ │ └── / │ ├── flake.nix # optional — description is extracted automatically │ └── ... │ └── lib/ └── / └── default.nix # merged into lib..* ``` All directories are optional; Snowfall Lib handles non-existent paths gracefully. --- ## Special Arguments Injected by Snowfall Lib ### System modules (`modules/nixos/`, `modules/darwin/`) | Arg | Type | Description | |---|---|---| | `system` | `String` | Resolved system (e.g. `"x86_64-linux"`) | | `target` | `String` | Original target (e.g. `"x86_64-iso"`) | | `format` | `String` | `"linux"`, `"darwin"`, or the virtual format | | `virtual` | `Bool` | Whether this is a virtual system | | `systems` | `Attrs` | All created system configs (for cross-system references) | | `lib` | `Attrs` | Snowfall-extended lib | | `inputs` | `Attrs` | User flake inputs (without `src`) | | `namespace` | `String` | Snowfall namespace string | ### System configurations (`systems///default.nix`) Same as system modules plus: | Arg | Type | Description | |---|---|---| | `host` | `String` | The system's hostname | ### Home configurations (`homes///default.nix`) | Arg | Type | Description | |---|---|---| | `system` | `String` | The home's target system | | `name` | `String` | Unique home name (`user@system`) | | `user` | `String` | The username | | `host` | `String` | The bound hostname (may be `""`) | | `format` | `String` | Always `"home"` | | `inputs` | `Attrs` | User flake inputs (without `src`) | | `namespace` | `String` | Snowfall namespace | | `pkgs` | `Attrs` | nixpkgs package set for this system | | `lib` | `Attrs` | Snowfall-extended lib with `hm` attribute | ### Packages (`packages//default.nix`) Arguments are supplied via `callPackageWith` so any subset can be requested: | Arg | Type | Description | |---|---|---| | `pkgs.*` | Any | All standard nixpkgs attributes | | `pkgs.` | `Attrs` | All currently-building user packages | | `channels` | `Attrs` | All nixpkgs channel sets | | `lib` | `Attrs` | Snowfall-extended lib | | `inputs` | `Attrs` | User flake inputs | | `namespace` | `String` | Snowfall namespace | ### Shells and Checks Same as packages. ### Overlays (`overlays//default.nix`) Overlays are imported as functions and called with: ```nix user-inputs // { channels, namespace, inputs, # same as user-inputs lib, } ``` The overlay function itself should return the standard `final: prev: { ... }` overlay. --- ## Virtual Systems Virtual systems use [nixos-generators](https://github.com/nix-community/nixos-generators) to produce machine images. They are enabled by using a virtual format name **instead of** `linux` in the target string. The supported formats (in priority order, most-specific first): | Format | Target example | |---|---| | `amazon` | `x86_64-amazon` | | `azure` | `x86_64-azure` | | `cloudstack` | `x86_64-cloudstack` | | `docker` | `x86_64-docker` | | `do` | `x86_64-do` | | `gce` | `x86_64-gce` | | `install-iso-hyperv` | `x86_64-install-iso-hyperv` | | `hyperv` | `x86_64-hyperv` | | `install-iso` | `x86_64-install-iso` | | `iso` | `x86_64-iso` | | `kexec` | `x86_64-kexec` | | `kexec-bundle` | `x86_64-kexec-bundle` | | `kubevirt` | `x86_64-kubevirt` | | `proxmox-lxc` | `x86_64-proxmox-lxc` | | `lxc-metadata` | `x86_64-lxc-metadata` | | `lxc` | `x86_64-lxc` | | `openstack` | `x86_64-openstack` | | `proxmox` | `x86_64-proxmox` | | `qcow` | `x86_64-qcow` | | `raw-efi` | `x86_64-raw-efi` | | `raw` | `x86_64-raw` | | `sd-aarch64-installer` | `aarch64-sd-aarch64-installer` | | `sd-aarch64` | `aarch64-sd-aarch64` | | `vagrant-virtualbox` | `x86_64-vagrant-virtualbox` | | `virtualbox` | `x86_64-virtualbox` | | `vm-bootloader` | `x86_64-vm-bootloader` | | `vm-nogui` | `x86_64-vm-nogui` | | `vmware` | `x86_64-vmware` | | `vm` | `x86_64-vm` | > **Important**: The order matters. `"vm-bootloader"` must appear before `"vm"` so that a target containing `"vm-bootloader"` does not falsely match `"vm"`. Virtual systems output their configurations under `Configurations` (e.g. `isoConfigurations`). The `format` special arg is set to the virtual format string so modules can conditionally apply settings. --- ## Version History | Tag | Notable Changes | |---|---| | `v3.0.3` | Update nixpkgs to 25.11; `fold` → `foldr` correctness fix | | `v3.0.2` | Fix: flatten home configs into packages for flake schema compliance; expose activation packages | | `v3.0.1` | Refactor: eliminate DRY violations; add `fs.get-directories-with-default`, `path.get-relative-module-path`, `path.get-directory-name`, `path.get-output-name`; switch `fold` to `foldr` | | `v3.0.0` | Refactor: point-free style, pipe-based data transformations, improved attrs helpers, `create-simple-derivations` shared helper | | `v2.1.x` | Per-channel configuration; same-username-across-targets support; namespace injection in overlays and home-manager | | `v2.0.0` | Auto-extract template descriptions; replace `./` path roots with `self` for evaluation speed | | `v1.0.x` | Initial release |