From 6770bc76a2402b753f7c5c261d141c00a93c66e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Jane=C5=BEi=C4=8D?= Date: Sun, 12 Apr 2026 21:27:43 +0000 Subject: [PATCH] refactor: mkHost load-all infrastructure and convert simple features --- features/claude.nix | 23 +++++++--- features/direnv/default.nix | 48 ++++++++++++-------- features/docker.nix | 19 +++++--- features/filedrop.nix | 82 ++++++++++++++++++++--------------- features/gaming.nix | 23 ++++++---- features/gnupg.nix | 39 ++++++++++++++--- features/harmonia/default.nix | 58 ++++++++++++++----------- features/initrd-ssh.nix | 58 +++++++++++++------------ features/localisation.nix | 29 ++++++++----- features/neovim.nix | 34 ++++++++++----- features/networkmanager.nix | 23 +++++++--- features/nix-ld.nix | 15 +++++-- features/nix-settings.nix | 71 ++++++++++++++++++++++++++++++ features/openssh.nix | 13 ++++-- features/printing.nix | 23 +++++++--- features/remote-base.nix | 21 ++++++--- features/tailscale.nix | 19 +++++--- lib/mkHost.nix | 67 ++++++++++++++++++---------- 18 files changed, 455 insertions(+), 210 deletions(-) create mode 100644 features/nix-settings.nix diff --git a/features/claude.nix b/features/claude.nix index 6f5fd2a..23a5c7b 100644 --- a/features/claude.nix +++ b/features/claude.nix @@ -1,10 +1,21 @@ { - home = - { pkgs, ... }: + nixos = + { lib, ... }: { - home.packages = [ - pkgs.claude-code - pkgs.mcp-nixos - ]; + options.features.claude.enable = lib.mkEnableOption "claude"; + }; + + home = + { pkgs, lib, osConfig, ... }: + let + cfg = osConfig.features.claude; + in + { + config = lib.mkIf cfg.enable { + home.packages = [ + pkgs.claude-code + pkgs.mcp-nixos + ]; + }; }; } diff --git a/features/direnv/default.nix b/features/direnv/default.nix index a50c083..06af9d3 100644 --- a/features/direnv/default.nix +++ b/features/direnv/default.nix @@ -1,26 +1,40 @@ { nixos = - { inputs, ... }: + { config, lib, inputs, ... }: + let + cfg = config.features.direnv; + in { - nix.registry.dev = { - from = { - type = "indirect"; - id = "dev"; - }; - to = { - type = "path"; - path = inputs.self.outPath; + options.features.direnv.enable = lib.mkEnableOption "direnv"; + + config = lib.mkIf cfg.enable { + nix.registry.dev = { + from = { + type = "indirect"; + id = "dev"; + }; + to = { + type = "path"; + path = inputs.self.outPath; + }; }; }; }; - home = _: { - programs.direnv = { - enable = true; - nix-direnv.enable = true; - config.global.hide_env_diff = true; - }; + home = + { lib, osConfig, ... }: + let + cfg = osConfig.features.direnv; + in + { + config = lib.mkIf cfg.enable { + programs.direnv = { + enable = true; + nix-direnv.enable = true; + config.global.hide_env_diff = true; + }; - xdg.configFile."direnv/lib/use_dev.sh".source = ./use_dev.sh; - }; + xdg.configFile."direnv/lib/use_dev.sh".source = ./use_dev.sh; + }; + }; } diff --git a/features/docker.nix b/features/docker.nix index 16440ee..fd7b7f3 100644 --- a/features/docker.nix +++ b/features/docker.nix @@ -1,12 +1,19 @@ { nixos = - { user, ... }: + { config, lib, user, ... }: + let + cfg = config.features.docker; + in { - virtualisation.docker = { - enable = true; - logDriver = "json-file"; - }; + options.features.docker.enable = lib.mkEnableOption "docker"; - users.users.${user}.extraGroups = [ "docker" ]; + config = lib.mkIf cfg.enable { + virtualisation.docker = { + enable = true; + logDriver = "json-file"; + }; + + users.users.${user}.extraGroups = [ "docker" ]; + }; }; } diff --git a/features/filedrop.nix b/features/filedrop.nix index 4cebf26..fe867b4 100644 --- a/features/filedrop.nix +++ b/features/filedrop.nix @@ -1,42 +1,56 @@ { nixos = - { config, userKeys, ... }: + { config, lib, userKeys, ... }: + let + cfg = config.features.filedrop; + in { - sops.secrets.filedrop-authorized-keys = { - sopsFile = ../secrets/floo.yaml; - mode = "0444"; + options.features.filedrop = { + enable = lib.mkEnableOption "filedrop sftp service"; + + sopsFile = lib.mkOption { + type = lib.types.path; + + }; }; - users.groups.filedrop = { - members = [ "matej" ]; + config = lib.mkIf cfg.enable { + sops.secrets.filedrop-authorized-keys = { + inherit (cfg) sopsFile; + mode = "0444"; + }; + + users.groups.filedrop = { + members = [ "matej" ]; + }; + + users.users.filedrop = { + isSystemUser = true; + group = "filedrop"; + home = "/home/filedrop"; + shell = "/run/current-system/sw/bin/nologin"; + openssh.authorizedKeys.keys = userKeys.sshAuthorizedKeys; + }; + + # chroot dir must be root-owned; incoming is writable by filedrop + systemd.tmpfiles.rules = [ + "d /home/filedrop 0755 root root -" + "d /home/filedrop/incoming 2775 filedrop filedrop -" + "a+ /home/filedrop/incoming - - - - group:filedrop:rwx" + "a+ /home/filedrop/incoming - - - - default:group:filedrop:rwx" + "a+ /home/filedrop/incoming - - - - default:mask::rwx" + "L /home/matej/filedrop - - - - /home/filedrop/incoming" + ]; + + # relaxed umask so default acl takes full effect + services.openssh.extraConfig = '' + Match User filedrop + ForceCommand internal-sftp -u 0002 + ChrootDirectory /home/filedrop + AuthorizedKeysFile /etc/ssh/authorized_keys.d/filedrop %h/.ssh/authorized_keys ${config.sops.secrets.filedrop-authorized-keys.path} + AllowTcpForwarding no + X11Forwarding no + ''; }; - - users.users.filedrop = { - isSystemUser = true; - group = "filedrop"; - home = "/home/filedrop"; - shell = "/run/current-system/sw/bin/nologin"; - openssh.authorizedKeys.keys = userKeys.sshAuthorizedKeys; - }; - - # chroot dir must be root-owned; incoming is writable by filedrop - systemd.tmpfiles.rules = [ - "d /home/filedrop 0755 root root -" - "d /home/filedrop/incoming 2775 filedrop filedrop -" - "a+ /home/filedrop/incoming - - - - group:filedrop:rwx" - "a+ /home/filedrop/incoming - - - - default:group:filedrop:rwx" - "a+ /home/filedrop/incoming - - - - default:mask::rwx" - "L /home/matej/filedrop - - - - /home/filedrop/incoming" - ]; - - # relaxed umask so default acl takes full effect - services.openssh.extraConfig = '' - Match User filedrop - ForceCommand internal-sftp -u 0002 - ChrootDirectory /home/filedrop - AuthorizedKeysFile /etc/ssh/authorized_keys.d/filedrop %h/.ssh/authorized_keys ${config.sops.secrets.filedrop-authorized-keys.path} - AllowTcpForwarding no - X11Forwarding no - ''; }; } diff --git a/features/gaming.nix b/features/gaming.nix index feaf7e7..b4e07c3 100644 --- a/features/gaming.nix +++ b/features/gaming.nix @@ -1,14 +1,21 @@ { nixos = - { pkgs, ... }: + { config, lib, pkgs, ... }: + let + cfg = config.features.gaming; + in { - programs.steam = { - enable = true; - remotePlay.openFirewall = true; - dedicatedServer.openFirewall = true; - localNetworkGameTransfers.openFirewall = true; - }; + options.features.gaming.enable = lib.mkEnableOption "gaming"; - environment.systemPackages = [ pkgs.prismlauncher ]; + config = lib.mkIf cfg.enable { + programs.steam = { + enable = true; + remotePlay.openFirewall = true; + dedicatedServer.openFirewall = true; + localNetworkGameTransfers.openFirewall = true; + }; + + environment.systemPackages = [ pkgs.prismlauncher ]; + }; }; } diff --git a/features/gnupg.nix b/features/gnupg.nix index e39f156..8647bc4 100644 --- a/features/gnupg.nix +++ b/features/gnupg.nix @@ -1,9 +1,36 @@ { - nixos = _: { - programs.gnupg.agent = { - enable = true; - enableSSHSupport = true; - enableExtraSocket = true; + nixos = + { config, lib, pkgs, ... }: + let + cfg = config.features.gnupg; + in + { + options.features.gnupg = { + enable = lib.mkEnableOption "gnupg"; + + yubikey.enable = lib.mkOption { + type = lib.types.bool; + default = false; + }; + }; + + config = lib.mkIf cfg.enable (lib.mkMerge [ + { + programs.gnupg.agent = { + enable = true; + enableSSHSupport = true; + enableExtraSocket = true; + }; + } + + (lib.mkIf cfg.yubikey.enable { + environment.systemPackages = with pkgs; [ + yubikey-personalization + yubikey-manager + ]; + + services.pcscd.enable = true; + }) + ]); }; - }; } diff --git a/features/harmonia/default.nix b/features/harmonia/default.nix index 3d842f4..a29a0b5 100644 --- a/features/harmonia/default.nix +++ b/features/harmonia/default.nix @@ -1,12 +1,14 @@ { nixos = { - pkgs, config, + lib, + pkgs, inputs, ... }: let + cfg = config.features.harmonia; hosts = [ "fw16" "tower" @@ -17,34 +19,38 @@ flakeRef = inputs.self.outPath; in { - services.harmonia.cache = { - enable = true; - signKeyPaths = [ config.sops.secrets.nix-signing-key.path ]; - }; + options.features.harmonia.enable = lib.mkEnableOption "harmonia"; - networking.firewall.interfaces."tailscale0".allowedTCPPorts = [ 5000 ]; - - systemd.services.cache-builder = { - description = "Build all host closures for binary cache"; - serviceConfig = { - Type = "oneshot"; - ExecStart = "${pkgs.bash}/bin/bash ${./cache-builder.sh}"; + config = lib.mkIf cfg.enable { + services.harmonia.cache = { + enable = true; + signKeyPaths = [ config.sops.secrets.nix-signing-key.path ]; }; - environment = { - FLAKE_REF = flakeRef; - HOSTS = builtins.concatStringsSep " " hosts; - GC_ROOT_DIR = "/nix/var/nix/gcroots/cache-builder"; - }; - path = [ config.nix.package ]; - }; - systemd.timers.cache-builder = { - description = "Periodically build all host closures"; - wantedBy = [ "timers.target" ]; - timerConfig = { - OnUnitActiveSec = "15min"; - OnBootSec = "5min"; - Persistent = true; + networking.firewall.interfaces."tailscale0".allowedTCPPorts = [ 5000 ]; + + systemd.services.cache-builder = { + description = "Build all host closures for binary cache"; + serviceConfig = { + Type = "oneshot"; + ExecStart = "${pkgs.bash}/bin/bash ${./cache-builder.sh}"; + }; + environment = { + FLAKE_REF = flakeRef; + HOSTS = builtins.concatStringsSep " " hosts; + GC_ROOT_DIR = "/nix/var/nix/gcroots/cache-builder"; + }; + path = [ config.nix.package ]; + }; + + systemd.timers.cache-builder = { + description = "Periodically build all host closures"; + wantedBy = [ "timers.target" ]; + timerConfig = { + OnUnitActiveSec = "15min"; + OnBootSec = "5min"; + Persistent = true; + }; }; }; }; diff --git a/features/initrd-ssh.nix b/features/initrd-ssh.nix index 23e7056..10b65a0 100644 --- a/features/initrd-ssh.nix +++ b/features/initrd-ssh.nix @@ -2,6 +2,7 @@ nixos = { lib, config, ... }: let + cfg = config.features.initrd-ssh; keyDir = "/etc/secrets/initrd"; mkIpString = @@ -15,44 +16,45 @@ "${address}::${gateway}:${netmask}::${interface}:none"; in { - options = { - initrd-ssh = { - ip = { - enable = lib.mkEnableOption "static IP for initrd (otherwise DHCP)"; + options.features.initrd-ssh = { + enable = lib.mkEnableOption "initrd ssh"; - address = lib.mkOption { - type = lib.types.str; - }; + ip = { + enable = lib.mkEnableOption "static IP for initrd (otherwise DHCP)"; - gateway = lib.mkOption { - type = lib.types.str; - }; - - netmask = lib.mkOption { - type = lib.types.str; - default = "255.255.255.0"; - }; - - interface = lib.mkOption { - type = lib.types.str; - }; + address = lib.mkOption { + type = lib.types.str; }; - authorizedKeys = lib.mkOption { - type = lib.types.listOf lib.types.str; - default = [ ]; + gateway = lib.mkOption { + type = lib.types.str; }; - networkModule = lib.mkOption { + netmask = lib.mkOption { + type = lib.types.str; + default = "255.255.255.0"; + }; + + interface = lib.mkOption { type = lib.types.str; }; }; + + authorizedKeys = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ ]; + }; + + networkModule = lib.mkOption { + type = lib.types.str; + }; }; - config = { - boot.initrd.kernelModules = [ config.initrd-ssh.networkModule ]; - boot.kernelParams = lib.mkIf config.initrd-ssh.ip.enable [ - "ip=${mkIpString config.initrd-ssh.ip}" + config = lib.mkIf cfg.enable { + boot.initrd.availableKernelModules = [ cfg.networkModule ]; + boot.initrd.kernelModules = [ cfg.networkModule ]; + boot.kernelParams = lib.mkIf cfg.ip.enable [ + "ip=${mkIpString cfg.ip}" ]; boot.initrd.network = { @@ -64,7 +66,7 @@ "${keyDir}/ssh_host_rsa_key" "${keyDir}/ssh_host_ed25519_key" ]; - inherit (config.initrd-ssh) authorizedKeys; + inherit (cfg) authorizedKeys; }; postCommands = '' echo 'cryptsetup-askpass' >> /root/.profile diff --git a/features/localisation.nix b/features/localisation.nix index df07cdc..ec5f649 100644 --- a/features/localisation.nix +++ b/features/localisation.nix @@ -1,25 +1,30 @@ { nixos = { lib, config, ... }: + let + cfg = config.features.localisation; + in { - options = { - localisation = { - timeZone = lib.mkOption { - type = lib.types.str; - }; + options.features.localisation = { + enable = lib.mkEnableOption "localisation"; - defaultLocale = lib.mkOption { - type = lib.types.str; - }; + timeZone = lib.mkOption { + type = lib.types.str; + default = "Europe/Ljubljana"; + }; + + defaultLocale = lib.mkOption { + type = lib.types.str; + default = "en_US.UTF-8"; }; }; - config = { - time.timeZone = config.localisation.timeZone; - i18n.defaultLocale = config.localisation.defaultLocale; + config = lib.mkIf cfg.enable { + time.timeZone = cfg.timeZone; + i18n.defaultLocale = cfg.defaultLocale; # NOTE:(@janezicmatej) some apps (e.g. java) need TZ env var explicitly - environment.variables.TZ = config.localisation.timeZone; + environment.variables.TZ = cfg.timeZone; }; }; } diff --git a/features/neovim.nix b/features/neovim.nix index fb72a39..a348e2f 100644 --- a/features/neovim.nix +++ b/features/neovim.nix @@ -1,4 +1,17 @@ { + nixos = + { lib, ... }: + { + options.features.neovim = { + enable = lib.mkEnableOption "neovim"; + + dotfiles = lib.mkOption { + type = lib.types.nullOr lib.types.path; + default = null; + }; + }; + }; + home = { config, @@ -6,24 +19,21 @@ lib, pkgs, inputs, + osConfig, ... }: + let + cfg = osConfig.features.neovim; + in { - options = { - neovim.dotfiles = lib.mkOption { - type = lib.types.nullOr lib.types.path; - default = null; - }; - }; - - config = lib.mkMerge [ + config = lib.mkIf cfg.enable (lib.mkMerge [ (lib.optionalAttrs (options ? stylix) { - # disable stylix neovim target when stylix is present (loaded by desktop feature) + # disable stylix neovim target when stylix is present stylix.targets.neovim.enable = false; }) { - xdg.configFile."nvim" = lib.mkIf (config.neovim.dotfiles != null) { - source = config.neovim.dotfiles; + xdg.configFile."nvim" = lib.mkIf (cfg.dotfiles != null) { + source = cfg.dotfiles; }; programs.neovim = { @@ -64,6 +74,6 @@ ]; }; } - ]; + ]); }; } diff --git a/features/networkmanager.nix b/features/networkmanager.nix index 05a10c2..dc62e1c 100644 --- a/features/networkmanager.nix +++ b/features/networkmanager.nix @@ -1,9 +1,18 @@ { - nixos = _: { - networking.networkmanager.enable = true; - networking.nameservers = [ - "1.1.1.1" - "8.8.8.8" - ]; - }; + nixos = + { config, lib, ... }: + let + cfg = config.features.networkmanager; + in + { + options.features.networkmanager.enable = lib.mkEnableOption "networkmanager"; + + config = lib.mkIf cfg.enable { + networking.networkmanager.enable = true; + networking.nameservers = [ + "1.1.1.1" + "8.8.8.8" + ]; + }; + }; } diff --git a/features/nix-ld.nix b/features/nix-ld.nix index e81219c..7c9940a 100644 --- a/features/nix-ld.nix +++ b/features/nix-ld.nix @@ -1,5 +1,14 @@ { - nixos = _: { - programs.nix-ld.enable = true; - }; + nixos = + { config, lib, ... }: + let + cfg = config.features.nix-ld; + in + { + options.features.nix-ld.enable = lib.mkEnableOption "nix-ld"; + + config = lib.mkIf cfg.enable { + programs.nix-ld.enable = true; + }; + }; } diff --git a/features/nix-settings.nix b/features/nix-settings.nix new file mode 100644 index 0000000..06246d1 --- /dev/null +++ b/features/nix-settings.nix @@ -0,0 +1,71 @@ +{ + nixos = + { config, lib, ... }: + let + cfg = config.features.nix-settings; + in + { + options.features.nix-settings = { + enable = lib.mkEnableOption "nix settings"; + + towerCache.enable = lib.mkOption { + type = lib.types.bool; + default = true; + + }; + + gc = { + dates = lib.mkOption { + type = lib.types.str; + default = "monthly"; + }; + + olderThan = lib.mkOption { + type = lib.types.str; + default = "30d"; + }; + }; + + optimise.dates = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ "monthly" ]; + }; + }; + + config = lib.mkIf cfg.enable { + nix = { + settings = { + experimental-features = [ + "nix-command" + "flakes" + ]; + download-buffer-size = 2 * 1024 * 1024 * 1024; + warn-dirty = false; + substituters = + [ + "https://cache.nixos.org" + "https://nix-community.cachix.org?priority=45" + ] + ++ lib.optional cfg.towerCache.enable "http://tower:5000?priority=50"; + trusted-public-keys = + [ + "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" + "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" + ] + ++ lib.optional cfg.towerCache.enable "matej.nix-1:TdbemLVYblvAxqJcwb3mVKmmr3cfzXbMcZHE5ILnZDE="; + }; + + gc = { + automatic = true; + dates = cfg.gc.dates; + options = "--delete-older-than ${cfg.gc.olderThan}"; + }; + + optimise = { + automatic = true; + dates = cfg.optimise.dates; + }; + }; + }; + }; +} diff --git a/features/openssh.nix b/features/openssh.nix index 7a03aef..9a0fd58 100644 --- a/features/openssh.nix +++ b/features/openssh.nix @@ -1,18 +1,23 @@ { nixos = { lib, config, ... }: + let + cfg = config.features.openssh; + in { - options = { - openssh.port = lib.mkOption { + options.features.openssh = { + enable = lib.mkEnableOption "openssh"; + + port = lib.mkOption { type = lib.types.port; default = 22; }; }; - config = { + config = lib.mkIf cfg.enable { services.openssh = { enable = true; - ports = [ config.openssh.port ]; + ports = [ cfg.port ]; settings = { PasswordAuthentication = false; AllowUsers = null; diff --git a/features/printing.nix b/features/printing.nix index a564157..81c6762 100644 --- a/features/printing.nix +++ b/features/printing.nix @@ -1,10 +1,19 @@ { - nixos = _: { - services.printing.enable = true; - services.avahi = { - enable = true; - nssmdns4 = true; - openFirewall = true; + nixos = + { config, lib, ... }: + let + cfg = config.features.printing; + in + { + options.features.printing.enable = lib.mkEnableOption "printing"; + + config = lib.mkIf cfg.enable { + services.printing.enable = true; + services.avahi = { + enable = true; + nssmdns4 = true; + openFirewall = true; + }; + }; }; - }; } diff --git a/features/remote-base.nix b/features/remote-base.nix index cde28d2..18c4d22 100644 --- a/features/remote-base.nix +++ b/features/remote-base.nix @@ -1,13 +1,20 @@ { nixos = - { config, user, ... }: + { config, lib, user, ... }: + let + cfg = config.features.remote-base; + in { - sops.secrets.user-password = { - sopsFile = ../secrets/common.yaml; - neededForUsers = true; - }; + options.features.remote-base.enable = lib.mkEnableOption "remote-base"; - users.mutableUsers = false; - users.users.${user}.hashedPasswordFile = config.sops.secrets.user-password.path; + config = lib.mkIf cfg.enable { + sops.secrets.user-password = { + sopsFile = ../secrets/common.yaml; + neededForUsers = true; + }; + + users.mutableUsers = false; + users.users.${user}.hashedPasswordFile = config.sops.secrets.user-password.path; + }; }; } diff --git a/features/tailscale.nix b/features/tailscale.nix index a6916ad..69f543d 100644 --- a/features/tailscale.nix +++ b/features/tailscale.nix @@ -1,8 +1,17 @@ { - nixos = _: { - services.tailscale = { - enable = true; - useRoutingFeatures = "both"; + nixos = + { config, lib, ... }: + let + cfg = config.features.tailscale; + in + { + options.features.tailscale.enable = lib.mkEnableOption "tailscale"; + + config = lib.mkIf cfg.enable { + services.tailscale = { + enable = true; + useRoutingFeatures = "both"; + }; + }; }; - }; } diff --git a/lib/mkHost.nix b/lib/mkHost.nix index 0d5bd44..d6517fd 100644 --- a/lib/mkHost.nix +++ b/lib/mkHost.nix @@ -27,7 +27,19 @@ let hostConfig = ../hosts/${name}/configuration.nix; hostHWConfig = ../hosts/${name}/hardware-configuration.nix; - # load feature with path check + # auto-discover all features, excluding user-* and default.nix + featureDir = builtins.readDir ../features; + allFeatureNames = lib.pipe featureDir [ + (lib.filterAttrs ( + n: t: + (t == "regular" && lib.hasSuffix ".nix" n && n != "default.nix" && !lib.hasPrefix "user-" n) + || (t == "directory" && builtins.pathExists ../features/${n}/default.nix) + )) + builtins.attrNames + (map (n: lib.removeSuffix ".nix" n)) + ]; + + # load all features unconditionally loadFeature = f: assert @@ -35,7 +47,7 @@ let || throw "feature '${f}' not found at ${toString (featurePath f)}"; import (featurePath f); - loadedFeatures = map loadFeature features; + loadedFeatures = map loadFeature allFeatureNames; # load user feature with path check userFeature = @@ -55,31 +67,42 @@ let # collect nixos and home modules from all features nixosMods = map (f: f.nixos) (builtins.filter (f: f ? nixos) allFeatures); homeMods = map (f: f.home) (builtins.filter (f: f ? home) allFeatures); + + # translate features list to enable flags + featureEnableModule = + { lib, ... }: + { + config.features = lib.genAttrs features (_: { + enable = true; + }); + }; in nixpkgs.lib.nixosSystem { inherit system; - modules = [ - ../nix.nix - inputs.sops-nix.nixosModules.sops + modules = + [ + inputs.sops-nix.nixosModules.sops + inputs.stylix.nixosModules.stylix - { nixpkgs.overlays = overlays; } - { nixpkgs.config.allowUnfree = true; } - { networking.hostName = name; } + { nixpkgs.overlays = overlays; } + { nixpkgs.config.allowUnfree = true; } + { networking.hostName = name; } - hostConfig - ] - ++ lib.optional (builtins.pathExists hostHWConfig) hostHWConfig - ++ nixosMods - ++ lib.optionals hasUser [ - inputs.home-manager.nixosModules.home-manager - { - home-manager.useGlobalPkgs = true; - home-manager.useUserPackages = true; - home-manager.backupFileExtension = "backup"; - home-manager.users.${user}.imports = homeMods; - home-manager.extraSpecialArgs = { inherit inputs; }; - } - ]; + featureEnableModule + hostConfig + ] + ++ lib.optional (builtins.pathExists hostHWConfig) hostHWConfig + ++ nixosMods + ++ lib.optionals hasUser [ + inputs.home-manager.nixosModules.home-manager + { + home-manager.useGlobalPkgs = true; + home-manager.useUserPackages = true; + home-manager.backupFileExtension = "backup"; + home-manager.users.${user}.imports = homeMods; + home-manager.extraSpecialArgs = { inherit inputs; }; + } + ]; specialArgs = { inherit inputs userKeys user; };