This commit is contained in:
mjallen18
2026-03-18 20:39:24 -05:00
parent 4a7b2f835e
commit 46b249560f
18 changed files with 142 additions and 917 deletions

View File

@@ -1,3 +0,0 @@

 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ

View File

@@ -1,62 +0,0 @@
{ inputs }:
let
inherit (inputs.nixpkgs.lib)
concatLists
concatMapStrings
foldl'
genList
hasSuffix
imap0
length
mod
nameValuePair
stringToCharacters
sublist
substring
take
;
in
rec {
base64Table = builtins.listToAttrs (
imap0 (i: c: nameValuePair c i) (
# The '=' is included so the main algorithm doesn't fail before we can trim the result
stringToCharacters "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
)
);
# Generated using python3:
# print(''.join([ chr(n) for n in range(1, 256) ]), file=open('ascii', 'w'))
ascii = builtins.readFile ./ascii;
decode =
str:
let
paddingCount =
if hasSuffix "==" str then
2
else if hasSuffix "=" str then
1
else
0;
numbers64 = map (c: base64Table.${c}) (stringToCharacters str);
allBytes = concatLists (
genList (
i:
let
v = foldl' (acc: el: acc * 64 + el) 0 (sublist (i * 4) 4 numbers64);
in
[
(mod (v / 256 / 256) 256)
(mod (v / 256) 256)
(mod v 256)
]
) (length numbers64 / 4)
);
finalBytes = take (length allBytes - paddingCount) allBytes;
in
concatMapStrings (n: substring (n - 1) 1 ascii) finalBytes;
}

View File

@@ -1,22 +1,8 @@
{ 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 reverse proxy utilities
reverseproxy = import ./reverseproxy { inherit inputs; };
# Import examples
examples = import ./examples { inherit inputs; };
# Import versioning utilities
versioning = import ./versioning {
lib = inputs.nixpkgs.lib;
inherit inputs;

View File

@@ -1,8 +0,0 @@
{ ... }:
{
# Import all examples
sops = import ./sops.nix;
homeSops = import ./home-sops.nix;
fileUtils = import ./file-utils.nix;
systemUtils = import ./system-utils.nix;
}

View File

@@ -1,60 +0,0 @@
{ lib, namespace, ... }:
let
inherit (lib.${namespace}.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;
}

View File

@@ -1,40 +0,0 @@
{
config,
lib,
pkgs,
namespace,
...
}:
let
inherit (lib.${namespace}.module) mkModule mkOpt;
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.${namespace}.sops) defaultSopsFile;
defaultSopsFormat = "yaml";
age = {
generateKey = true;
keyFile = "${config.home.homeDirectory}/.config/sops/age/keys.txt";
sshKeyPaths = [
"${config.home.homeDirectory}/.ssh/id_ed25519"
]
++ config.${namespace}.sops.sshKeyPaths;
};
};
};
}

View File

