{ config, options, lib, nixfiles-lib, inputs, self, ... }: let cfg = config.nixfiles.systems; inherit (lib) types mkOption mkIf filterAttrs mapAttrs ; inherit (builtins) attrNames isNull; inherit (nixfiles-lib.flake-legacy) mkSystem mkHome mkWSLSystem mkISOSystem homeManagerInit; inherit (nixfiles-lib.types) mkCheckedType; mkConfigurationOption = systemType: mkOption { description = "${systemType} configuration type"; type = with types; nullOr mkCheckedType "configuration"; default = null; }; in { options.nixfiles.systems = let systemModule = let outerConfig = config; outerOptions = options; in { name, config, ... }: { options = { enable = lib.mkEnableOption "" // { description = '' Whether to install this configuration into the flake outputs. ''; default = true; }; nixpkgs = mkOption { description = "nixpkgs input to build system with"; type = nixfiles-lib.types.flake; default = inputs.nixpkgs-unstable; }; extraConfig = mkOption { description = '' Arguments to pass to nixpkgs.lib.nixosSystem ''; type = types.attrs; default = {}; }; system = mkOption { description = "Nix system value"; type = types.str; example = "x86_64-linux"; }; modules = mkOption { description = "Extra NixOS configuration modules."; type = with types; listOf deferredModule; default = []; }; name = mkOption { description = '' Name of NixOS configuration. This influences the default directory to load configuration from. This does *not* modify the system's hostname, but should probably be set to the same value. ''; type = lib.types.str; default = name; }; configRoot = mkOption { description = "Path to directory containing system and home configuration modules."; type = lib.types.path; default = self + "/hosts/${config.name}"; }; configuration = mkOption { description = "Path/module of main NixOS configuration."; type = with types; nullOr deferredModule; default = config.configRoot + "/configuration.nix"; }; home-manager = { enable = lib.mkEnableOption "" // { description = '' Whether to enable home-manager for this configuration. ''; default = true; }; input = mkOption { description = "home-manager input"; type = nixfiles-lib.types.flake; default = inputs.home-manager-unstable; }; configuration = mkOption { description = "Path/module of main home-manager configuration."; type = with types; nullOr deferredModule; default = config.configRoot + "/home.nix"; }; modules = mkOption { description = "Extra home-manager modules"; type = with types; listOf deferredModule; }; }; wsl = lib.mkEnableOption "" // { description = '' Whether to import WSL related configuration ''; }; result = lib.mkOption { description = "Resulting system configuration"; type = with types; nullOr (mkCheckedType "configuration"); }; }; config = { home-manager.input = lib.mkIf (config.nixpkgs == inputs.nixpkgs) (lib.mkDefault inputs.home-manager); modules = let nixfilesModule = self + "/system"; defaultsModule = {...}: { # Values for every single system that would not conceivably need # to be made modular # this should be set in the system config # system.stateVersion = stateVersion; nixpkgs = { inherit (outerConfig.nixfiles.common) overlays; config = { # not having the freedom to install unfree programs is unfree allowUnfree = true; }; }; # this should be on by default and there is no reason to turn it # off because this flake will literally stop working otheriwse nix.settings.experimental-features = ["nix-command" "flakes"]; }; wslModule = {...}: { imports = [ inputs.nix-wsl.nixosModules.wsl ]; wsl.enable = true; wsl.defaultUser = outerConfig.nixfiles.vars.username; }; homeManagerModule = let homeManagerModuleInner = homeManagerInit { inherit (config) nixpkgs system; inherit (outerConfig.nixfiles.vars) username; home-manager = config.home-manager.input; module = if (isNull config.home-manager.configuration) then {} else config.home-manager.configuration; }; in { config, pkgs, lib, ... }: let perUserDefaultsModule = {lib, ...}: { config = { # previously, home-manager inherited stateVersion from # nixos in a really hacky way that depended on the wrapper # function. this should preserve that behavior in a much # safer way by directly setting it in a module. ideally, it # should probably be set manually, but I want to maintain # backwards compatibility for now. home.stateVersion = lib.mkDefault config.system.stateVersion; # pass the system nixpkgs config as defaults for the # home-manager nixpkgs config. useGlobalPkgs prevents # setting overlays at the home level; this allows for doing # that while inheriting the system overlays. nixpkgs = { config = lib.mapAttrs (n: v: lib.mkDefault v) config.nixpkgs.config; # mkOrder 900 is after mkBefore but before default order overlays = lib.mkOrder 900 config.nixpkgs.overlays; }; }; }; in { imports = [ # TODO placeholder using old function homeManagerModuleInner ]; options.home-manager.users = lib.mkOption { type = with lib.types; attrsOf (submodule perUserDefaultsModule); }; }; in [ nixfilesModule defaultsModule ] ++ lib.optional (!(isNull config.configuration)) config.configuration ++ lib.optional config.home-manager.enable homeManagerModule ++ lib.optional config.wsl wslModule; extraConfig = { inherit (config) system modules; # TODO get rid of specialArgs and pass things as a module specialArgs = let inherit (self) outputs; in { inherit inputs outputs; inherit (outerConfig.nixfiles) vars; inherit (config) nixpkgs; inherit (config.home-manager) input; }; }; result = config.nixpkgs.lib.nixosSystem config.extraConfig; }; }; in lib.mkOption { description = '' NixOS system configurations ''; type = with types; attrsOf (submodule systemModule); default = {}; }; config = { flake.nixosConfigurations = let enabledSystems = filterAttrs (n: v: v.enable) cfg; in mapAttrs (_: v: v.result) enabledSystems; }; }