stuff
This commit is contained in:
130
lib/README.md
Normal file
130
lib/README.md
Normal file
@@ -0,0 +1,130 @@
|
||||
# mjallen-lib Utility Functions
|
||||
|
||||
This directory contains utility functions that can be used to enhance your Nix configuration. These functions are inspired by the khanelinix repository and provide a more explicit and modular approach to building Nix configurations.
|
||||
|
||||
## Directory Structure
|
||||
|
||||
- `default.nix`: Main entry point that imports and exposes all utility functions
|
||||
- `module/`: Utilities for module creation and option handling
|
||||
- `file/`: Utilities for file handling and module discovery
|
||||
- `system/`: Utilities for system configuration building
|
||||
|
||||
## How to Use
|
||||
|
||||
### 1. Import the Library
|
||||
|
||||
The library is already imported in your flake.nix file through the outputs-builder:
|
||||
|
||||
```nix
|
||||
outputs-builder = channels: {
|
||||
formatter = inputs.treefmt-nix.lib.mkWrapper channels.nixpkgs ./treefmt.nix;
|
||||
|
||||
# Add mjallen-lib to the flake outputs
|
||||
overlays = {
|
||||
mjallen-lib = final: prev: {
|
||||
mjallen-lib = (import ./lib { inherit inputs; }).mjallen-lib;
|
||||
};
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
This makes the mjallen-lib available to all your modules through the extended lib.
|
||||
|
||||
### 2. Use the Module Utilities
|
||||
|
||||
The module utilities provide functions for creating modules with consistent options:
|
||||
|
||||
```nix
|
||||
{ lib, ... }:
|
||||
let
|
||||
inherit (lib.mjallen.module) mkModule mkOpt mkBoolOpt;
|
||||
in
|
||||
mkModule {
|
||||
name = "mymodule";
|
||||
description = "My awesome module";
|
||||
options = {
|
||||
setting1 = mkOpt lib.types.str "default" "Description of setting1";
|
||||
setting2 = mkBoolOpt false "Description of setting2";
|
||||
};
|
||||
config = {
|
||||
# Module implementation
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Use the File Utilities
|
||||
|
||||
The file utilities provide functions for file handling and module discovery:
|
||||
|
||||
```nix
|
||||
{ lib, ... }:
|
||||
let
|
||||
inherit (lib.mjallen.file) safeImport importModulesRecursive;
|
||||
in
|
||||
{
|
||||
# Import a file with error handling
|
||||
myConfig = safeImport ./my-config.nix {};
|
||||
|
||||
# Import all modules recursively
|
||||
imports = importModulesRecursive ./modules;
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Use the System Utilities
|
||||
|
||||
The system utilities provide functions for building system configurations:
|
||||
|
||||
```nix
|
||||
{ lib, ... }:
|
||||
let
|
||||
inherit (lib.mjallen.system.common) mkHomeManagerConfig;
|
||||
in
|
||||
{
|
||||
# Build home-manager configurations
|
||||
homeManagerConfig = mkHomeManagerConfig {
|
||||
extendedLib = lib;
|
||||
inputs = inputs;
|
||||
system = "x86_64-linux";
|
||||
matchingHomes = { ... };
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Available Functions
|
||||
|
||||
### Module Utilities
|
||||
|
||||
- `mkModule`: Create a module with common options
|
||||
- `mkOpt`: Create an option with a type, default value, and description
|
||||
- `mkOpt'`: Create an option with a type and default value (no description)
|
||||
- `mkBoolOpt`: Create a boolean option with a default value and description
|
||||
- `mkBoolOpt'`: Create a boolean option with a default value (no description)
|
||||
- `enabled`: Standard enable pattern
|
||||
- `disabled`: Standard disable pattern
|
||||
- `capitalize`: Capitalize a string
|
||||
- `boolToNum`: Convert a boolean to a number
|
||||
- `default-attrs`: Apply mkDefault to all attributes
|
||||
- `force-attrs`: Apply mkForce to all attributes
|
||||
- `nested-default-attrs`: Apply default-attrs to nested attributes
|
||||
- `nested-force-attrs`: Apply force-attrs to nested attributes
|
||||
|
||||
### File Utilities
|
||||
|
||||
- `readFile`: Read a file and return its contents
|
||||
- `pathExists`: Check if a file exists
|
||||
- `safeImport`: Import a nix file with error handling
|
||||
- `scanDir`: Scan a directory and return directory names
|
||||
- `getFile`: Get a file path relative to the flake root
|
||||
- `importModulesRecursive`: Recursively discover and import all Nix modules in a directory tree
|
||||
- `scanSystems`: Recursively scan systems directory structure
|
||||
- `filterNixOSSystems`: Filter systems for NixOS (Linux)
|
||||
- `filterDarwinSystems`: Filter systems for Darwin (macOS)
|
||||
- `scanHomes`: Scan homes directory structure for home configurations
|
||||
|
||||
### System Utilities
|
||||
|
||||
- `mkExtendedLib`: Extend the nixpkgs lib with mjallen-lib
|
||||
- `mkNixpkgsConfig`: Create a nixpkgs configuration
|
||||
- `mkHomeConfigs`: Create home configurations for a system and hostname
|
||||
- `mkHomeManagerConfig`: Create a home-manager configuration
|
||||
- `mkSpecialArgs`: Create special arguments for a system configuration
|
||||
16
lib/default.nix
Normal file
16
lib/default.nix
Normal file
@@ -0,0 +1,16 @@
|
||||
{ inputs, ... }:
|
||||
{
|
||||
mjallen-lib = {
|
||||
# Import module utilities
|
||||
module = import ./module { inherit inputs; };
|
||||
|
||||
# Import file utilities
|
||||
file = import ./file { inherit inputs; };
|
||||
|
||||
# Import system utilities
|
||||
system = import ./system { inherit inputs; };
|
||||
|
||||
# Import examples
|
||||
examples = import ./examples { inherit inputs; };
|
||||
};
|
||||
}
|
||||
8
lib/examples/default.nix
Normal file
8
lib/examples/default.nix
Normal file
@@ -0,0 +1,8 @@
|
||||
{ inputs, ... }:
|
||||
{
|
||||
# Import all examples
|
||||
sops = import ./sops.nix;
|
||||
homeSops = import ./home-sops.nix;
|
||||
fileUtils = import ./file-utils.nix;
|
||||
systemUtils = import ./system-utils.nix;
|
||||
}
|
||||
58
lib/examples/file-utils.nix
Normal file
58
lib/examples/file-utils.nix
Normal file
@@ -0,0 +1,58 @@
|
||||
{ lib, ... }:
|
||||
let
|
||||
inherit (lib.mjallen.file)
|
||||
readFile
|
||||
pathExists
|
||||
safeImport
|
||||
scanDir
|
||||
getFile
|
||||
importModulesRecursive
|
||||
scanSystems
|
||||
filterNixOSSystems
|
||||
filterDarwinSystems
|
||||
scanHomes;
|
||||
in
|
||||
{
|
||||
# Example of reading a file
|
||||
myFileContent = readFile ./example.txt;
|
||||
|
||||
# Example of checking if a file exists
|
||||
fileExists = pathExists ./example.txt;
|
||||
|
||||
# Example of safely importing a file
|
||||
myConfig = safeImport ./my-config.nix {};
|
||||
|
||||
# Example of scanning a directory
|
||||
directoryContents = scanDir ./modules;
|
||||
|
||||
# Example of getting a file path relative to the flake root
|
||||
flakeFile = getFile "flake.nix";
|
||||
|
||||
# Example of importing modules recursively
|
||||
modules = importModulesRecursive ./modules;
|
||||
|
||||
# Example of scanning systems
|
||||
allSystems = scanSystems ./systems;
|
||||
|
||||
# Example of filtering systems
|
||||
nixosSystems = filterNixOSSystems allSystems;
|
||||
darwinSystems = filterDarwinSystems allSystems;
|
||||
|
||||
# Example of scanning homes
|
||||
allHomes = scanHomes ./homes;
|
||||
|
||||
# Example of using these functions together
|
||||
nixosConfigurations = lib.mapAttrs' (
|
||||
name:
|
||||
{ system, hostname, ... }:
|
||||
{
|
||||
name = hostname;
|
||||
value = lib.nixosSystem {
|
||||
inherit system;
|
||||
modules = [
|
||||
{ networking.hostName = hostname; }
|
||||
] ++ importModulesRecursive ./modules/nixos;
|
||||
};
|
||||
}
|
||||
) nixosSystems;
|
||||
}
|
||||
31
lib/examples/home-sops.nix
Normal file
31
lib/examples/home-sops.nix
Normal file
@@ -0,0 +1,31 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
inherit (lib.mjallen.module) mkModule mkOpt mkBoolOpt;
|
||||
in
|
||||
mkModule {
|
||||
name = "sops";
|
||||
description = "SOPS secret management for home-manager";
|
||||
options = {
|
||||
defaultSopsFile = mkOpt lib.types.path null "Default sops file.";
|
||||
|
||||
sshKeyPaths = mkOpt (lib.types.listOf lib.types.str) [] "SSH Key paths to use.";
|
||||
};
|
||||
config = {
|
||||
home.packages = with pkgs; [
|
||||
age
|
||||
sops
|
||||
ssh-to-age
|
||||
];
|
||||
|
||||
sops = {
|
||||
inherit (config.mjallen.sops) defaultSopsFile;
|
||||
defaultSopsFormat = "yaml";
|
||||
|
||||
age = {
|
||||
generateKey = true;
|
||||
keyFile = "${config.home.homeDirectory}/.config/sops/age/keys.txt";
|
||||
sshKeyPaths = [ "${config.home.homeDirectory}/.ssh/id_ed25519" ] ++ config.mjallen.sops.sshKeyPaths;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
36
lib/examples/sops.nix
Normal file
36
lib/examples/sops.nix
Normal file
@@ -0,0 +1,36 @@
|
||||
{ config, lib, ... }:
|
||||
let
|
||||
inherit (lib.mjallen.module) mkModule mkOpt mkBoolOpt;
|
||||
in
|
||||
mkModule {
|
||||
name = "sops";
|
||||
description = "SOPS secret management";
|
||||
options = {
|
||||
defaultSopsFile = mkOpt lib.types.path null "Default sops file.";
|
||||
|
||||
generateAgeKey = mkBoolOpt true "Whether to automatically generate an age key if one doesn't exist.";
|
||||
|
||||
ageKeyPath = mkOpt (lib.types.nullOr lib.types.str) null "Custom path to the age key file. If null, will use the default path.";
|
||||
|
||||
sshKeyPaths = mkOpt (lib.types.listOf lib.types.str) [
|
||||
"/etc/ssh/ssh_host_ed25519_key"
|
||||
] "SSH Key paths to use.";
|
||||
|
||||
validateSopsFiles = mkBoolOpt false "Whether to validate that sops files exist.";
|
||||
};
|
||||
config = {
|
||||
sops = {
|
||||
inherit (config.mjallen.sops) defaultSopsFile validateSopsFiles;
|
||||
|
||||
age = {
|
||||
inherit (config.mjallen.sops) generateAgeKey;
|
||||
|
||||
keyFile = if config.mjallen.sops.ageKeyPath != null
|
||||
then config.mjallen.sops.ageKeyPath
|
||||
else "${config.users.users.${config.mjallen.user.name}.home}/.config/sops/age/keys.txt";
|
||||
|
||||
sshKeyPaths = config.mjallen.sops.sshKeyPaths;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
111
lib/examples/system-utils.nix
Normal file
111
lib/examples/system-utils.nix
Normal file
@@ -0,0 +1,111 @@
|
||||
{ inputs, ... }:
|
||||
let
|
||||
inherit (inputs.self.mjallen-lib.system.common)
|
||||
mkExtendedLib
|
||||
mkNixpkgsConfig
|
||||
mkHomeConfigs
|
||||
mkHomeManagerConfig
|
||||
mkSpecialArgs;
|
||||
in
|
||||
{
|
||||
# Example of creating NixOS configurations
|
||||
nixosConfigurations =
|
||||
let
|
||||
# Get all systems
|
||||
allSystems = inputs.self.mjallen-lib.file.scanSystems ../systems;
|
||||
|
||||
# Filter for NixOS systems
|
||||
nixosSystems = inputs.self.mjallen-lib.file.filterNixOSSystems allSystems;
|
||||
in
|
||||
inputs.nixpkgs.lib.mapAttrs' (
|
||||
name:
|
||||
{ system, hostname, ... }:
|
||||
let
|
||||
# Create extended lib with mjallen-lib
|
||||
extendedLib = mkExtendedLib inputs.self inputs.nixpkgs;
|
||||
|
||||
# Find matching home configurations for this system
|
||||
matchingHomes = mkHomeConfigs {
|
||||
flake = inputs.self;
|
||||
inherit system hostname;
|
||||
};
|
||||
|
||||
# Create home-manager configuration
|
||||
homeManagerConfig = mkHomeManagerConfig {
|
||||
inherit extendedLib inputs system matchingHomes;
|
||||
isNixOS = true;
|
||||
};
|
||||
in
|
||||
{
|
||||
name = hostname;
|
||||
value = inputs.nixpkgs.lib.nixosSystem {
|
||||
inherit system;
|
||||
|
||||
# Pass special arguments to modules
|
||||
specialArgs = mkSpecialArgs {
|
||||
inherit inputs hostname extendedLib;
|
||||
username = "mjallen";
|
||||
};
|
||||
|
||||
modules = [
|
||||
# Set lib to extended lib
|
||||
{ _module.args.lib = extendedLib; }
|
||||
|
||||
# Configure nixpkgs
|
||||
{
|
||||
nixpkgs = {
|
||||
inherit system;
|
||||
} // mkNixpkgsConfig inputs.self;
|
||||
}
|
||||
|
||||
# Import home-manager module
|
||||
inputs.home-manager.nixosModules.home-manager
|
||||
|
||||
# Auto-inject home configurations
|
||||
homeManagerConfig
|
||||
|
||||
# Import all nixos modules recursively
|
||||
../${system}/${hostname}
|
||||
] ++ (extendedLib.mjallen.file.importModulesRecursive ../modules/nixos);
|
||||
};
|
||||
}
|
||||
) nixosSystems;
|
||||
|
||||
# Example of creating home-manager configurations
|
||||
homeConfigurations =
|
||||
let
|
||||
# Get all homes
|
||||
allHomes = inputs.self.mjallen-lib.file.scanHomes ../homes;
|
||||
in
|
||||
inputs.nixpkgs.lib.mapAttrs' (
|
||||
name:
|
||||
{ system, username, hostname, userAtHost, path, ... }:
|
||||
let
|
||||
# Create extended lib with mjallen-lib
|
||||
extendedLib = mkExtendedLib inputs.self inputs.nixpkgs;
|
||||
in
|
||||
{
|
||||
name = userAtHost;
|
||||
value = inputs.home-manager.lib.homeManagerConfiguration {
|
||||
pkgs = import inputs.nixpkgs {
|
||||
inherit system;
|
||||
inherit ((mkNixpkgsConfig inputs.self)) config overlays;
|
||||
};
|
||||
|
||||
extraSpecialArgs = {
|
||||
inherit inputs hostname username system;
|
||||
inherit (inputs) self;
|
||||
lib = extendedLib;
|
||||
};
|
||||
|
||||
modules = [
|
||||
# Set lib to extended lib
|
||||
{ _module.args.lib = extendedLib; }
|
||||
|
||||
# Import the home configuration
|
||||
path
|
||||
] ++ (extendedLib.mjallen.file.importModulesRecursive ../modules/home);
|
||||
};
|
||||
}
|
||||
) allHomes;
|
||||
}
|
||||
127
lib/file/default.nix
Normal file
127
lib/file/default.nix
Normal file
@@ -0,0 +1,127 @@
|
||||
{ inputs, ... }@args:
|
||||
let
|
||||
# Get self from args or default to ../.. (the flake root)
|
||||
self = if args ? self then args.self else ../..;
|
||||
|
||||
inherit (inputs.nixpkgs.lib)
|
||||
genAttrs
|
||||
filterAttrs
|
||||
hasPrefix
|
||||
foldl'
|
||||
;
|
||||
in
|
||||
{
|
||||
# Read a file and return its contents
|
||||
readFile = path: builtins.readFile path;
|
||||
|
||||
# Check if a file exists
|
||||
pathExists = path: builtins.pathExists path;
|
||||
|
||||
# Import a nix file with error handling
|
||||
safeImport = path: default: if builtins.pathExists path then import path else default;
|
||||
|
||||
# Scan a directory and return directory names
|
||||
scanDir = path: builtins.attrNames (builtins.readDir path);
|
||||
|
||||
# Get a file path relative to the flake root (similar to Snowfall's get-file)
|
||||
getFile = relativePath: self + "/${relativePath}";
|
||||
|
||||
# Recursively discover and import all Nix modules in a directory tree
|
||||
importModulesRecursive =
|
||||
path:
|
||||
let
|
||||
# Helper function to recursively walk directories
|
||||
walkDir =
|
||||
currentPath:
|
||||
let
|
||||
currentEntries = builtins.readDir currentPath;
|
||||
entryNames = builtins.attrNames currentEntries;
|
||||
|
||||
# Get all directories that contain default.nix
|
||||
directoriesWithDefault = builtins.filter (
|
||||
name:
|
||||
currentEntries.${name} == "directory" && builtins.pathExists (currentPath + "/${name}/default.nix")
|
||||
) entryNames;
|
||||
|
||||
# Get ALL directories (to recurse into)
|
||||
allDirectories = builtins.filter (name: currentEntries.${name} == "directory") entryNames;
|
||||
|
||||
# Import directories that have default.nix
|
||||
directoryImports = map (name: currentPath + "/${name}") directoriesWithDefault;
|
||||
|
||||
# Recursively walk ALL subdirectories
|
||||
subDirImports = builtins.concatLists (map (dir: walkDir (currentPath + "/${dir}")) allDirectories);
|
||||
|
||||
in
|
||||
directoryImports ++ subDirImports;
|
||||
|
||||
in
|
||||
walkDir path;
|
||||
|
||||
# Recursively scan systems directory structure
|
||||
scanSystems =
|
||||
systemsPath:
|
||||
let
|
||||
systemArchs = builtins.attrNames (builtins.readDir systemsPath);
|
||||
|
||||
generateSystemConfigs =
|
||||
system:
|
||||
let
|
||||
systemPath = systemsPath + "/${system}";
|
||||
hosts = builtins.attrNames (builtins.readDir systemPath);
|
||||
in
|
||||
genAttrs hosts (hostname: {
|
||||
inherit system hostname;
|
||||
path = systemPath + "/${hostname}";
|
||||
});
|
||||
in
|
||||
foldl' (acc: system: acc // generateSystemConfigs system) { } systemArchs;
|
||||
|
||||
# Filter systems for NixOS (Linux)
|
||||
filterNixOSSystems =
|
||||
systems:
|
||||
filterAttrs (
|
||||
_name: { system, ... }: hasPrefix "x86_64-linux" system || hasPrefix "aarch64-linux" system
|
||||
) systems;
|
||||
|
||||
# Filter systems for Darwin (macOS)
|
||||
filterDarwinSystems =
|
||||
systems:
|
||||
filterAttrs (
|
||||
_name: { system, ... }: hasPrefix "aarch64-darwin" system || hasPrefix "x86_64-darwin" system
|
||||
) systems;
|
||||
|
||||
# Scan homes directory structure for home configurations
|
||||
scanHomes =
|
||||
homesPath:
|
||||
let
|
||||
systemArchs = builtins.attrNames (builtins.readDir homesPath);
|
||||
|
||||
generateHomeConfigs =
|
||||
system:
|
||||
let
|
||||
systemPath = homesPath + "/${system}";
|
||||
userAtHosts = builtins.attrNames (builtins.readDir systemPath);
|
||||
|
||||
parseUserAtHost =
|
||||
userAtHost:
|
||||
let
|
||||
# Split "username@hostname" into parts
|
||||
parts = builtins.split "@" userAtHost;
|
||||
username = builtins.head parts;
|
||||
hostname = builtins.elemAt parts 2; # After split: [username, "@", hostname]
|
||||
in
|
||||
{
|
||||
inherit
|
||||
system
|
||||
username
|
||||
hostname
|
||||
userAtHost
|
||||
;
|
||||
path = systemPath + "/${userAtHost}";
|
||||
};
|
||||
in
|
||||
genAttrs userAtHosts parseUserAtHost;
|
||||
in
|
||||
foldl' (acc: system: acc // generateHomeConfigs system) { } systemArchs;
|
||||
}
|
||||
98
lib/system/common.nix
Normal file
98
lib/system/common.nix
Normal file
@@ -0,0 +1,98 @@
|
||||
{ inputs }:
|
||||
let
|
||||
inherit (inputs.nixpkgs.lib) filterAttrs mapAttrs';
|
||||
in
|
||||
{
|
||||
mkExtendedLib = flake: nixpkgs: nixpkgs.lib.extend (final: prev: {
|
||||
mjallen = flake.mjallen-lib;
|
||||
});
|
||||
|
||||
mkNixpkgsConfig = flake: {
|
||||
overlays = builtins.attrValues flake.overlays;
|
||||
config = {
|
||||
allowAliases = false;
|
||||
allowUnfree = true;
|
||||
permittedInsecurePackages = [
|
||||
# Add any permitted insecure packages here
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
mkHomeConfigs =
|
||||
{
|
||||
flake,
|
||||
system,
|
||||
hostname,
|
||||
}:
|
||||
let
|
||||
inherit (flake.mjallen-lib.file) scanHomes;
|
||||
homesPath = ../../homes;
|
||||
allHomes = scanHomes homesPath;
|
||||
in
|
||||
filterAttrs (
|
||||
_name: homeConfig: homeConfig.system == system && homeConfig.hostname == hostname
|
||||
) allHomes;
|
||||
|
||||
mkHomeManagerConfig =
|
||||
{
|
||||
extendedLib,
|
||||
inputs,
|
||||
system,
|
||||
matchingHomes,
|
||||
isNixOS ? true,
|
||||
}:
|
||||
if matchingHomes != { } then
|
||||
{
|
||||
home-manager = {
|
||||
useGlobalPkgs = true;
|
||||
useUserPackages = true;
|
||||
extraSpecialArgs = {
|
||||
inherit inputs system;
|
||||
inherit (inputs) self;
|
||||
lib = extendedLib;
|
||||
};
|
||||
sharedModules = [
|
||||
{ _module.args.lib = extendedLib; }
|
||||
]
|
||||
++ (extendedLib.mjallen.file.importModulesRecursive ../../modules/home);
|
||||
users = mapAttrs' (_name: homeConfig: {
|
||||
name = homeConfig.username;
|
||||
value = {
|
||||
imports = [ homeConfig.path ];
|
||||
home = {
|
||||
inherit (homeConfig) username;
|
||||
homeDirectory = inputs.nixpkgs.lib.mkDefault (
|
||||
if isNixOS then "/home/${homeConfig.username}" else "/Users/${homeConfig.username}"
|
||||
);
|
||||
};
|
||||
}
|
||||
// (
|
||||
if isNixOS then
|
||||
{
|
||||
_module.args.username = homeConfig.username;
|
||||
}
|
||||
else
|
||||
{ }
|
||||
);
|
||||
}) matchingHomes;
|
||||
};
|
||||
}
|
||||
else
|
||||
{ };
|
||||
|
||||
mkSpecialArgs =
|
||||
{
|
||||
inputs,
|
||||
hostname,
|
||||
username,
|
||||
extendedLib,
|
||||
}:
|
||||
{
|
||||
inherit inputs hostname username;
|
||||
inherit (inputs) self;
|
||||
lib = extendedLib;
|
||||
namespace = "mjallen";
|
||||
format = "system";
|
||||
host = hostname;
|
||||
};
|
||||
}
|
||||
5
lib/system/default.nix
Normal file
5
lib/system/default.nix
Normal file
@@ -0,0 +1,5 @@
|
||||
{ inputs }:
|
||||
{
|
||||
# Common utilities used by system builders
|
||||
common = import ./common.nix { inherit inputs; };
|
||||
}
|
||||
Reference in New Issue
Block a user