From 057e8959a006d2ecd509e747285e983ae6c4071d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20Schwarz=C3=A4ugl?= Date: Tue, 7 Oct 2025 19:29:32 +0200 Subject: [PATCH] feat: initial microvm framework --- SwarselSystems.org | 104 +++++++++++++++++++++++ flake.nix | 4 + modules/nixos/optional/microvm-guest.nix | 64 ++++++++++++++ modules/nixos/optional/microvm-host.nix | 15 ++++ modules/shared/options.nix | 1 + nix/hosts.nix | 5 ++ 6 files changed, 193 insertions(+) create mode 100644 modules/nixos/optional/microvm-guest.nix create mode 100644 modules/nixos/optional/microvm-host.nix diff --git a/SwarselSystems.org b/SwarselSystems.org index 940be17..4ce21c1 100644 --- a/SwarselSystems.org +++ b/SwarselSystems.org @@ -483,6 +483,10 @@ A short overview over each input and what it does: url = "github:sodiboo/niri-flake"; inputs.nixpkgs.follows = "nixpkgs"; }; + microvm = { + url = "github:astro/microvm.nix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; }; outputs = @@ -851,10 +855,15 @@ The rest of the outputs either define or help define the actual configurations: inputs.nswitch-rcm-nix.nixosModules.nswitch-rcm inputs.swarsel-modules.nixosModules.default inputs.niri-flake.nixosModules.niri + inputs.microvm.nixosModules.host + inputs.microvm.nixosModules.microvm "${self}/hosts/nixos/${configName}" "${self}/profiles/nixos" "${self}/modules/nixos" { + + microvm.guest.enable = lib.mkDefault false; + node = { name = configName; secretsDir = ../hosts/nixos/${configName}/secrets; @@ -10771,6 +10780,100 @@ Options that I need specifically at work. There are more options at [[#h:f0b2ea9 } #+end_src +**** microvm-host + +Some standard options that should be set for every microvm host. + +#+begin_src nix-ts :tangle modules/nixos/optional/microvm-host.nix + { lib, config, ... }: + { + options.swarselmodules.optional.microvmHost = lib.mkEnableOption "optional microvmHost settings"; + # imports = [ + # inputs.microvm.nixosModules.host + # ]; + + config = lib.mkIf (config.swarselmodules.optional.microvmHost && config.swarselsystems.withMicroVMs) { + + microvm = { + hypervisor = lib.mkDefault "qemu"; + }; + }; + + } +#+end_src + +**** microvm-guest + +Some standard options that should be set vor every microvm guest. We set the default + +#+begin_src nix-ts :tangle modules/nixos/optional/microvm-guest.nix + { lib, config, ... }: + { + options.swarselmodules.optional.microvmGuest = lib.mkEnableOption "optional microvmGuest settings"; + # imports = [ + # inputs.microvm.nixosModules.microvm + # "${self}/profiles/nixos" + # "${self}/modules/nixos" + # ]; + config = lib.mkIf config.swarselmodules.optional.microvmGuest + { + # imports = [ + # inputs.microvm.nixosModules.microvm + + # "${self}/profiles/nixos" + # "${self}/modules/nixos" + # ]; + + boot.kernelParams = [ "systemd.hostname=${config.networking.hostName}" ]; + + node.name = config; + documentation.enable = lib.mkForce false; + + microvm = { + guest.enable = lib.mkForce true; + hypervisor = lib.mkDefault "qemu"; + mem = lib.mkDefault 1024 * 4; + vcpu = lib.mkDefault 4; + optimize.enable = false; + writableStoreOverlay = "/nix/.rw-store"; + + # interfaces = flip lib.mapAttrsToList guestCfg.microvm.interfaces ( + # _: { mac, hostLink, ...}: + # { + # type = "macvtap"; + # id = "vm-${replaceStrings [ ":" ] [ "" ] mac}"; + # inherit mac; + # macvtap = { + # link = hostLink; + # mode = "bridge"; + # }; + # } + # ); + shares = + [ + { + source = "/nix/store"; + mountPoint = "/nix/.ro-store"; + tag = "ro-store"; + proto = "virtiofs"; + } + ]; + }; + # systemd.network.networks = lib.flip lib.concatMapAttrs guestCfg.microvm.interfaces ( + # name: + # { mac, ... }: + # { + # "10-${name}".matchConfig = mkForce { + # MACAddress = mac; + # }; + # } + # ); + + }; + } + +#+end_src + ** Home-manager :PROPERTIES: :CUSTOM_ID: h:08ded95b-9c43-475d-a0b2-fc088a512287 @@ -14953,6 +15056,7 @@ TODO: check which of these can be replaced but builtin functions. default = "swarsel"; }; isCrypted = lib.mkEnableOption "uses full disk encryption"; + withMicroVMs = lib.mkEnableOption "enable MicroVMs on this host"; isImpermanence = lib.mkEnableOption "use impermanence on this system"; isSecureBoot = lib.mkEnableOption "use secure boot on this system"; diff --git a/flake.nix b/flake.nix index c6036ef..c7a9310 100644 --- a/flake.nix +++ b/flake.nix @@ -90,6 +90,10 @@ url = "github:sodiboo/niri-flake"; inputs.nixpkgs.follows = "nixpkgs"; }; + microvm = { + url = "github:astro/microvm.nix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; }; outputs = diff --git a/modules/nixos/optional/microvm-guest.nix b/modules/nixos/optional/microvm-guest.nix new file mode 100644 index 0000000..2eed2f8 --- /dev/null +++ b/modules/nixos/optional/microvm-guest.nix @@ -0,0 +1,64 @@ +{ lib, config, ... }: +{ + options.swarselmodules.optional.microvmGuest = lib.mkEnableOption "optional microvmGuest settings"; + # imports = [ + # inputs.microvm.nixosModules.microvm + # "${self}/profiles/nixos" + # "${self}/modules/nixos" + # ]; + config = lib.mkIf config.swarselmodules.optional.microvmGuest + { + # imports = [ + # inputs.microvm.nixosModules.microvm + + # "${self}/profiles/nixos" + # "${self}/modules/nixos" + # ]; + + boot.kernelParams = [ "systemd.hostname=${config.networking.hostName}" ]; + + node.name = config; + documentation.enable = lib.mkForce false; + + microvm = { + guest.enable = lib.mkForce true; + hypervisor = lib.mkDefault "qemu"; + mem = lib.mkDefault 1024 * 4; + vcpu = lib.mkDefault 4; + optimize.enable = false; + writableStoreOverlay = "/nix/.rw-store"; + + # interfaces = flip lib.mapAttrsToList guestCfg.microvm.interfaces ( + # _: { mac, hostLink, ...}: + # { + # type = "macvtap"; + # id = "vm-${replaceStrings [ ":" ] [ "" ] mac}"; + # inherit mac; + # macvtap = { + # link = hostLink; + # mode = "bridge"; + # }; + # } + # ); + shares = + [ + { + source = "/nix/store"; + mountPoint = "/nix/.ro-store"; + tag = "ro-store"; + proto = "virtiofs"; + } + ]; + }; + # systemd.network.networks = lib.flip lib.concatMapAttrs guestCfg.microvm.interfaces ( + # name: + # { mac, ... }: + # { + # "10-${name}".matchConfig = mkForce { + # MACAddress = mac; + # }; + # } + # ); + + }; +} diff --git a/modules/nixos/optional/microvm-host.nix b/modules/nixos/optional/microvm-host.nix new file mode 100644 index 0000000..73dac40 --- /dev/null +++ b/modules/nixos/optional/microvm-host.nix @@ -0,0 +1,15 @@ +{ lib, config, ... }: +{ + options.swarselmodules.optional.microvmHost = lib.mkEnableOption "optional microvmHost settings"; + # imports = [ + # inputs.microvm.nixosModules.host + # ]; + + config = lib.mkIf (config.swarselmodules.optional.microvmHost && config.swarselsystems.withMicroVMs) { + + microvm = { + hypervisor = lib.mkDefault "qemu"; + }; + }; + +} diff --git a/modules/shared/options.nix b/modules/shared/options.nix index f126351..d73c0a2 100644 --- a/modules/shared/options.nix +++ b/modules/shared/options.nix @@ -22,6 +22,7 @@ default = "swarsel"; }; isCrypted = lib.mkEnableOption "uses full disk encryption"; + withMicroVMs = lib.mkEnableOption "enable MicroVMs on this host"; isImpermanence = lib.mkEnableOption "use impermanence on this system"; isSecureBoot = lib.mkEnableOption "use secure boot on this system"; diff --git a/nix/hosts.nix b/nix/hosts.nix index 972ddca..2eb1b92 100644 --- a/nix/hosts.nix +++ b/nix/hosts.nix @@ -20,10 +20,15 @@ inputs.nswitch-rcm-nix.nixosModules.nswitch-rcm inputs.swarsel-modules.nixosModules.default inputs.niri-flake.nixosModules.niri + inputs.microvm.nixosModules.host + inputs.microvm.nixosModules.microvm "${self}/hosts/nixos/${configName}" "${self}/profiles/nixos" "${self}/modules/nixos" { + + microvm.guest.enable = lib.mkDefault false; + node = { name = configName; secretsDir = ../hosts/nixos/${configName}/secrets;