@@ -1,117 +0,0 @@
# Example usage of the reverse proxy utilities
{ lib, namespace, ... }:
let
inherit (lib.${namespace} - lib.reverseproxy)
mkReverseProxy
mkReverseProxies
templates
middlewares
urls
;
in
{
# Example 1: Simple reverse proxy for a local service
simpleProxy = mkReverseProxy {
name = "myapp";
subdomain = "myapp";
url = "http://127.0.0.1:3000";
};
# Example 2: Authenticated service with custom middlewares
authProxy = mkReverseProxy {
name = "admin-panel";
subdomain = "admin";
url = "http://127.0.0.1:8080";
middlewares = middlewares.authBasic;
};
# Example 3: Container-based service
containerProxy = mkReverseProxy {
name = "nextcloud";
subdomain = "cloud";
url = urls.container "nextcloud" 80;
middlewares = middlewares.basic;
};
# Example 4: Multiple proxies at once
multipleProxies = mkReverseProxies [
{
name = "grafana";
subdomain = "grafana";
url = urls.localhost 3000;
middlewares = middlewares.authBasic;
}
{
name = "prometheus";
subdomain = "prometheus";
url = urls.localhost 9090;
middlewares = middlewares.internal;
}
{
name = "alertmanager";
subdomain = "alerts";
url = urls.localhost 9093;
middlewares = middlewares.authBasic;
}
];
# Example 5: Using templates for common patterns
webappExample = templates.webapp {
name = "webapp";
subdomain = "app";
port = 8080;
};
authWebappExample = templates.authWebapp {
name = "secure-app";
subdomain = "secure";
port = 9000;
};
containerExample = templates.containerService {
name = "gitea";
subdomain = "git";
containerName = "gitea";
port = 3000;
};
internalExample = templates.internalService {
name = "internal-api";
subdomain = "api-internal";
port = 8000;
};
# Example 6: Custom domain and advanced configuration
customProxy = mkReverseProxy {
name = "custom-service";
subdomain = "custom";
url = "http://10.0.1.100:8080";
domain = "example.com";
priority = 20;
rule = "Host(`custom.example.com`) && PathPrefix(`/api`)";
middlewares = [
"crowdsec"
"whitelist-geoblock"
"rate-limit"
];
};
# Example usage in a Traefik configuration:
#
# mjallen.services.traefik = {
# enable = true;
# extraServices = multipleProxies.extraServices;
# extraRouters = multipleProxies.extraRouters;
# };
#
# Or for individual proxies:
#
# mjallen.services.traefik = {
# enable = true;
# extraServices = [ simpleProxy.service ];
# extraRouters = [{
# inherit (simpleProxy.router) subdomain entryPoints middlewares;
# service = simpleProxy.router.service;
# }];
# };
}

View File

@@ -1,45 +0,0 @@
{
config,
lib,
namespace,
...
}:
let
inherit (lib.${namespace}.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.${namespace}.sops) defaultSopsFile validateSopsFiles;
age = {
inherit (config.${namespace}.sops) generateAgeKey;
keyFile =
if config.${namespace}.sops.ageKeyPath != null then
config.${namespace}.sops.ageKeyPath
else
"${config.users.users.${config.${namespace}.user.name}.home}/.config/sops/age/keys.txt";
sshKeyPaths = config.${namespace}.sops.sshKeyPaths;
};
};
};
}

View File

@@ -1,132 +0,0 @@
{ inputs, namespace, ... }:
let
inherit (inputs.self.${namespace} - lib.system.common)
mkExtendedLib
mkNixpkgsConfig
mkHomeConfigs
mkHomeManagerConfig
mkSpecialArgs
;
in
{
# Example of creating NixOS configurations
nixosConfigurations =
let
# Get all systems
allSystems = inputs.self.${namespace} - lib.file.scanSystems ../systems;
# Filter for NixOS systems
nixosSystems = inputs.self.${namespace} - 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.${namespace}.file.importModulesRecursive ../modules/nixos);
};
}
) nixosSystems;
# Example of creating home-manager configurations
homeConfigurations =
let
# Get all homes
allHomes = inputs.self.${namespace} - 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.${namespace}.file.importModulesRecursive ../modules/home);
};
}
) allHomes;
}

View File

