{ config, lib, pkgs, ... }: # It is not the intent to stick to the microvm.nix-like static interface, # but we shall begin by reproducing at least some of their work. let cfg = config.uvms.cloud-hypervisor; inherit (config.debug.closure.erofs) layers; in { options = { uvms.cloud-hypervisor.enable = lib.mkEnableOption "Configure guest (e.g. fileSystems)"; uvms.cloud-hypervisor.runner = lib.mkOption { type = lib.types.package; description = "A naive script for running this system in cloud-hypervisor"; }; uvms.cloud-hypervisor.extraArgv = lib.mkOption { type = lib.types.listOf lib.types.str; default = [ ]; }; uvms.cloud-hypervisor.argv = lib.mkOption { type = lib.types.listOf lib.types.str; }; uvms.cloud-hypervisor.extraCmdline = lib.mkOption { type = lib.types.listOf lib.types.str; default = [ ]; }; uvms.cloud-hypervisor.cmdline = lib.mkOption { type = lib.types.listOf lib.types.str; default = [ "earlyprintk=ttyS0" "console=ttyS0" "reboot=t" "panic=-1" "init=${config.system.build.toplevel}/init" ] ++ config.boot.kernelParams ++ config.uvms.cloud-hypervisor.extraCmdline; }; }; config = lib.mkMerge [ { uvms.cloud-hypervisor.argv = lib.mkBefore ( [ (lib.getExe pkgs.cloud-hypervisor) "--cmdline=${lib.concatStringsSep " " cfg.cmdline}" "--kernel=${config.boot.kernelPackages.kernel}/${pkgs.stdenv.hostPlatform.linux-kernel.target}" "--initramfs=${config.system.build.initialRamdisk}/${config.system.boot.loader.initrdFile}" "--vsock=cid=4,socket=CONNECT.sock" "--api-socket=ch.sock" "--serial=tty" "--console=null" "--watchdog" "--seccomp=true" ] ++ cfg.extraArgv ); uvms.cloud-hypervisor.runner = pkgs.writeShellScriptBin "run-${config.networking.hostName}" '' set -euo pipefail GUESTNAME=${config.networking.hostName} args=( ${lib.concatMapStringsSep "\n" lib.escapeShellArg cfg.argv} ) mkdir -p "$HOME/uvms/$GUESTNAME" cd "$HOME/uvms/$GUESTNAME" cleanup() { rm "$HOME/uvms/$GUESTNAME"/{ch,CONNECT}.sock } exec -a "uuvm/$GUESTNAME" "''${args[@]}" ''; } (lib.mkIf cfg.enable { boot.initrd.availableKernelModules = [ "erofs" "overlay" "virtio_mmio" "virtio_pci" "virtio_blk" # "9pnet_virtio" # "9p" "virtiofs" ]; boot.initrd.systemd.enable = true; fileSystems = { "/nix/store" = { fsType = "overlay"; overlay.lowerdir = map (img: "/nix/.ro-stores/${toString img.seq}") layers; neededForBoot = true; }; } // lib.listToAttrs ( map ( img: lib.nameValuePair "/nix/.ro-stores/${toString img.seq}" { device = "/dev/disk/by-label/${img.label}"; neededForBoot = true; options = [ "x-systemd.device-timeout=5" ]; } ) layers ); uvms.cloud-hypervisor.argv = [ "--memory=size=1536M,hotplug_size=1536M,hotplugged_size=512M,hotplug_method=virtio-mem,mergeable=on,shared=on" "--cpus=boot=4" "--disk" ] ++ map (img: "path=${img},readonly=true,id=${toString img.label}") layers; }) ]; }