{ config, lib, ... }: let mkHost = { name, displays ? { }, input ? { }, users ? { }, imports ? [ ], stateVersion ? "24.05", }: { meta.host = { inherit displays input name users ; }; inherit imports; networking.hostName = name; system.stateVersion = stateVersion; }; mkCaddyReverseProxy = { domain, port, extraHeaders ? [ ], extraConfigText ? "", }: let headerLines = map (header: " header_up ${header.name} ${header.value}") extraHeaders; extraConfigLines = map (line: " ${line}") ( lib.filter (line: line != "") (lib.splitString "\n" extraConfigText) ); bodyLines = headerLines ++ extraConfigLines; body = lib.concatStringsSep "\n" bodyLines; in { services.caddy.virtualHosts.${domain}.extraConfig = if body == "" then "reverse_proxy :${toString port}" else '' reverse_proxy :${toString port} { ${body} } ''; }; mkHostUser = { account, homeImports, needsPassword ? false, stateVersion ? "24.05", }: { config, pkgs, ... }: let name = account.name; primaryEmails = lib.filter (email: email.primary) (builtins.attrValues account.emails); in { assertions = [ { assertion = builtins.length primaryEmails == 1; message = "User ${name} must define exactly one primary email entry."; } ]; programs.zsh.enable = true; sops.secrets = lib.optionalAttrs needsPassword { "hashed-password-${name}".neededForUsers = true; }; users.users.${name} = { name = account.name; home = account.homeDirectory; isNormalUser = true; shell = pkgs.zsh; extraGroups = [ "wheel" "networkmanager" ]; } // lib.optionalAttrs needsPassword { hashedPasswordFile = config.sops.secrets."hashed-password-${name}".path; }; home-manager.users.${name} = { imports = homeImports; meta = { host = config.meta.host; user = account; }; home = { username = account.name; homeDirectory = account.homeDirectory; inherit stateVersion; }; }; }; in { options.meta.lib.mkHost = lib.mkOption { type = lib.types.raw; description = "Internal host constructor shared between flake-parts modules."; internal = true; readOnly = true; }; options.meta.lib.mkCaddyReverseProxy = lib.mkOption { type = lib.types.raw; description = "Internal Caddy reverse proxy helper shared between flake-parts modules."; internal = true; readOnly = true; }; options.meta.lib.mkHostUser = lib.mkOption { type = lib.types.raw; description = "Internal helper for explicit per-host user assembly."; internal = true; readOnly = true; }; options.meta.lib.users = lib.mkOption { type = lib.types.attrs; description = "Canonical user attrsets shared by host definitions."; internal = true; readOnly = true; }; config.meta.lib = { inherit mkCaddyReverseProxy mkHost mkHostUser ; }; }