diff --git a/config/basic/generate-installer-package.nix b/config/basic/generate-installer-package.nix new file mode 100644 index 0000000..57c4558 --- /dev/null +++ b/config/basic/generate-installer-package.nix @@ -0,0 +1,45 @@ +{ + config, + lib, + pkgs, + ... +}: +let + + disko-script = pkgs.writeShellScriptBin "disko-script" "${config.system.build.diskoScript}"; + disko-mount = pkgs.writeShellScriptBin "disko-mount" "${config.system.build.mountScript}"; + disko-format = pkgs.writeShellScriptBin "disko-format" "${config.system.build.formatScript}"; + + install-system = pkgs.writeShellScriptBin "install-system" '' + set -euo pipefail + + echo "Formatting disks..." + ${disko-script}/bin/disko-script + + echo "Installing system..." + nixos-install --no-root-password --system ${config.system.build.toplevel} + + echo "Done!" + ''; + + installer-package = pkgs.symlinkJoin { + name = "installer-package-${config.node.name}"; + paths = [ + disko-script + disko-mount + disko-format + install-system + ]; + }; +in +{ + options.system.build.installFromLive = lib.mkOption { + type = lib.types.package; + description = '' + A single script that can be used from a live system, which will + format disks and copy the derivation. + ''; + default = installer-package; + readOnly = true; + }; +} diff --git a/flake.lock b/flake.lock index 4defe0c..9f6aa21 100644 --- a/flake.lock +++ b/flake.lock @@ -531,6 +531,24 @@ } }, "flake-parts": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib" + }, + "locked": { + "lastModified": 1722555600, + "narHash": "sha256-XOQkdLafnb/p9ij77byFQjDf5m5QYl9b2REiVClC+x4=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "8471fe90ad337a8074e957b69ca4d0089218391d", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-parts_2": { "inputs": { "nixpkgs-lib": [ "lanzaboote", @@ -551,7 +569,7 @@ "type": "github" } }, - "flake-parts_2": { + "flake-parts_3": { "inputs": { "nixpkgs-lib": [ "nixpkgs-wayland", @@ -573,7 +591,7 @@ "type": "github" } }, - "flake-parts_3": { + "flake-parts_4": { "inputs": { "nixpkgs-lib": [ "nixvim", @@ -997,7 +1015,7 @@ "inputs": { "crane": "crane", "flake-compat": "flake-compat_2", - "flake-parts": "flake-parts", + "flake-parts": "flake-parts_2", "flake-utils": "flake-utils_2", "nixpkgs": [ "nixpkgs" @@ -1023,7 +1041,7 @@ "lib-aggregate": { "inputs": { "flake-utils": "flake-utils_6", - "nixpkgs-lib": "nixpkgs-lib" + "nixpkgs-lib": "nixpkgs-lib_2" }, "locked": { "lastModified": 1722168631, @@ -1100,7 +1118,7 @@ }, "nix-eval-jobs": { "inputs": { - "flake-parts": "flake-parts_2", + "flake-parts": "flake-parts_3", "nix-github-actions": "nix-github-actions", "nixpkgs": "nixpkgs_3", "treefmt-nix": "treefmt-nix" @@ -1295,6 +1313,18 @@ } }, "nixpkgs-lib": { + "locked": { + "lastModified": 1722555339, + "narHash": "sha256-uFf2QeW7eAHlYXuDktm9c25OxOyCoUOQmh5SZ9amE5Q=", + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/a5d394176e64ab29c852d03346c1fc9b0b7d33eb.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/a5d394176e64ab29c852d03346c1fc9b0b7d33eb.tar.gz" + } + }, + "nixpkgs-lib_2": { "locked": { "lastModified": 1722128034, "narHash": "sha256-L8rwzYPsLo/TYtydPJoQyYOfetuiyQYnTWYcyB8UE/s=", @@ -1464,7 +1494,7 @@ "inputs": { "devshell": "devshell_5", "flake-compat": "flake-compat_6", - "flake-parts": "flake-parts_3", + "flake-parts": "flake-parts_4", "git-hooks": "git-hooks", "home-manager": "home-manager_2", "nix-darwin": "nix-darwin", @@ -1654,6 +1684,7 @@ "agenix-rekey": "agenix-rekey", "devshell": "devshell_2", "disko": "disko", + "flake-parts": "flake-parts", "flake-utils": "flake-utils", "home-manager": "home-manager", "impermanence": "impermanence", diff --git a/flake.nix b/flake.nix index a334276..fbfe395 100644 --- a/flake.nix +++ b/flake.nix @@ -43,6 +43,8 @@ inputs.nixpkgs.follows = "nixpkgs"; }; + flake-parts.url = "github:hercules-ci/flake-parts"; + # Bin zu faul des zu kopieren agenix-rekey = { url = "github:oddlama/agenix-rekey"; @@ -104,107 +106,50 @@ outputs = { self, - nixpkgs, - flake-utils, - agenix-rekey, nixos-generators, - pre-commit-hooks, - devshell, - nixvim, nixos-extra-modules, nix-topology, ... }@inputs: - let - inherit (nixpkgs) lib; - stateVersion = "23.05"; - in - { - secretsConfig = { - # This should be a link to one of the age public keys is './keys' - masterIdentities = [ ./keys/PatC.pub ]; - extraEncryptionPubkeys = [ ./secrets/recipients.txt ]; - }; - agenix-rekey = agenix-rekey.configure { - userFlake = self; - inherit (self) nodes pkgs; - }; + inputs.flake-parts.lib.mkFlake { inherit inputs; } { + imports = [ + ./nix/agenix-rekey.nix + ./nix/devshell.nix + ./nix/hosts.nix + ./nix/pkgs.nix + nix-topology.flakeModule + ]; - inherit stateVersion; - inherit (import ./nix/hosts.nix inputs) - hosts - nixosConfigurations - minimalConfigurations - guestConfigurations - ; - nodes = self.nixosConfigurations // self.guestConfigurations; + systems = [ + "x86_64-linux" + "aarch64-linux" + ]; - inherit - (lib.foldl' lib.recursiveUpdate { } ( - lib.mapAttrsToList (import ./nix/generate-installer-package.nix inputs) self.minimalConfigurations - )) - packages - ; - } - // flake-utils.lib.eachDefaultSystem (system: rec { - apps.setupHetznerStorageBoxes = - import (nixos-extra-modules + "/apps/setup-hetzner-storage-boxes.nix") - { + perSystem = + { pkgs, system, ... }: + { + topology.modules = [ ./nix/topology.nix ]; + apps.setupHetznerStorageBoxes = + import (nixos-extra-modules + "/apps/setup-hetzner-storage-boxes.nix") + { + inherit pkgs; + nixosConfigurations = inputs.self.nodes; + decryptIdentity = builtins.head self.secretsConfig.masterIdentities; + }; + packages.live-iso = nixos-generators.nixosGenerate { inherit pkgs; - nixosConfigurations = self.nodes; - decryptIdentity = builtins.head self.secretsConfig.masterIdentities; + modules = [ + ./nix/installer-configuration.nix + ./config/basic/ssh.nix + ]; + format = + { + x86_64-linux = "install-iso"; + aarch64-linux = "sd-aarch64-installer"; + } + .${system}; }; - pkgs = import nixpkgs { - overlays = - import ./lib inputs - ++ import ./pkgs - ++ [ - # nixpkgs-wayland.overlay - nixos-extra-modules.overlays.default - nix-topology.overlays.default - devshell.overlays.default - agenix-rekey.overlays.default - nixvim.overlays.default - ]; - inherit system; - config.allowUnfree = true; - }; - packages = pkgs; - topology = import nix-topology { - inherit pkgs; - modules = [ - { inherit (self) nixosConfigurations; } - ./nix/topology.nix - ]; - }; - - images.live-iso = nixos-generators.nixosGenerate { - inherit pkgs; - modules = [ - ./nix/installer-configuration.nix - ./config/basic/ssh.nix - ]; - format = - { - x86_64-linux = "install-iso"; - aarch64-linux = "sd-aarch64-installer"; - } - .${system}; - }; - - checks.pre-commit-check = pre-commit-hooks.lib.${system}.run { - src = lib.cleanSource ./.; - hooks = { - nixfmt = { - enable = true; - package = pkgs.nixfmt-rfc-style; - }; - deadnix.enable = true; - statix.enable = true; }; - }; - devShell = import ./nix/devshell.nix inputs system; - formatter = pkgs.nixfmt-rfc-style; - }); + }; } diff --git a/lib/default.nix b/lib/default.nix deleted file mode 100644 index 5f4e218..0000000 --- a/lib/default.nix +++ /dev/null @@ -1 +0,0 @@ -_inputs: [ ] diff --git a/nix/agenix-rekey.nix b/nix/agenix-rekey.nix new file mode 100644 index 0000000..fe246d3 --- /dev/null +++ b/nix/agenix-rekey.nix @@ -0,0 +1,31 @@ +{ inputs, self, ... }: +{ + imports = [ inputs.agenix-rekey.flakeModule ]; + flake = { + secretsConfig = { + # This should be a link to one of the age public keys in './keys' + masterIdentities = [ ../keys/PatC.pub ]; + extraEncryptionPubkeys = [ ../secrets/recipients.txt ]; + }; + }; + perSystem = + { config, ... }: + { + agenix-rekey.nodes = self.nodes; + devshells.default = { + commands = [ + { + inherit (config.agenix-rekey) package; + help = "Edit, generate and rekey secrets"; + } + ]; + env = [ + { + # Always add files to git after agenix rekey and agenix generate. + name = "AGENIX_REKEY_ADD_TO_GIT"; + value = "true"; + } + ]; + }; + }; +} diff --git a/nix/devshell.nix b/nix/devshell.nix index ad0223b..8aa7510 100644 --- a/nix/devshell.nix +++ b/nix/devshell.nix @@ -1,69 +1,80 @@ -{ self, ... }: -system: -let - pkgs = self.pkgs.${system}; -in -pkgs.devshell.mkShell { - name = "nix-config"; - packages = with pkgs; [ - # Nix - nil - - # Misc - shellcheck - pre-commit - rage - nix - nix-diff - nix-update - ]; - commands = [ - { - package = pkgs.deploy; - help = "build and deploy nix configurations"; - } - { - package = pkgs.agenix-rekey; - help = "Edit and rekey repository secrets"; - } - { - package = pkgs.nixfmt-rfc-style; - help = "Format nix code"; - } - { - package = pkgs.statix; - help = "Linter for nix"; - } - { - package = pkgs.deadnix; - help = "Remove dead nix code"; - } - { - package = pkgs.nix-tree; - help = "Show nix closure tree"; - } - { - package = pkgs.update-nix-fetchgit; - help = "Update fetcher inside nix files"; - } - { - package = pkgs.nvd; - help = "List package differences between systems"; - } - { - package = pkgs.vulnix; - help = "List vulnerabilities found in your system"; - } - ]; - env = [ - { - name = "NIX_CONFIG"; - value = '' - plugin-files = ${pkgs.nix-plugins}/lib/nix/plugins - extra-builtins-file = ${../nix}/extra-builtins.nix - ''; - } +{ inputs, ... }: +{ + imports = [ + inputs.devshell.flakeModule + inputs.pre-commit-hooks.flakeModule ]; - devshell.startup.pre-commit.text = self.checks.${system}.pre-commit-check.shellHook; + perSystem = + { config, pkgs, ... }: + { + pre-commit.settings.hooks = { + nixfmt = { + enable = true; + package = pkgs.nixfmt-rfc-style; + }; + deadnix.enable = true; + statix.enable = true; + }; + formatter = pkgs.nixfmt-rfc-style; + devshells.default = { + packages = with pkgs; [ + # Nix + nil + + # Misc + shellcheck + pre-commit + rage + nix + nix-diff + nix-update + ]; + commands = [ + { + package = pkgs.deploy; + help = "build and deploy nix configurations"; + } + { + package = pkgs.nixfmt-rfc-style; + help = "Format nix code"; + } + { + package = pkgs.statix; + help = "Linter for nix"; + } + { + package = pkgs.deadnix; + help = "Remove dead nix code"; + } + { + package = pkgs.nix-tree; + help = "Show nix closure tree"; + } + { + package = pkgs.update-nix-fetchgit; + help = "Update fetcher inside nix files"; + } + { + package = pkgs.nvd; + help = "List package differences between systems"; + } + { + package = pkgs.vulnix; + help = "List vulnerabilities found in your system"; + } + ]; + env = [ + { + name = "NIX_CONFIG"; + value = '' + plugin-files = ${pkgs.nix-plugins}/lib/nix/plugins + extra-builtins-file = ${../nix}/extra-builtins.nix + ''; + } + ]; + + devshell.startup.pre-commit.text = config.pre-commit.installationScript; + }; + }; } diff --git a/nix/generate-installer-package.nix b/nix/generate-installer-package.nix deleted file mode 100644 index 9075786..0000000 --- a/nix/generate-installer-package.nix +++ /dev/null @@ -1,40 +0,0 @@ -{ self, ... }: -nodeName: nodeAttrs: -let - #FIXME inherit nodeAttrs. system; - system = "x86_64-linux"; - pkgs = self.pkgs.${system}; - - disko-script = pkgs.writeShellScriptBin "disko-script" "${nodeAttrs.config.system.build.diskoScript - }"; - disko-mount = pkgs.writeShellScriptBin "disko-mount" "${nodeAttrs.config.system.build.mountScript}"; - disko-format = pkgs.writeShellScriptBin "disko-format" "${nodeAttrs.config.system.build.formatScript - }"; - - install-system = pkgs.writeShellScriptBin "install-system" '' - set -euo pipefail - - echo "Formatting disks..." - ${disko-script}/bin/disko-script - - echo "Installing system..." - nixos-install --no-root-password --system ${nodeAttrs.config.system.build.toplevel} - - echo "Done!" - ''; - - installer-package = pkgs.symlinkJoin { - name = "installer-package-${nodeName}"; - paths = [ - disko-script - disko-mount - disko-format - install-system - ]; - }; -in -{ - # Everything required for the installer as a single package, - # so it can be used from an existing live system by copying the derivation. - packages.${system}.installer-package.${nodeName} = installer-package; -} diff --git a/nix/hosts.nix b/nix/hosts.nix index 9ef8806..2bed07b 100644 --- a/nix/hosts.nix +++ b/nix/hosts.nix @@ -1,78 +1,85 @@ -inputs: -let - inherit (inputs) self; - inherit (inputs.nixpkgs.lib) - concatMapAttrs - filterAttrs - flip - genAttrs - mapAttrs' - nameValuePair - nixosSystem - ; - - # Creates a new nixosSystem with the correct specialArgs, pkgs and name definition - mkHost = - { minimal }: - name: - let - pkgs = self.pkgs.x86_64-linux; - in - nixosSystem { - specialArgs = { - # Use the correct instance lib that has our overlays - inherit (pkgs) lib; - inherit (self) nodes stateVersion; - inherit inputs minimal; - }; - modules = [ - { - # We cannot force the package set via nixpkgs.pkgs and - # inputs.nixpkgs.nixosModules.readOnlyPkgs, since some nixosModules - # like nixseparatedebuginfod depend on adding packages via nixpkgs.overlays. - # So we just mimic the options and overlays defined by the passed pkgs set. - nixpkgs.overlays = pkgs.overlays; - nixpkgs.config = pkgs.config; - node.name = name; - node.secretsDir = ../. + "/hosts/${name}/secrets"; - } - ../hosts/${name} - ]; - }; - - # Load the list of hosts that this flake defines, which - # associates the minimum amount of metadata that is necessary - # to instanciate hosts correctly. - hosts = builtins.attrNames (filterAttrs (_: type: type == "directory") (builtins.readDir ../hosts)); - # Process each nixosHosts declaration and generatea nixosSystem definitions - nixosConfigurations = genAttrs hosts (mkHost { - minimal = false; - }); - minimalConfigurations = genAttrs hosts (mkHost { - minimal = true; - }); - - # True NixOS nodes can define additional guest nodes that are built - # together with it. We collect all defined guests from each node here - # to allow accessing any node via the unified attribute `nodes`. - guestConfigurations = flip concatMapAttrs self.nixosConfigurations ( - _: node: - flip mapAttrs' (node.config.guests or { }) ( - guestName: guestDef: - nameValuePair guestDef.nodeName ( - if guestDef.backend == "microvm" then - node.config.microvm.vms.${guestName}.config - else - node.config.containers.${guestName}.nixosConfiguration - ) - ) - ); -in +{ inputs, ... }: { - inherit - hosts - nixosConfigurations - minimalConfigurations - guestConfigurations - ; + flake = + { config, lib, ... }: + let + inherit (lib) + concatMapAttrs + filterAttrs + flip + genAttrs + mapAttrs' + nameValuePair + ; + + # Creates a new nixosSystem with the correct specialArgs, pkgs and name definition + mkHost = + { minimal }: + name: + let + pkgs = config.pkgs.x86_64-linux; + stateVersion = "23.05"; + in + inputs.nixpkgs.lib.nixosSystem { + specialArgs = { + # Use the correct instance lib that has our overlays + inherit (pkgs) lib; + inherit (config) nodes; + inherit inputs minimal stateVersion; + }; + modules = [ + { + # We cannot force the package set via nixpkgs.pkgs and + # inputs.nixpkgs.nixosModules.readOnlyPkgs, since some nixosModules + # like nixseparatedebuginfod depend on adding packages via nixpkgs.overlays. + # So we just mimic the options and overlays defined by the passed pkgs set. + node.name = name; + node.secretsDir = ../. + "/hosts/${name}/secrets"; + nixpkgs.overlays = (import ../pkgs) ++ [ + # nixpkgs-wayland.overlay + inputs.nixos-extra-modules.overlays.default + inputs.nix-topology.overlays.default + inputs.devshell.overlays.default + inputs.agenix-rekey.overlays.default + inputs.nixvim.overlays.default + ]; + nixpkgs.config.allowUnfree = true; + } + ../hosts/${name} + ]; + }; + + # Load the list of hosts that this flake defines, which + # associates the minimum amount of metadata that is necessary + # to instanciate hosts correctly. + hosts = builtins.attrNames (filterAttrs (_: type: type == "directory") (builtins.readDir ../hosts)); + in + # Process each nixosHosts declaration and generatea nixosSystem definitions + { + nixosConfigurations = genAttrs hosts (mkHost { + minimal = false; + }); + minimalConfigurations = genAttrs hosts (mkHost { + minimal = true; + }); + + # True NixOS nodes can define additional guest nodes that are built + # together with it. We collect all defined guests from each node here + # to allow accessing any node via the unified attribute `nodes`. + guestConfigurations = flip concatMapAttrs config.nixosConfigurations ( + _: node: + flip mapAttrs' (node.config.guests or { }) ( + guestName: guestDef: + nameValuePair guestDef.nodeName ( + if guestDef.backend == "microvm" then + node.config.microvm.vms.${guestName}.config + else + node.config.containers.${guestName}.nixosConfiguration + ) + ) + ); + # All nixosSystem instanciations are collected here, so that we can refer + # to any system via nodes. + nodes = config.nixosConfigurations // config.guestConfigurations; + }; } diff --git a/nix/pkgs.nix b/nix/pkgs.nix new file mode 100644 index 0000000..877827b --- /dev/null +++ b/nix/pkgs.nix @@ -0,0 +1,28 @@ +{ inputs, ... }: +{ + imports = [ + ( + { lib, flake-parts-lib, ... }: + flake-parts-lib.mkTransposedPerSystemModule { + name = "pkgs"; + file = ./pkgs.nix; + option = lib.mkOption { type = lib.types.unspecified; }; + } + ) + ]; + + perSystem = + { pkgs, system, ... }: + { + _module.args.pkgs = import inputs.nixpkgs { + inherit system; + config.allowUnfree = true; + overlays = (import ../pkgs/default.nix) ++ [ + inputs.nix-topology.overlays.default + inputs.nixos-extra-modules.overlays.default + ]; + }; + + inherit pkgs; + }; +}