{ description = "GKleen's flakey nixos configuration"; nixConfig = { extra-substituters = [ "https://nix-community.cachix.org" ]; extra-trusted-public-keys = [ "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" ]; }; inputs = { nixpkgs = { type = "github"; owner = "NixOS"; repo = "nixpkgs"; ref = "nixos-unstable"; }; nixpkgs-pgbackrest = { type = "github"; owner = "NixOS"; repo = "nixpkgs"; ref = "23.05"; }; nixpkgs-stable = { type = "github"; owner = "NixOS"; repo = "nixpkgs"; ref = "24.05"; }; nixpkgs-eostre = { type = "github"; owner = "NixOS"; repo = "nixpkgs"; ref = "23.11"; }; home-manager = { type = "github"; # owner = "nix-community"; # repo = "home-manager"; # ref = "master"; owner = "gkleen"; repo = "home-manager"; ref = "nixos-late-start"; inputs = { nixpkgs.follows = "nixpkgs"; }; }; home-manager-eostre = { type = "github"; owner = "gkleen"; repo = "home-manager"; ref = "nixos-late-start-23.11"; inputs = { nixpkgs.follows = "nixpkgs-eostre"; }; }; sops-nix = { type = "github"; owner = "Mic92"; repo = "sops-nix"; ref = "master"; inputs.nixpkgs.follows = "nixpkgs"; }; deploy-rs = { type = "github"; owner = "serokell"; repo = "deploy-rs"; ref = "master"; inputs = { nixpkgs.follows = "nixpkgs"; utils.follows = "flake-utils"; flake-compat.follows = "flake-compat"; }; }; nvfetcher = { type = "github"; owner = "berberman"; repo = "nvfetcher"; ref = "master"; inputs = { nixpkgs.follows = "nixpkgs"; flake-utils.follows = "flake-utils"; flake-compat.follows = "flake-compat"; }; }; flake-compat = { type = "github"; owner = "edolstra"; repo = "flake-compat"; ref = "master"; flake = false; }; flake-utils = { type = "github"; owner = "numtide"; repo = "flake-utils"; ref = "main"; }; flake-registry = { type = "github"; owner = "NixOS"; repo = "flake-registry"; flake = false; }; nix-index-database = { type = "github"; owner = "Mic92"; repo = "nix-index-database"; ref = "main"; inputs = { nixpkgs.follows = "nixpkgs"; }; }; poetry2nix = { type = "github"; owner = "nix-community"; repo = "poetry2nix"; ref = "master"; inputs = { flake-utils.follows = "flake-utils"; nixpkgs.follows = "nixpkgs"; }; }; ca-util = { type = "gitlab"; owner = "gkleen"; repo = "ca"; ref = "v3.1.3"; inputs = { nixpkgs.follows = "nixpkgs"; poetry2nix.follows = "poetry2nix"; }; }; backup-utils = { type = "gitlab"; owner = "gkleen"; repo = "backup-utils"; ref = "v0.1.6"; inputs = { nixpkgs.follows = "nixpkgs"; poetry2nix.follows = "poetry2nix"; }; }; prometheus-borg-exporter = { type = "gitlab"; owner = "gkleen"; repo = "prometheus-borg-exporter"; ref = "main"; inputs = { nixpkgs.follows = "nixpkgs"; poetry2nix.follows = "poetry2nix"; }; }; nixos-hardware = { type = "github"; owner = "NixOS"; repo = "nixos-hardware"; ref = "master"; }; impermanence = { type = "github"; owner = "nix-community"; repo = "impermanence"; ref = "master"; }; waybar = { type = "github"; owner = "gkleen"; repo = "Waybar"; ref = "feat/privacy-ignore"; inputs = { nixpkgs.follows = "nixpkgs"; flake-compat.follows = "flake-compat"; }; }; nixVirt = { type = "github"; owner = "AshleyYakeley"; repo = "NixVirt"; inputs.nixpkgs.follows = "nixpkgs"; }; }; outputs = { self, nixpkgs, home-manager, sops-nix, deploy-rs, nvfetcher, ... }@inputs: let inherit (builtins) attrNames attrValues elemAt toJSON isNull pathExists; inherit (nixpkgs) lib; utils = import ./utils { inherit lib; }; inherit (utils) nixImport overrideModule; inherit (lib) mkIf splitString filterAttrs listToAttrs mapAttrsToList nameValuePair concatMap composeManyExtensions mapAttrs mapAttrs' recursiveUpdate genAttrs unique elem optionalAttrs isDerivation concatLists concatStringsSep fix filter makeOverridable foldr; inherit (lib.strings) escapeNixString hasSuffix; accountUserName = accountName: let accountName' = splitString "@" accountName; in elemAt accountName' 0; accountHostName = accountName: let accountName' = splitString "@" accountName; in elemAt accountName' 1; mkSources = pkgs: optionalAttrs (pathExists _sources/generated.nix) { sources = pkgs.callPackage _sources/generated.nix {}; }; mkOverlay = path: final: prev: import path ({ inherit final; inherit prev; flakeInputs = inputs; flake = self; } // mkSources prev); mkNixosConfiguration = addProfiles: dir: path: hostName: let inherit ((inputs."nixpkgs-${hostName}" or inputs.nixpkgs).lib) nixosSystem; in nixosSystem rec { specialArgs = { flake = self; flakeInputs = inputs; path = ./.; home-manager = inputs.${if inputs ? "home-manager-${hostName}" then "home-manager-${hostName}" else "home-manager"}; }; modules = let defaultProfiles = with self.nixosModules.systemProfiles; [ core ]; local = dir + "/${path}"; argsModule = { pkgs, ... }: { _module.args = { customUtils = utils; inherit hostName; } // mkSources pkgs; }; accountModules = attrValues (filterAttrs accountMatchesHost self.nixosModules.accounts); accountMatchesHost = n: _v: accountHostName n == hostName; in attrValues (filterAttrs (n: _v: !(elem n ["systemProfiles" "users" "userProfiles" "accounts"])) self.nixosModules) ++ [ argsModule ] ++ defaultProfiles ++ addProfiles ++ [ local ] ++ accountModules; }; mkSystemProfile = dir: path: profileName: { imports = [ (dir + "/${path}") ]; config = { system.profiles = [profileName]; }; }; defaultUserProfiles = userName: with self.nixosModules.userProfiles.${userName}; [ core ]; mkUserModule = dir: path: userName: overrideModule (import (dir + "/${path}")) (inputs: inputs // { inherit userName; }) (outputs: { _file = dir + "/${path}"; } // outputs // { imports = defaultUserProfiles userName ++ (outputs.imports or []); }); mkUserProfile = userName: dir: path: profileName: let profileModule = overrideModule (import (dir + "/${path}")) (inputs: inputs // { inherit userName; }) (outputs: { _file = dir + "/${path}"; } // outputs); in { imports = [profileModule]; config = { users.users.${userName}.profiles = [profileName]; }; }; mkAccountModule = dir: path: accountName: let userName = accountUserName accountName; in overrideModule (import (dir + "/${path}")) (inputs: inputs // { inherit userName; }) (outputs: { _file = dir + "/${path}"; } // outputs // { imports = [self.nixosModules.users.${userName} or ({...}: { imports = defaultUserProfiles userName; })] ++ (outputs.imports or []); }); systemsSelector = "x86_64-linux"; systems = filter (system: !(isNull (builtins.match systemsSelector system))) nixpkgs.lib.systems.flakeExposed; # systems = # let # disallowedSystems = ["armv5tel-linux" "armv6l-linux"]; # in filter (system: !(elem system disallowedSystems)) nixpkgs.lib.systems.flakeExposed; nixpkgsPackages = localSystem: (makeOverridable (import (nixpkgs.outPath + "/pkgs/top-level"))) { inherit localSystem; }; forAllSystems = f: mapAttrs f (genAttrs systems nixpkgsPackages); forAllUsers = genAttrs (unique (map accountUserName (attrNames self.nixosModules.accounts))); activateNixosConfigurations = forAllSystems (system: _pkgs: filterAttrs (_n: v: v != null) (mapAttrs' (hostName: nixosConfig: nameValuePair "${hostName}-activate" (if system == nixosConfig.config.nixpkgs.system then { type = "app"; program = "${nixosConfig.config.system.build.toplevel}/bin/switch-to-configuration"; } else null)) self.nixosConfigurations)); startVMs = forAllSystems (system: pkgs: mapAttrs' (hostName: nixosConfig: nameValuePair "run-${hostName}-vm" { type = "app"; program = "${nixosConfig.config.system.build.vm}/bin/run-${hostName}-vm"; }) (nixImport rec { dir = ./hosts; _import = mkNixosConfiguration [ { config.virtualisation.host.pkgs = pkgs; } ] dir; })); activateHomeManagerConfigurations = forAllSystems (system: _pkgs: filterAttrs (_n: v: v != null) (listToAttrs (concatLists (mapAttrsToList (hostName: nixosConfig: mapAttrsToList (userName: userCfg: nameValuePair "${userName}@${hostName}-activate" (if system == nixosConfig.config.nixpkgs.system then { type = "app"; program = "${userCfg.home.activationPackage}/activate"; } else null)) nixosConfig.config.home-manager.users) self.nixosConfigurations)))); installerShells = system: pkgs: mapAttrs (installerName: config: pkgs.callPackage ./installer/shell.nix { inherit system installerName config; }) (filterAttrs (n: _v: hasSuffix "-netboot" n) installerNixosConfigurations); overlayPaths = nixImport rec { dir = ./overlays; _import = (path: _name: dir + "/${path}"); }; installerProfiles = nixImport rec { dir = ./installer-profiles; _import = path: name: mkSystemProfile dir path "installer-${name}"; }; installerConfig = if pathExists ./installer.nix then "installer.nix" else (if pathExists ./installer then "installer" else null); mkInstallerForSystem = system: (lib.systems.elaborate system).isLinux; installers = let mkInstallers = system: mapAttrs (mkInstaller system) installerProfiles; mkInstaller = system: name: profile: mkNixosConfiguration [profile { config.nixpkgs.system = system; }] ./. installerConfig "installer"; in forAllSystems (system: _systemPkgs: optionalAttrs (!(isNull installerConfig) && mkInstallerForSystem system) (mkInstallers system)); installerNixosConfigurations = listToAttrs (concatLists (mapAttrsToList (system: mapAttrsToList (profile: config: nameValuePair ("installer-${system}-${profile}") config)) installers)); # packages = forAllSystems (system: systemPkgs: composeManyExtensions (attrValues self.overlays) self.legacyPackages.${system} systemPkgs); activateHomeManager = system: base: (deploy-rs.lib.${system}.activate.custom // { dryActivate = "DRY_RUN=1 $PROFILE/activate"; }) base.activationPackage "$PROFILE/activate"; in { nixosModules = let modulesAttrs = nixImport { dir = ./modules; }; systemProfiles = nixImport rec { dir = ./system-profiles; _import = mkSystemProfile dir; }; users = nixImport rec { dir = ./users; _import = mkUserModule dir; }; userProfiles = forAllUsers (userName: nixImport rec { dir = ./user-profiles; _import = mkUserProfile userName dir; }); accounts = recursiveUpdate rootAccounts (nixImport rec { dir = ./accounts; _import = mkAccountModule dir; }); rootAccounts = mapAttrs' (hostName: _value: nameValuePair "root@${hostName}" ({...}: { imports = [ self.nixosModules.users.root or ({...}: { imports = defaultUserProfiles "root"; }) ]; })) self.nixosConfigurations; in modulesAttrs // { inherit systemProfiles users userProfiles accounts; }; nixosConfigurations = installerNixosConfigurations // nixImport rec { dir = ./hosts; _import = mkNixosConfiguration [] dir; }; homeModules = nixImport rec { dir = ./home-modules; }; homeConfigurations = listToAttrs (concatLists (mapAttrsToList (hostname: nixosConfig: mapAttrsToList (username: configuration: nameValuePair "${username}@${hostname}" { inherit (configuration.home) activationPackage; }) nixosConfig.config.home-manager.users) self.nixosConfigurations)); overlays = mapAttrs (_name: path: mkOverlay path) overlayPaths; packages = forAllSystems (system: systemPkgs: nixImport rec { dir = ./tools; _import = _path: name: import "${toString dir}/${name}" ({ inherit system; } // inputs); }); # packages = mapAttrs (_name: filterAttrs (_name: isDerivation)) packages; # packages' = mapAttrs (_name: filterAttrs (_name: value: !(isDerivation value))) packages; legacyPackages = forAllSystems (system: systemPkgs: systemPkgs.override { overlays = attrValues self.overlays; }); apps = foldr recursiveUpdate {} [startVMs activateNixosConfigurations activateHomeManagerConfigurations]; devShells = forAllSystems (system: systemPkgs: { default = import ./shell.nix ({ inherit system; } // inputs); } // installerShells system systemPkgs); templates.default = { path = ./.; description = "GKleen's flakey nixos configuration"; }; deploy.nodes = let defaults = mapAttrs (hostname: _: { inherit hostname; sshUser = "root"; sshOpts = [ "-S" "none" ]; profilesOrder = ["system"]; # system first profiles = { system = { path = deploy-rs.lib.${self.nixosConfigurations.${hostname}.config.nixpkgs.system}.activate.nixos self.nixosConfigurations.${hostname}; }; }; # // (mapAttrs (_user: usercfg: { # user = usercfg.home.username; # path = activateHomeManager (self.nixosConfigurations.${hostname}.config.nixpkgs.system) usercfg.home; # }) self.nixosConfigurations.${hostname}.config.home-manager.users); }) (nixImport { dir = ./hosts; _import = (_path: name: name); }); overrides = if pathExists ./deploy then nixImport { dir = ./deploy; _import = path: _name: import (./deploy + "/${path}") inputs; } else {}; filterEnabled = attrs: mapAttrs (_n: v: filterAttrs (n: _v: n != "enabled") v) (filterAttrs (_n: v: v.enabled or true) attrs); in mapAttrs (_n: v: if v ? "profiles" then v // { profiles = filterEnabled v.profiles; } else v) (filterEnabled (recursiveUpdate defaults overrides)); checks = builtins.mapAttrs (system: deployLib: deployLib.deployChecks self.deploy) deploy-rs.lib; }; }