diff --git a/nixosModules/clanCore/vm-base.nix b/nixosModules/clanCore/vm-base.nix new file mode 100644 index 000000000..739cf57b8 --- /dev/null +++ b/nixosModules/clanCore/vm-base.nix @@ -0,0 +1,116 @@ +# Standalone VM base module that can be imported independently +# This module contains the core VM configuration without the system extension +{ + lib, + config, + pkgs, + modulesPath, + ... +}: +let + # Flatten the list of state folders into a single list + stateFolders = lib.flatten ( + lib.mapAttrsToList (_item: attrs: attrs.folders) config.clan.core.state + ); +in +{ + imports = [ + (modulesPath + "/virtualisation/qemu-vm.nix") + ./serial.nix + ./waypipe.nix + ]; + + clan.core.state.HOME.folders = [ "/home" ]; + + clan.services.waypipe = { + inherit (config.clan.core.vm.inspect.waypipe) enable command; + }; + + # required for issuing shell commands via qga + services.qemuGuest.enable = true; + + # required to react to system_powerdown qmp command + # Some desktop managers like xfce override the poweroff signal and therefore + # make it impossible to handle it via 'logind' directly. + services.acpid.enable = true; + services.acpid.handlers.power.event = "button/power.*"; + services.acpid.handlers.power.action = "poweroff"; + + # only works on x11 + services.spice-vdagentd.enable = config.services.xserver.enable; + + boot.initrd.systemd.enable = true; + + boot.initrd.systemd.storePaths = [ + pkgs.util-linux + pkgs.e2fsprogs + ]; + boot.initrd.systemd.emergencyAccess = true; + + # userborn would be faster because it doesn't need perl, but it cannot create normal users + services.userborn.enable = true; + users.mutableUsers = false; + users.allowNoPasswordLogin = true; + + boot.initrd.kernelModules = [ "virtiofs" ]; + virtualisation.writableStore = false; + virtualisation.fileSystems = lib.mkForce ( + { + "/nix/store" = { + device = "nix-store"; + options = [ + "x-systemd.requires=systemd-modules-load.service" + "ro" + ]; + fsType = "virtiofs"; + }; + + "/" = { + device = "/dev/vda"; + fsType = "ext4"; + options = [ + "defaults" + "x-systemd.makefs" + "nobarrier" + "noatime" + "nodiratime" + "data=writeback" + "discard" + ]; + }; + + "/vmstate" = { + device = "/dev/vdb"; + options = [ + "x-systemd.makefs" + "noatime" + "nodiratime" + "discard" + ]; + noCheck = true; + fsType = "ext4"; + }; + + ${config.clan.core.facts.secretUploadDirectory} = { + device = "secrets"; + fsType = "9p"; + neededForBoot = true; + options = [ + "trans=virtio" + "version=9p2000.L" + "cache=loose" + ]; + }; + } + // lib.listToAttrs ( + map ( + folder: + lib.nameValuePair folder { + device = "/vmstate${folder}"; + fsType = "none"; + options = [ "bind" ]; + } + ) stateFolders + ) + ); +} diff --git a/nixosModules/clanCore/vm.nix b/nixosModules/clanCore/vm.nix index c3c6c73ac..bcd2efac8 100644 --- a/nixosModules/clanCore/vm.nix +++ b/nixosModules/clanCore/vm.nix @@ -4,116 +4,11 @@ pkgs, options, extendModules, - modulesPath, ... }: let - # Flatten the list of state folders into a single list - stateFolders = lib.flatten ( - lib.mapAttrsToList (_item: attrs: attrs.folders) config.clan.core.state - ); - - vmModule = { - imports = [ - (modulesPath + "/virtualisation/qemu-vm.nix") - ./serial.nix - ./waypipe.nix - ]; - - clan.core.state.HOME.folders = [ "/home" ]; - - clan.services.waypipe = { - inherit (config.clan.core.vm.inspect.waypipe) enable command; - }; - - # required for issuing shell commands via qga - services.qemuGuest.enable = true; - - # required to react to system_powerdown qmp command - # Some desktop managers like xfce override the poweroff signal and therefore - # make it impossible to handle it via 'logind' directly. - services.acpid.enable = true; - services.acpid.handlers.power.event = "button/power.*"; - services.acpid.handlers.power.action = "poweroff"; - - # only works on x11 - services.spice-vdagentd.enable = config.services.xserver.enable; - - boot.initrd.systemd.enable = true; - - boot.initrd.systemd.storePaths = [ - pkgs.util-linux - pkgs.e2fsprogs - ]; - boot.initrd.systemd.emergencyAccess = true; - - # userborn would be faster because it doesn't need perl, but it cannot create normal users - services.userborn.enable = true; - users.mutableUsers = false; - users.allowNoPasswordLogin = true; - - boot.initrd.kernelModules = [ "virtiofs" ]; - virtualisation.writableStore = false; - virtualisation.fileSystems = lib.mkForce ( - { - "/nix/store" = { - device = "nix-store"; - options = [ - "x-systemd.requires=systemd-modules-load.service" - "ro" - ]; - fsType = "virtiofs"; - }; - - "/" = { - device = "/dev/vda"; - fsType = "ext4"; - options = [ - "defaults" - "x-systemd.makefs" - "nobarrier" - "noatime" - "nodiratime" - "data=writeback" - "discard" - ]; - }; - - "/vmstate" = { - device = "/dev/vdb"; - options = [ - "x-systemd.makefs" - "noatime" - "nodiratime" - "discard" - ]; - noCheck = true; - fsType = "ext4"; - }; - - ${config.clan.core.facts.secretUploadDirectory} = { - device = "secrets"; - fsType = "9p"; - neededForBoot = true; - options = [ - "trans=virtio" - "version=9p2000.L" - "cache=loose" - ]; - }; - } - // lib.listToAttrs ( - map ( - folder: - lib.nameValuePair folder { - device = "/vmstate${folder}"; - fsType = "none"; - options = [ "bind" ]; - } - ) stateFolders - ) - ); - }; + # Import the standalone VM base module + vmModule = import ./vm-base.nix; # We cannot simply merge the VM config into the current system config, because # it is not necessarily a VM. diff --git a/nixosModules/flake-module.nix b/nixosModules/flake-module.nix index 0662361db..3d82fec62 100644 --- a/nixosModules/flake-module.nix +++ b/nixosModules/flake-module.nix @@ -34,4 +34,7 @@ in flake.nixosModules.clanCore = clanCore; flake.darwinModules.clanCore = clanCore; + + # Standalone VM base module that can be imported for VM testing + flake.nixosModules.clan-vm-base = ./clanCore/vm-base.nix; } diff --git a/pkgs/clan-cli/clan_cli/tests/flake-module.nix b/pkgs/clan-cli/clan_cli/tests/flake-module.nix index a60bf8e37..c37b075ff 100644 --- a/pkgs/clan-cli/clan_cli/tests/flake-module.nix +++ b/pkgs/clan-cli/clan_cli/tests/flake-module.nix @@ -25,6 +25,8 @@ test-vm-persistence = { config, ... }: { + imports = [ self.nixosModules.clan-vm-base ]; + system.stateVersion = config.system.nixos.release; # Disable services that might cause issues in tests @@ -62,6 +64,8 @@ test-vm-deployment = { config, lib, ... }: { + imports = [ self.nixosModules.clan-vm-base ]; + system.stateVersion = config.system.nixos.release; # Disable services that might cause issues in tests