diff --git a/machines/configuration.nix b/machines/configuration.nix index 69fdb0d..0f6e628 100644 --- a/machines/configuration.nix +++ b/machines/configuration.nix @@ -202,5 +202,4 @@ in specialArgs.self = self; modules = defaultModules ++ [ ./testvm ]; }; - } diff --git a/machines/fanny/configuration.nix b/machines/fanny/configuration.nix index 2eb0c6b..84ac843 100644 --- a/machines/fanny/configuration.nix +++ b/machines/fanny/configuration.nix @@ -53,7 +53,7 @@ in }; services.malobeo.microvm.enableHostBridge = true; - services.malobeo.microvm.deployHosts = [ "infradocs" "nextcloud" ]; + services.malobeo.microvm.deployHosts = [ "infradocs" "nextcloud" "overwatch" ]; networking = { firewall = { diff --git a/machines/modules/malobeo/microvm_host.nix b/machines/modules/malobeo/microvm_host.nix index f665553..5db2570 100644 --- a/machines/modules/malobeo/microvm_host.nix +++ b/machines/modules/malobeo/microvm_host.nix @@ -86,6 +86,12 @@ in in builtins.listToAttrs (map mapperFunc cfg.deployHosts); + systemd.tmpfiles.rules = builtins.concatLists (map (name: [ + "d /var/lib/microvms/${name}/var 0755 root root - -" + "d /var/lib/microvms/${name}/etc 0755 root root - -" + "d /${name} 0755 root root - -" + ]) cfg.deployHosts); + systemd.services = builtins.foldl' (services: name: services // { "microvm-update@${name}" = { description = "Update MicroVMs automatically"; diff --git a/machines/vpn/configuration.nix b/machines/vpn/configuration.nix index bd67ecf..f7ba6b2 100644 --- a/machines/vpn/configuration.nix +++ b/machines/vpn/configuration.nix @@ -17,6 +17,7 @@ with lib; }; imports = [ + inputs.self.nixosModules.malobeo.vpn ../modules/malobeo_user.nix ../modules/sshd.nix ../modules/minimal_tools.nix diff --git a/outputs.nix b/outputs.nix index 9cfbf03..fd0bb5b 100644 --- a/outputs.nix +++ b/outputs.nix @@ -12,6 +12,97 @@ let filter_system = name: if name == utils.lib.system.i686-linux then false else true; in (utils.lib.eachSystem (builtins.filter filter_system utils.lib.defaultSystems) ( system: let + baseModules = [ + # make flake inputs accessiable in NixOS + { _module.args.inputs = inputs; } + { + imports = [ + ({ pkgs, ... }: { + nix = { + extraOptions = '' + experimental-features = nix-command flakes + ''; + + settings = { + substituters = [ + "https://cache.dynamicdiscord.de" + "https://cache.nixos.org/" + ]; + trusted-public-keys = [ + "cache.dynamicdiscord.de:DKueZicqi2NhJJXz9MYgUbiyobMs10fTyHCgAUibRP4=" + ]; + trusted-users = [ "root" "@wheel" ]; + }; + }; + }) + sops-nix.nixosModules.sops + #microvm.nixosModules.microvm + ]; + } + ]; + defaultModules = baseModules; + + makeMicroVM = hostName: ipv4Addr: macAddr: modules: [ + self.nixosModules.malobeo.metrics + { + microvm = { + hypervisor = "cloud-hypervisor"; + mem = 2560; + shares = [ + { + source = "/nix/store"; + mountPoint = "/nix/.ro-store"; + tag = "store"; + proto = "virtiofs"; + socket = "store.socket"; + } + { + source = "/var/lib/microvms/${hostName}/etc"; + mountPoint = "/etc"; + tag = "etc"; + proto = "virtiofs"; + socket = "etc.socket"; + } + { + source = "/var/lib/microvms/${hostName}/var"; + mountPoint = "/var"; + tag = "var"; + proto = "virtiofs"; + socket = "var.socket"; + } + ]; + + interfaces = [ + { + type = "tap"; + id = "vm-${hostName}"; + mac = "${macAddr}"; + } + ]; + }; + + malobeo.metrics = { + enable = true; + enablePromtail = true; + logNginx = false; + lokiHost = "10.0.0.14"; + }; + + systemd.network.enable = true; + + systemd.network.networks."20-lan" = { + matchConfig.Type = "ether"; + networkConfig = { + Address = [ "${ipv4Addr}/24" ]; + Gateway = "10.0.0.1"; + DNS = ["1.1.1.1"]; + DHCP = "no"; + }; + }; + } + ] ++ defaultModules ++ modules; + + pkgs-unstable = nixpkgs-unstable.legacyPackages."${system}"; pkgs = nixpkgs.legacyPackages."${system}"; @@ -20,7 +111,17 @@ in (utils.lib.eachSystem (builtins.filter filter_system utils.lib.defaultSystems mem = pkgs.lib.mkForce 4096; hypervisor = pkgs.lib.mkForce "qemu"; socket = pkgs.lib.mkForce null; - shares = pkgs.lib.mkForce ([ + + + #needed for hosts that deploy imperative microvms (for example fanny) + writableStoreOverlay = pkgs.lib.mkIf options.writableStore "/nix/.rw-store"; + volumes = pkgs.lib.mkIf options.writableStore [ { + image = "nix-store-overlay.img"; + mountPoint = self.nixosConfigurations.${hostname}.config.microvm.writableStoreOverlay; + size = 2048; + } ]; + + shares = pkgs.lib.mkForce (pkgs.lib.optionals (!options.writableStore) [ { tag = "ro-store"; source = "/nix/store"; @@ -34,11 +135,18 @@ in (utils.lib.eachSystem (builtins.filter filter_system utils.lib.defaultSystems tag = "var"; } ]); + interfaces = pkgs.lib.mkIf (!options.withNetworking) (pkgs.lib.mkForce [{ type = "user"; id = "eth0"; mac = "02:23:de:ad:be:ef"; }]); + + #if networking is disabled forward port 80 to still have access to webservices + forwardPorts = pkgs.lib.mkIf (!options.withNetworking) (pkgs.lib.mkForce [ + { from = "host"; host.port = 8080; guest.port = 80; } + ]); + }; fileSystems = { @@ -86,15 +194,59 @@ in (utils.lib.eachSystem (builtins.filter filter_system utils.lib.defaultSystems }]; }; - buildVM = host: networking: sopsDummy: disableDisko: varPath: (self.nixosConfigurations.${host}.extendModules { + buildVM = host: networking: sopsDummy: disableDisko: varPath: writableStore: (self.nixosConfigurations.${host}.extendModules { modules = [ - (vmMicroVMOverwrites host { withNetworking = networking; varPath = "${varPath}"; }) + (vmMicroVMOverwrites host { + withNetworking = networking; + varPath = "${varPath}"; + writableStore = writableStore; }) (if sopsDummy then (vmSopsOverwrites host) else {}) (if disableDisko then vmDiskoOverwrites else {}) ] ++ pkgs.lib.optionals (! self.nixosConfigurations.${host}.config ? microvm) [ - microvm.nixosModules.microvm - ]; - }).config.microvm.declaredRunner; + #microvm.nixosModules.microvm + ] ++ pkgs.lib.optionals (self.nixosConfigurations.${host}.config ? services.malobeo.microvm.deployHosts) [ + #microvm.nixosModules.host + { + services.malobeo.microvm.deployHosts = pkgs.lib.mkForce []; + systemd.tmpfiles.rules = builtins.concatLists (map (name: [ + "q /var/lib/microvms/${name}/var 0755 root root - -" + "q /var/lib/microvms/${name}/etc 0755 root root - -" + "q /var/${name}/wow/it/works 0755 root root - -" + "q /var/lib/${name} 0755 root root - -" + "d /${name} 0755 root root - -" + ]) self.nixosConfigurations.${host}.config.services.malobeo.microvm.deployHosts); + + + microvm.vms = + let + # Map the values to each hostname to then generate an Attrset using listToAttrs + mapperFunc = name: { inherit name; value = { + #pkgs = import self.nixosConfigurations.${name}.config.nixpkgs; + + #pkgs = (buildVM name networking sopsDummy false "" false).config.nixpkgs; + #config = (buildVM name networking sopsDummy false "" false); + #pkgs = pkgs; + #config = self.nixosConfigurations.${name}; + specialArgs.inputs = inputs; + specialArgs.self = self; + config = { + imports = (makeMicroVM "${name}" "10.0.0.11" "D0:E5:CA:F0:D7:E7" [ + + #(vmMicroVMOverwrites name { + # withNetworking = true; + # varPath = ""; + # writableStore = false; }) + (if sopsDummy then (vmSopsOverwrites name) else {}) + + + ]); + + }; + }; }; + in + builtins.listToAttrs (map mapperFunc self.nixosConfigurations.${host}.config.services.malobeo.microvm.deployHosts); + }]; + }); in { devShells.default = @@ -157,6 +309,7 @@ in (utils.lib.eachSystem (builtins.filter filter_system utils.lib.defaultSystems echo "--networking setup interfaces. requires root and hostbridge enabled on the host" echo "--dummy-secrets run vm with dummy sops secrets" echo "--no-disko disable disko and initrd secrets. needed for real hosts like fanny" + echo "--writable-store enables writable store. necessary for host with nested imperative microvms like fanny" echo "--var path to directory that should be shared as /var. may require root otherwise some systemd units fail within vm. if dir is empty vm will populate" exit 1 } @@ -172,6 +325,7 @@ in (utils.lib.eachSystem (builtins.filter filter_system utils.lib.defaultSystems NETWORK=false DUMMY_SECRETS=false NO_DISKO=false + RW_STORE=false VAR_PATH="" # check argws @@ -181,6 +335,7 @@ in (utils.lib.eachSystem (builtins.filter filter_system utils.lib.defaultSystems --networking) NETWORK=true ;; --dummy-secrets) DUMMY_SECRETS=true ;; --no-disko) NO_DISKO=true ;; + --writable-store) RW_STORE=true ;; --var) if [[ -n "$2" && ! "$2" =~ ^- ]]; then VAR_PATH="$2" @@ -198,11 +353,12 @@ in (utils.lib.eachSystem (builtins.filter filter_system utils.lib.defaultSystems echo "enable networking: $NETWORK" echo "deploy dummy secrets: $DUMMY_SECRETS" echo "disable disko and initrd secrets: $NO_DISKO" + echo "use writable store: $RW_STORE" if [ -n "$VAR_PATH" ]; then echo "sharing var directory: $VAR_PATH" fi - ${pkgs.nix}/bin/nix run --show-trace --impure --expr "((builtins.getFlake \"$(pwd)\").vmBuilder.x86_64-linux \"$HOSTNAME\" $NETWORK $DUMMY_SECRETS $NO_DISKO \"$VAR_PATH\")" + ${pkgs.nix}/bin/nix run --show-trace --impure --expr "((builtins.getFlake \"$(pwd)\").vmBuilder.x86_64-linux \"$HOSTNAME\" $NETWORK $DUMMY_SECRETS $NO_DISKO \"$VAR_PATH\" $RW_STORE).config.microvm.declaredRunner" ''; };