36 KiB
Snowfall Lib — Comprehensive Reference
Unified configuration for systems, packages, modules, shells, templates, and more with Nix Flakes. Built on top of flake-utils-plus.
Table of Contents
- Overview
- Flake Inputs & Outputs
- Getting Started
- Library Bootstrap (
snowfall-lib/default.nix) - Library Modules
- NixOS / Darwin / Home Modules
- Directory Conventions
- Special Arguments Injected by Snowfall Lib
- Virtual Systems
- 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/, andtemplates/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
# 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
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
libattributes from every input that exposes one (accessible aslib.<input-name>.*) - the
snowfall.*sub-library namespace - the user's own
lib/modules (merged underlib.<namespace>.*)
mkFlake Signature
mkFlake : {
inputs,
src,
snowfall?,
systems?,
homes?,
modules?,
overlays?,
packages?,
shells?,
checks?,
templates?,
channels?,
channels-config?,
outputs-builder?,
alias?,
extra-exported-overlays?,
} -> <flake-outputs>
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:
-
Builds
snowfall-configfrom user options with defaults:namespacedefaults to"internal"rootdefaults tosrcmeta.name/meta.titledefault tonull
-
Collects library inputs: gathers the
.libattribute from every input that has one (both from core inputs and user inputs). -
Bootstraps the Snowfall sub-library (
snowfall-lib): usesfixto lazily load every subdirectory ofsnowfall-lib/as a Nix file, passing a sharedattrsset containing{ snowfall-lib, snowfall-config, core-inputs, user-inputs }. All resulting attribute sets are deep-merged. -
Builds
base-lib: shallow-mergesnixpkgs.lib, input libs, top-level (non-attrset) snowfall lib values, and{ snowfall = snowfall-lib; }. -
Loads the user's
lib/modules: discovers alldefault.nixfiles under<src>/lib/, calls each with{ inputs, snowfall-inputs, namespace, lib }, and deep-merges the results intouser-lib. -
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.<module>.<function>.
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.
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).
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).
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.
attrs.merge-shallow-packages [ { vim = <drv>; some.value = true; } { some.value = false; } ]
# => { vim = <drv>; 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.
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 <snowfall-root>/checks/, build them as derivations, apply aliases and overrides, and filter by the current system.
Each check's default.nix receives via callPackageWith:
- All
pkgsattributes channels— all nixpkgs channel setslib— the full Snowfall-extended libinputs— user inputs (withoutsrc)namespace— the configured namespace string
# 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.
flake.get-libs { nixpkgs = nixpkgs; empty = {}; }
# => { nixpkgs = nixpkgs.lib; }
mkFlake (the main entry point)
See Getting Started for the full signature. Internally it:
- Creates system configurations via
system.create-systems - Creates home-manager configurations via
home.create-homes - Creates NixOS, Darwin, and Home modules via
module.create-modules - Creates overlays via
overlay.create-overlays - Creates packages, shells, and checks inside
outputs-builder - Merges everything and delegates to
flake-utils-plus.lib.mkFlake - Post-processes
packagesoutput to include home-manager activation packages (ashomeConfigurations-<user>)
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.
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.
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).
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).
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.
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-managerflake input.
home.split-user-and-host
String -> { user: String, host: String }
Parse a "user@host" string. If no @ is present, host is "".
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 = trueandsnowfallorg.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 <snowfall-root>/homes/<system>/<user>/default.nix. Applies per-user overrides from homes.users.<name> 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
extraSpecialArgsto home-manager - Injecting
home-manager.sharedModules - Per-user
home-manager.users.<name>configuration scoped to the correct host home-manager.useGlobalPkgs = trueby 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 { <namespace> = user-lib; }.
internal.user-lib
The user's own library loaded from <snowfall-root>/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 <snowfall-root>/<type>), 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 <snowfall-root>/modules/nixos.
Each module wrapper:
- Derives
system,target,format, andvirtualfrom module arguments. - Injects
lib,inputs,namespaceinto module arguments. - Calls the module with the enriched args.
- Attaches
_filefor error attribution.
Modules are keyed by their relative path from src, without the trailing /default.nix, e.g. "hardware/nvidia".
# 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:
- Expose all user packages under
pkgs.<namespace>. - Apply any overlays discovered under
src(defaults to<snowfall-root>/overlays). - 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/<name>"— a per-package overlay for each discovered package."<name>"— each discovered overlay fromoverlays/."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 <snowfall-root>/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
pkgsattributes pkgs.<namespace>pointing to the currently-building package set (enables packages to depend on sibling packages)channels— all nixpkgs channel setslib— the full Snowfall-extended libinputs— user inputsnamespace— 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.
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.
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.
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.
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.
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 <snowfall-root>/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).
# 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 for the full list.
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-generatorsinput. Darwin systems require thedarwininput.
system.get-system-output
String -> String
Return the flake output attribute name for configurations:
| Target | Output |
|---|---|
| Virtual | "<format>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.
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 <snowfall-root>/systems/<target>/<name>/default.nix.
- Applies per-host overrides from
systems.hosts.<name> - 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/ormodules/darwin/ - All created systems are passed back as the
systemsspecial arg (enables cross-host references)
template
File: snowfall-lib/template/default.nix
template.create-templates
{
src?,
overrides?,
alias?,
} -> Attrs
Discover all directories under <snowfall-root>/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.
# 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.<name> options for declarative NixOS user management.
Migration note:
snowfallorg.user(singular) is a renamed alias forsnowfallorg.users(plural).
Options
snowfallorg.users.<name>
├── 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/<name>")
└── config Submodule — home-manager-compatible configuration
When create = true, a corresponding users.users.<name> entry is created with:
isNormalUser = truename = <name>home = <path>group = "users"extraGroups = [ "wheel" ]ifadmin = 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.<name>
├── create Bool (default: true)
└── home
├── enable Bool (default: true)
├── path String (default: "/Users/<name>")
└── config Submodule
When create = true, creates a users.users.<name> 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.usernameis set tosnowfallorg.user.namehome.homeDirectoryis set tosnowfallorg.user.home.directory
The default home.directory is determined in order:
osConfig.users.users.<name>.homeif available (NixOS/darwin integration)/Users/<name>on Darwin/home/<name>on Linux
Directory Conventions
Snowfall Lib auto-discovers files in the following directories relative to snowfall-config.root (defaults to your flake's src):
<root>/
├── systems/
│ └── <target>/ # e.g. x86_64-linux, aarch64-darwin, x86_64-iso
│ └── <hostname>/
│ └── default.nix
│
├── homes/
│ └── <target>/ # e.g. x86_64-linux
│ └── <user>/ # or <user>@<host> for host-scoped homes
│ └── default.nix
│
├── modules/
│ ├── nixos/
│ │ └── <path>/
│ │ └── default.nix
│ ├── darwin/
│ │ └── <path>/
│ │ └── default.nix
│ └── home/
│ └── <path>/
│ └── default.nix
│
├── packages/
│ └── <name>/
│ └── default.nix
│
├── overlays/
│ └── <name>/
│ └── default.nix
│
├── shells/
│ └── <name>/
│ └── default.nix
│
├── checks/
│ └── <name>/
│ └── default.nix
│
├── templates/
│ └── <name>/
│ ├── flake.nix # optional — description is extracted automatically
│ └── ...
│
└── lib/
└── <any-name>/
└── default.nix # merged into lib.<namespace>.*
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/<target>/<name>/default.nix)
Same as system modules plus:
| Arg | Type | Description |
|---|---|---|
host |
String |
The system's hostname |
Home configurations (homes/<target>/<user>/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/<name>/default.nix)
Arguments are supplied via callPackageWith so any subset can be requested:
| Arg | Type | Description |
|---|---|---|
pkgs.* |
Any | All standard nixpkgs attributes |
pkgs.<namespace> |
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/<name>/default.nix)
Overlays are imported as functions and called with:
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 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 <format>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 |