@@ -14,8 +14,6 @@ let
mkDefault
mkForce
;
base64Lib = import ../base64 { inherit inputs; };
in
rec {
@@ -26,7 +24,9 @@ rec {
mod: mod.systems or [ ] == [ ] || builtins.elem system (mod.systems or [ ])
) modules;
# Create a module with common options
# Create a NixOS module with standard options (enable, port, reverseProxy,
# firewall, user, postgresql, redis) and optional caller-supplied options and
# config. All config is gated behind `cfg.enable`.
mkModule =
{
name,
@@ -51,9 +51,6 @@ rec {
defaultConfig = {
# Caddy reverse proxy: when reverseProxy.enable = true, contribute this
# service's named-matcher block into the shared wildcard virtual host.
# The TLS block stays in the caddy module itself; all services merge
# their handle blocks into the same "*.${domain}" extraConfig via the
# lines type (which concatenates automatically).
services.caddy.virtualHosts."*.${cfg.reverseProxy.domain}" = lib.mkIf cfg.reverseProxy.enable {
extraConfig = ''
@${name} host ${fqdn}
@@ -79,20 +76,15 @@ rec {
groups.${name} = { };
};
systemd.services.${serviceName} = {
requires = [
"media-nas-main.mount"
# "openvpn-us.protonvpn.udp.service"
];
after = lib.mkForce [
"media-nas-main.mount"
# "openvpn-us.protonvpn.udp.service"
];
# serviceConfig = {
# NetworkNamespacePath = lib.mkIf cfg.enableVpn "/run/netns/vpn";
# # Consider also setting DNS *inside* the netns (see note below).
# };
};
# Ensure the service waits for the filesystem that hosts configDir and
# dataDir to be mounted before starting. RequiresMountsFor is the
# idiomatic systemd way to express this: if the paths live on the root
# filesystem the directive is silently ignored, so it is safe on every
# host — not just the NAS.
systemd.services.${serviceName}.unitConfig.RequiresMountsFor = [
cfg.configDir
cfg.dataDir
];
services = {
postgresql = lib.mkIf cfg.configureDb {
@@ -110,12 +102,6 @@ rec {
port = cfg.redis.port;
};
};
# systemd.tmpfiles.rules = [
# "d ${cfg.configDir} 0700 ${name} ${name} - -"
# # "d ${cfg.configDir}/server-files 0775 ${name} ${name} - -"
# # "d ${cfg.configDir}/user-files 0775 ${name} ${name} - -"
# ];
};
in
{ lib, ... }:
@@ -134,44 +120,42 @@ rec {
options = {
enable = lib.mkEnableOption description;
port = mkOpt types.int 80 "Port for ${name} to be hosted on";
port = mkOpt types.int 80 "Port for ${name} to listen on";
configDir = mkOpt types.str "/media/nas/main/appdata" "Path to the config dir";
configDir = mkOpt types.str "/var/lib/${name}" "Path to the config directory";
dataDir = mkOpt types.str "/media/nas/main" "Path to the data dir";
dataDir = mkOpt types.str "/var/lib/${name}/data" "Path to the data directory";
createUser = mkBoolOpt false "create a user for this module/service";
createUser = mkBoolOpt false "Create a dedicated system user for this service";
configureDb = mkBoolOpt false "Manage db for this service";
configureDb = mkBoolOpt false "Manage a PostgreSQL database for this service";
environmentFile = mkOpt types.str "" "Environment File";
environmentFile =
mkOpt (types.nullOr types.str) null
"Path to an environment file (EnvironmentFile=)";
puid = mkOpt types.str "911" "default user id";
puid = mkOpt types.str "911" "User ID for container-based services";
pgid = mkOpt types.str "1000" "default group id";
pgid = mkOpt types.str "100" "Group ID for container-based services";
timeZone = mkOpt types.str "America/Chicago" "default timezone";
timeZone = mkOpt types.str "UTC" "Timezone for container-based services";
listenAddress = mkOpt types.str "0.0.0.0" "Environment File";
listenAddress = mkOpt types.str "0.0.0.0" "Listen address";
openFirewall = mkBoolOpt true "Open the firewall";
enableVpn = mkBoolOpt true "Enable routing through VPN";
openFirewall = mkBoolOpt true "Open firewall ports for this service";
redis = {
enable = lib.mkEnableOption "enable redis";
port = mkOpt types.int 80 "Port for ${name} redis to be hosted on";
enable = lib.mkEnableOption "a dedicated Redis server for this service";
port = mkOpt types.int 6379 "Redis port for ${name}";
};
hashedPassword =
mkOpt (types.nullOr types.str)
"$y$j9T$EkPXmsmIMFFZ.WRrBYCxS1$P0kwo6e4.WM5DsqUcEqWC3MrZp5KfCjxffraMFZWu06"
"Hashed password for code-server authentication";
mkOpt (types.nullOr types.str) null
"Hashed password (e.g. for web-based authentication)";
extraEnvironment =
mkOpt (types.attrsOf types.str) { }
"Extra environment variables for code-server";
"Extra environment variables passed to the service";
reverseProxy = mkReverseProxyOpt name;
}
@@ -181,58 +165,15 @@ rec {
};
};
# container
mkContainer =
{
name,
localAddress ? "127.0.0.1",
ports ? [ 80 ],
bindMounts ? { },
config ? { },
}:
{ lib, ... }:
{
containers.${name} = {
inherit localAddress bindMounts;
config = config // {
networking = {
firewall = {
enable = true;
allowedTCPPorts = ports;
};
# Use systemd-resolved inside the container
# Workaround for bug https://github.com/NixOS/nixpkgs/issues/162686
useHostResolvConf = lib.mkForce false;
};
services.resolved.enable = true;
system.stateVersion = "23.11";
};
autoStart = lib.mkDefault true;
privateNetwork = lib.mkDefault true;
hostAddress = lib.mkDefault "10.0.1.3";
};
networking = {
nat.forwardPorts = map (port: {
destination = lib.mkDefault "${localAddress}:${toString port}";
sourcePort = lib.mkDefault port;
}) ports;
firewall = {
allowedTCPPorts = ports;
allowedUDPPorts = ports;
};
};
};
# Migrated mjallen utilities
# ---------------------------------------------------------------------------
# Option creation helpers
# ---------------------------------------------------------------------------
mkOpt =
type: default: description:
mkOption { inherit type default description; };
mkOpt' = type: default: mkOpt type default null;
mkOpt' = type: default: mkOpt type default "";
mkBoolOpt = mkOpt types.bool;
@@ -245,26 +186,28 @@ rec {
domain = mkOpt types.str "mjallen.dev" "Base domain for the reverse proxy";
# Override the upstream URL if the backend is not on localhost at cfg.port.
# Leave empty to use http://127.0.0.1:<port> automatically.
upstreamUrl =
mkOpt (types.nullOr types.str) null
"Override upstream URL (e.g. for services on a different host). Defaults to http://127.0.0.1:<port>.";
"Override upstream URL (e.g. for a service on a different host). Defaults to http://127.0.0.1:<port>.";
# Extra Caddyfile directives inserted inside the virtual host block.
extraCaddyConfig = mkOpt types.lines "" "Extra Caddyfile directives for this virtual host block";
extraCaddyConfig = mkOpt types.lines "" "Extra Caddyfile directives inside this virtual host block";
};
# Standard enable/disable patterns
# ---------------------------------------------------------------------------
# Convenience shorthands
# ---------------------------------------------------------------------------
enabled = {
enable = true;
};
disabled = {
enable = false;
};
# ---------------------------------------------------------------------------
# String utilities
# ---------------------------------------------------------------------------
capitalize =
s:
let
@@ -272,10 +215,16 @@ rec {
in
if len == 0 then "" else (toUpper (substring 0 1 s)) + (substring 1 len s);
# ---------------------------------------------------------------------------
# Boolean utilities
# ---------------------------------------------------------------------------
boolToNum = bool: if bool then 1 else 0;
# ---------------------------------------------------------------------------
# Attribute manipulation utilities
# ---------------------------------------------------------------------------
default-attrs = mapAttrs (_key: mkDefault);
force-attrs = mapAttrs (_key: mkForce);
@@ -284,4 +233,3 @@ rec {
nested-force-attrs = mapAttrs (_key: force-attrs);
}
// base64Lib

View File

@@ -1,220 +0,0 @@
{ inputs }:
let
inherit (inputs.nixpkgs.lib)
listToAttrs
nameValuePair
;
in
rec {
# Create a service configuration for Traefik
mkService =
{
name,
url,
loadBalancer ? { },
}:
{
inherit name url;
config = {
loadBalancer = {
servers = [ { inherit url; } ];
}
// loadBalancer;
};
};
# Create a router configuration for Traefik
mkRouter =
{
subdomain,
domain ? "mjallen.dev",
service,
entryPoints ? [ "websecure" ],
middlewares ? [
"crowdsec"
"whitelist-geoblock"
],
priority ? null,
rule ? null,
tls ? {
certResolver = "letsencrypt";
},
}:
{
inherit
subdomain
service
entryPoints
middlewares
;
config = {
inherit
entryPoints
service
middlewares
tls
;
rule = if rule != null then rule else "Host(`${subdomain}.${domain}`)";
}
// (if priority != null then { inherit priority; } else { });
};
# Create both service and router for a simple reverse proxy setup
mkReverseProxy =
{
name,
subdomain,
url,
domain ? "mjallen.dev",
entryPoints ? [ "websecure" ],
middlewares ? [
"crowdsec"
"whitelist-geoblock"
],
priority ? null,
rule ? null,
tls ? {
certResolver = "letsencrypt";
},
loadBalancer ? { },
}:
{
service = mkService {
inherit name url loadBalancer;
};
router = mkRouter {
inherit
subdomain
domain
entryPoints
middlewares
priority
rule
tls
;
service = name;
};
};
# Convert a list of services to the format expected by Traefik module
servicesToConfig =
services: listToAttrs (map (service: nameValuePair service.name service.config) services);
# Convert a list of routers to the format expected by Traefik module
routersToConfig =
routers: listToAttrs (map (router: nameValuePair router.subdomain router.config) routers);
# Helper to create multiple reverse proxies at once
mkReverseProxies =
proxies:
let
results = map mkReverseProxy proxies;
services = map (result: result.service) results;
routers = map (result: result.router) results;
in
{
services = servicesToConfig services;
routers = routersToConfig routers;
extraServices = services;
extraRouters = map (router: {
inherit (router) subdomain entryPoints middlewares;
service = router.service;
}) routers;
};
# Common middleware configurations
middlewares = {
# Authentication middleware
auth = [ "authentik" ];
# Basic security (default)
basic = [
"crowdsec"
"whitelist-geoblock"
];
# Internal only access
internal = [
"crowdsec"
"whitelist-geoblock"
"internal-ipallowlist"
];
# WebSocket support
websocket = [
"crowdsec"
"whitelist-geoblock"
"onlyoffice-websocket"
];
# Authenticated with basic security
authBasic = [
"crowdsec"
"whitelist-geoblock"
"authentik"
];
};
# Common service URL builders
urls = {
# Local container service
container =
containerName: port: "http://\${config.containers.${containerName}.localAddress}:${toString port}";
# Local host service
localhost = port: "http://127.0.0.1:${toString port}";
# Network service
network = ip: port: "http://${ip}:${toString port}";
# Server IP service (using your server IP pattern)
server = port: "http://\${serverIp}:${toString port}";
};
# Pre-configured reverse proxy templates
templates = {
# Standard web application
webapp =
{ port, ... }@args:
mkReverseProxy (
{
url = urls.localhost port;
middlewares = middlewares.basic;
}
// args
);
# Authenticated web application
authWebapp =
{ port, ... }@args:
mkReverseProxy (
{
url = urls.localhost port;
middlewares = middlewares.authBasic;
}
// args
);
# Container-based service
containerService =
{ containerName, port, ... }@args:
mkReverseProxy (
{
url = urls.container containerName port;
middlewares = middlewares.basic;
}
// args
);
# Internal-only service
internalService =
{ port, ... }@args:
mkReverseProxy (
{
url = urls.localhost port;
middlewares = middlewares.internal;
}
// args
);
};
}

View File

@@ -1,103 +0,0 @@
{ inputs, namespace }:
let
inherit (inputs.nixpkgs.lib) filterAttrs mapAttrs';
in
{
mkExtendedLib =
flake: nixpkgs:
nixpkgs.lib.extend (
_final: _prev: {
mjallen = flake.${namespace} - lib;
}
);
mkNixpkgsConfig = flake: {
overlays = builtins.attrValues flake.overlays;
config = {
allowAliases = false;
allowUnfree = true;
permittedInsecurePackages = [
# Add any permitted insecure packages here
"mbedtls-2.28.10"
];
};
};
mkHomeConfigs =
{
flake,
system,
hostname,
}:
let
inherit (flake.${namespace} - 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.${namespace}.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;
};
}

View File

@@ -1,5 +0,0 @@
{ inputs }:
{
# Common utilities used by system builders
common = import ./common.nix { inherit inputs; };
}