pkgs.uvms: init

...with some basic optional persistence and without having to rebuild
images for every app

nix run -f . pkgs.uvms -- --persist-home librewolf alacritty --run librewolf --run alacritty
This commit is contained in:
Else Someone 2026-02-27 18:26:41 +02:00
parent 22b613d157
commit 384b45bdef
15 changed files with 1155 additions and 452 deletions

View file

@ -9,7 +9,7 @@
# but we shall begin by reproducing at least some of their work.
let
cfg = config.uvms.cloud-hypervisor;
cfg = config.uvms.ch;
inherit (config.networking) hostName;
inherit (config.debug.closure.erofs) layers;
@ -48,69 +48,21 @@ let
in
{
options = {
uvms.cloud-hypervisor.enable = lib.mkEnableOption "Configure guest (e.g. fileSystems)";
uvms.cloud-hypervisor.runner = mkOption {
uvms.ch.enable = lib.mkEnableOption "Configure guest (e.g. fileSystems)";
uvms.ch.runner = mkOption {
type = types.package;
description = "A naive script for running this system in cloud-hypervisor";
};
uvms.cloud-hypervisor.debugger = mkOption {
uvms.ch.debugger = mkOption {
type = types.lazyAttrsOf types.anything;
description = "Same but you can debug the kernel";
};
uvms.cloud-hypervisor.settingsFile = mkOption {
uvms.ch.settingsFile = mkOption {
type = types.package;
default = chSettingsFile;
defaultText = "...";
readOnly = true;
};
uvms.cloud-hypervisor.settings = mkOption {
default = { };
type = types.submodule {
freeformType = (pkgs.formats.json { }).type;
options = {
payload = {
cmdline = mkOption { type = types.str; };
kernel = mkOption { type = types.str; };
initramfs = mkOption {
type = types.str;
default = "${config.system.build.initialRamdisk}/${config.system.boot.loader.initrdFile}";
};
};
vsock = {
cid = mkOption {
type = types.int;
default = 4;
};
socket = mkOption {
type = types.str;
default = "vsock.sock";
};
};
"api-socket" = mkOption {
type = types.str;
default = "vmm.sock";
};
"serial".mode = mkOption {
type = types.str;
default = "File";
};
"serial".file = mkOption {
type = types.nullOr types.str;
default = "serial";
};
"console".mode = mkOption {
type = types.str;
default = "Pty";
};
"console".file = mkOption {
type = types.nullOr types.str;
default = null;
};
# "watchdog" = true;
# "seccomp" = true;
};
};
};
uvms.cloud-hypervisor.extraCmdline = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
@ -118,44 +70,24 @@ in
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;
};
};
imports = [ ./baseImage.nix ];
config = lib.mkMerge [
{
# boot.kernelPackages = pkgs.linuxPackagesFor (uvmsPkgs.linux-uvm);
uvms.cloud-hypervisor.settings = {
payload = {
cmdline = lib.concatStringsSep " " cfg.cmdline;
kernel = "${config.boot.kernelPackages.kernel}/${pkgs.stdenv.hostPlatform.linux-kernel.target}";
};
disks = map (img: {
path = img;
readonly = true;
id = toString img.label;
}) layers;
uvms.ch.settings = {
memory = {
size = 1536 * 1048576;
shared = true;
mergeable = true;
# hotplugged_size = 512 * 1048576;
# hotplugd_size = 1536 * 1048576;
# hotplug_method = "virtio-mem"
};
cpus = {
boot_vcpus = 4;
max_vcpus = 4;
};
};
uvms.cloud-hypervisor.debugger = pkgs.testers.runNixOSTest (
uvms.ch.debugger = pkgs.testers.runNixOSTest (
{ config, ... }:
{
name = "test-run-${hostName}";
@ -265,39 +197,9 @@ in
);
# NOTE: Used to be an even uglier bash script, but, for now, execline makes for easier comparisons against spectrum
uvms.cloud-hypervisor.runner = writeElb "run-${hostName}" ''
uvms.ch.runner = writeElb "run-${hostName}" ''
${lib.getExe uvmsPkgs.uvms} --vm-config=${chSettingsFile} --vm=${hostName}
'';
}
(lib.mkIf cfg.enable {
boot.initrd.availableKernelModules = [
"erofs"
"overlay"
"virtio_mmio"
"virtio_pci"
"virtio_blk"
# "9pnet_virtio"
# "9p"
"virtiofs"
];
boot.initrd.systemd.enable = lib.mkDefault 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
);
})
];
}