From 1b9d9fc58a0fe5f180f8c666d09c42bf0b69a8b3 Mon Sep 17 00:00:00 2001 From: oddlama Date: Mon, 8 May 2023 14:48:59 +0200 Subject: [PATCH] feat: add declarative microvms --- flake.lock | 40 +++++++++++++--------------- flake.nix | 15 +++++------ hosts/common/core/net.nix | 24 +++++++++-------- hosts/ward/default.nix | 21 +++++++++++++++ hosts/ward/microvms/test/default.nix | 28 +++++++++++++++++++ nix/generate-node.nix | 26 +++++++----------- nix/microvms.nix | 21 --------------- nix/secrets.nix | 29 +++++++++++++++++--- 8 files changed, 124 insertions(+), 80 deletions(-) create mode 100644 hosts/ward/microvms/test/default.nix delete mode 100644 nix/microvms.nix diff --git a/flake.lock b/flake.lock index 11b5e69..a7712df 100644 --- a/flake.lock +++ b/flake.lock @@ -116,11 +116,11 @@ ] }, "locked": { - "lastModified": 1682856014, - "narHash": "sha256-QkjneK3DH68IsEf2VnTkMesjsyHsVeVlr6TFxp97uIw=", + "lastModified": 1683508929, + "narHash": "sha256-AqkIrwewCL8+zlkqhNxheF+kOfyakzZDk43SqRTIqRE=", "owner": "nix-community", "repo": "disko", - "rev": "8b43938cf77bbeddec127a5398b5dba3578c4290", + "rev": "2a59f5cf641607dbecb0cfec3ae32247e4aeb311", "type": "github" }, "original": { @@ -207,11 +207,11 @@ ] }, "locked": { - "lastModified": 1682779989, - "narHash": "sha256-H8AjcIBYFYrlRobYJ+n1B+ZJ6TsaaeZpuLn4iRqVvr4=", + "lastModified": 1683543852, + "narHash": "sha256-aS9qNcg9GwSYFLCWa3Lw+2nVPG11mmQ3B7Oka1hh04M=", "owner": "nix-community", "repo": "home-manager", - "rev": "3144311f31194b537808ae6848f86f3dbf977d59", + "rev": "3f3fa731ad0f99741d4dc98e8e1287b45e30b452", "type": "github" }, "original": { @@ -257,12 +257,10 @@ ] }, "locked": { - "lastModified": 1682817142, - "narHash": "sha256-mkKUFwQq8Sgw+p82K5SoWO6lODFeJcr+SpzH3+Utye0=", - "owner": "astro", - "repo": "microvm.nix", - "rev": "15fb183b412619d27db227dcbaf959c63bdaba09", - "type": "github" + "lastModified": 1682972682, + "narHash": "sha256-IYInF92rLqqVk/dyugT2QVbVeEfYx1rbBJjbUlRD8oE=", + "type": "git", + "url": "file:///root/projects/microvm.nix" }, "original": { "owner": "astro", @@ -293,11 +291,11 @@ ] }, "locked": { - "lastModified": 1682332772, - "narHash": "sha256-GMoWhChQdeNM2FFqVbEZgBABSdi/+JgSP6v+jUz5b24=", + "lastModified": 1683530131, + "narHash": "sha256-R0RSqj6JdZfru2x/cM19KJMHsU52OjtyxI5cccd+uFc=", "owner": "nix-community", "repo": "nixos-generators", - "rev": "d774aeedc0685e5871be1e1ee0511900deeb21c2", + "rev": "10079333313ff62446e6f2b0e7c5231c7431d269", "type": "github" }, "original": { @@ -308,11 +306,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1682836095, - "narHash": "sha256-PdzpJhuXBz71AgWNWMMYLbB8GMMce6QguhQY/6HOOcc=", + "lastModified": 1683269598, + "narHash": "sha256-KNsb+nBbB1Fmxd07dt4E0KXMT4YeKJB7gQaA6Xfk+mo=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "e4a21ddcb45ee5f5c85a5d9e9698debf77fb98c3", + "rev": "51559e691f1493a26f94f1df1aaf516bb507e78b", "type": "github" }, "original": { @@ -344,11 +342,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1682692304, - "narHash": "sha256-9/lyXN2BpHw+1xE+D2ySBSLMCHWqiWu5tPHBMRDib8M=", + "lastModified": 1683408522, + "narHash": "sha256-9kcPh6Uxo17a3kK3XCHhcWiV1Yu1kYj22RHiymUhMkU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "937a9d1ee7b1351d8c55fff6611a8edf6e7c1c37", + "rev": "897876e4c484f1e8f92009fd11b7d988a121a4e7", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 8cf7358..8e9f94e 100644 --- a/flake.nix +++ b/flake.nix @@ -69,6 +69,7 @@ colmena, nixos-generators, nixpkgs, + microvm, flake-utils, agenix-rekey, ... @@ -96,7 +97,6 @@ ward = { type = "nixos"; system = "x86_64-linux"; - microVmHost = true; }; zackbiene = { type = "nixos"; @@ -105,25 +105,24 @@ }; colmena = import ./nix/colmena.nix inputs; - colmenaNodes = ((colmena.lib.makeHive self.colmena).introspect (x: x)).nodes; - microvmNodes = import ./nix/microvms.nix inputs; - - # All nixos based hosts collected together - nodes = self.colmenaNodes // self.microvmNodes; + inherit ((colmena.lib.makeHive self.colmena).introspect (x: x)) nodes; # Collect installer packages inherit (recursiveMergeAttrs (nixpkgs.lib.mapAttrsToList (import ./nix/generate-installer.nix inputs) - self.colmenaNodes)) + self.nodes)) packages ; } // flake-utils.lib.eachDefaultSystem (system: rec { pkgs = import nixpkgs { - inherit system; + localSystem = system; config.allowUnfree = true; + overlays = [ + microvm.overlay + ]; }; apps = diff --git a/hosts/common/core/net.nix b/hosts/common/core/net.nix index 2d58e39..7de5028 100644 --- a/hosts/common/core/net.nix +++ b/hosts/common/core/net.nix @@ -16,7 +16,7 @@ ; in { networking = { - hostName = mkDefault nodeName; + hostName = nodeName; useDHCP = mkForce false; useNetworkd = true; dhcpcd.enable = false; @@ -80,14 +80,16 @@ in { }; # Rename known network interfaces - services.udev.packages = let - interfaceNamesUdevRules = pkgs.writeTextFile { - name = "interface-names-udev-rules"; - text = concatStringsSep "\n" (mapAttrsToList ( - interface: attrs: ''SUBSYSTEM=="net", ACTION=="add", ATTR{address}=="${attrs.mac}", NAME:="${interface}"'' - ) - nodeSecrets.networking.interfaces); - destination = "/etc/udev/rules.d/01-interface-names.rules"; - }; - in [interfaceNamesUdevRules]; + services.udev.packages = + lib.mkIf ((nodeSecrets.networking.interfaces or {}) != {}) + (let + interfaceNamesUdevRules = pkgs.writeTextFile { + name = "interface-names-udev-rules"; + text = concatStringsSep "\n" (mapAttrsToList ( + interface: attrs: ''SUBSYSTEM=="net", ACTION=="add", ATTR{address}=="${attrs.mac}", NAME:="${interface}"'' + ) + nodeSecrets.networking.interfaces); + destination = "/etc/udev/rules.d/01-interface-names.rules"; + }; + in [interfaceNamesUdevRules]); } diff --git a/hosts/ward/default.nix b/hosts/ward/default.nix index 1b04d75..094ac0b 100644 --- a/hosts/ward/default.nix +++ b/hosts/ward/default.nix @@ -1,5 +1,8 @@ { config, + inputs, + lib, + microvm, nixos-hardware, pkgs, ... @@ -8,6 +11,8 @@ nixos-hardware.common-cpu-intel nixos-hardware.common-pc-ssd + microvm.host + ../common/core ../common/hardware/intel.nix ../common/hardware/physical.nix @@ -23,6 +28,22 @@ boot.initrd.availableKernelModules = ["xhci_pci" "ahci" "nvme" "usbhid" "usb_storage" "sd_mod" "sdhci_pci" "r8169"]; + microvm.vms = { + test = let + node = + (import ../../nix/generate-node.nix inputs) + "ward-microvm-test" { + system = "x86_64-linux"; + config = ./microvms/test; + }; + in { + inherit (node) pkgs specialArgs; + config = { + inherit (node) imports; + }; + }; + }; + #services.authelia.instances.main = { # enable = true; # settings = { diff --git a/hosts/ward/microvms/test/default.nix b/hosts/ward/microvms/test/default.nix new file mode 100644 index 0000000..7d68ab9 --- /dev/null +++ b/hosts/ward/microvms/test/default.nix @@ -0,0 +1,28 @@ +{ + config, + inputs, + lib, + microvm, + nixos-hardware, + pkgs, + ... +}: { + imports = [ + microvm.microvm + + ../../../common/core + + ../../../../users/root + ]; + + systemd.network.networks = { + "10-wan" = { + # TODO + matchConfig.Name = "en*"; + DHCP = "yes"; + networkConfig.IPv6PrivacyExtensions = "kernel"; + dhcpV4Config.RouteMetric = 20; + dhcpV6Config.RouteMetric = 20; + }; + }; +} diff --git a/nix/generate-node.nix b/nix/generate-node.nix index 7b4e763..a81babf 100644 --- a/nix/generate-node.nix +++ b/nix/generate-node.nix @@ -25,21 +25,15 @@ in secrets = self.secrets.content; nodeSecrets = self.secrets.content.nodes.${nodeName}; nixos-hardware = nixos-hardware.nixosModules; + microvm = microvm.nixosModules; }; - imports = - [ - (../hosts + "/${nodeName}") - agenix.nixosModules.default - agenix-rekey.nixosModules.default - disko.nixosModules.disko - home-manager.nixosModules.default - impermanence.nixosModules.impermanence - nixos-nftables-firewall.nixosModules.default - ] - ++ optionals (nodeMeta.microVmHost or false) [ - microvm.nixosModules.host - ] - ++ optionals (nodeMeta.type == "microvm") [ - microvm.nixosModules.microvm - ]; + imports = [ + (nodeMeta.config or ../hosts + "/${nodeName}") + agenix.nixosModules.default + agenix-rekey.nixosModules.default + disko.nixosModules.disko + home-manager.nixosModules.default + impermanence.nixosModules.impermanence + nixos-nftables-firewall.nixosModules.default + ]; } diff --git a/nix/microvms.nix b/nix/microvms.nix deleted file mode 100644 index d085b77..0000000 --- a/nix/microvms.nix +++ /dev/null @@ -1,21 +0,0 @@ -{ - self, - nixpkgs, - ... -} @ inputs: let - inherit - (nixpkgs.lib) - filterAttrs - mapAttrs - nixosSystem - ; - - microvmNodes = filterAttrs (_: x: x.type == "microvm") self.hosts; - nodes = mapAttrs (import ./generate-node.nix inputs) microvmNodes; - generateMicrovmNode = nodeName: _: - nixosSystem { - inherit (nodes.${nodeName}) system pkgs specialArgs; - modules = nodes.${nodeName}.imports; - }; -in - mapAttrs generateMicrovmNode nodes diff --git a/nix/secrets.nix b/nix/secrets.nix index d605af3..440648c 100644 --- a/nix/secrets.nix +++ b/nix/secrets.nix @@ -18,7 +18,12 @@ } @ inputs: let inherit (nixpkgs.lib) + attrNames + concatMap + filterAttrs + listToAttrs mapAttrs + nameValuePair ; # If the given expression is a bare set, it will be wrapped in a function, # so that the imported file can always be applied to the inputs, similar to @@ -34,8 +39,26 @@ then builtins.extraBuiltins.rageImportEncrypted self.secrets.masterIdentities path else {} ); + + # Secrets for each physical node + nodeSecrets = mapAttrs (nodeName: _: importEncrypted ../hosts/${nodeName}/secrets/secrets.nix.age inputs) self.hosts; + + # A list of all nodes that have microvm directories + nodesWithMicrovms = builtins.filter (nodeName: builtins.pathExists ../hosts/${nodeName}/microvms) (attrNames self.hosts); + # Returns a list of all microvms defined for the given node + microvmsFor = nodeName: + attrNames (filterAttrs + (_: t: t == "directory") + (builtins.readDir ../hosts/${nodeName}/microvms)); + # Returns all defined microvms with name and definition for a given node + microvmDefsFor = nodeName: + map + (microvmName: nameValuePair "${nodeName}-microvm-${microvmName}" ../hosts/${nodeName}/microvms/${microvmName}) + (microvmsFor nodeName); + # A attrset mapping all microvm nodes to its definition folder + microvms = listToAttrs (concatMap microvmDefsFor nodesWithMicrovms); + # The secrets for each microvm + microvmSecrets = mapAttrs (microvmName: microvmPath: importEncrypted (microvmPath + "/secrets/secrets.nix.age") inputs) microvms; in (importEncrypted ../secrets/secrets.nix.age inputs) - // { - nodes = mapAttrs (hostName: _: importEncrypted ../hosts/${hostName}/secrets/secrets.nix.age inputs) self.hosts; - } + // {nodes = nodeSecrets // microvmSecrets;}