clan-core/nixosModules/clanCore/vm.nix

260 lines
7.2 KiB
Nix
Raw Permalink Normal View History

2024-03-17 18:48:49 +00:00
{
lib,
config,
pkgs,
options,
extendModules,
modulesPath,
...
}:
2023-09-28 16:27:06 +00:00
let
# Flatten the list of state folders into a single list
2024-06-17 10:42:28 +00:00
stateFolders = lib.flatten (
lib.mapAttrsToList (_item: attrs: attrs.folders) config.clan.core.state
);
vmModule = {
imports = [
2023-09-28 16:27:06 +00:00
(modulesPath + "/virtualisation/qemu-vm.nix")
./serial.nix
2023-09-28 16:27:06 +00:00
];
# 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
2024-06-11 21:44:08 +00:00
# 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;
# currently needed for system.etc.overlay.enable
boot.kernelPackages = pkgs.linuxPackages_latest;
2024-03-17 18:48:49 +00:00
boot.initrd.systemd.storePaths = [
pkgs.util-linux
pkgs.e2fsprogs
];
2024-02-07 13:55:14 +00:00
boot.initrd.systemd.emergencyAccess = true;
2024-02-13 13:14:54 +00:00
# sysusers is faster than nixos's perl scripts
# and doesn't require state.
systemd.sysusers.enable = true;
users.mutableUsers = false;
users.allowNoPasswordLogin = true;
2024-02-07 13:55:14 +00:00
boot.initrd.kernelModules = [ "virtiofs" ];
virtualisation.writableStore = false;
2024-03-17 18:48:49 +00:00
virtualisation.fileSystems = lib.mkForce (
{
"/nix/store" = {
device = "nix-store";
options = [
"x-systemd.requires=systemd-modules-load.service"
"ro"
];
fsType = "virtiofs";
};
2024-02-07 13:55:14 +00:00
2024-03-17 18:48:49 +00:00
"/" = {
device = "/dev/vda";
fsType = "ext4";
options = [
"defaults"
"x-systemd.makefs"
"nobarrier"
"noatime"
"nodiratime"
"data=writeback"
"discard"
];
};
2024-02-09 15:50:58 +00:00
2024-03-17 18:48:49 +00:00
"/vmstate" = {
device = "/dev/vdb";
options = [
"x-systemd.makefs"
"noatime"
"nodiratime"
"discard"
];
noCheck = true;
fsType = "ext4";
};
2024-02-09 15:40:10 +00:00
2024-06-17 10:42:28 +00:00
${config.clan.core.secretsUploadDirectory} = {
2024-03-17 18:48:49 +00:00
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
)
);
};
# We cannot simply merge the VM config into the current system config, because
# it is not necessarily a VM.
# Instead we use extendModules to create a second instance of the current
# system configuration, and then merge the VM config into that.
2024-03-17 18:48:49 +00:00
vmConfig = extendModules { modules = [ vmModule ]; };
2023-09-28 16:27:06 +00:00
in
{
options = {
clan.virtualisation = {
cores = lib.mkOption {
type = lib.types.ints.positive;
default = 1;
2024-05-28 11:35:11 +00:00
description = ''
Specify the number of cores the guest is permitted to use.
The number can be higher than the available cores on the
host system.
'';
};
memorySize = lib.mkOption {
type = lib.types.ints.positive;
default = 1024;
2024-05-28 11:35:11 +00:00
description = ''
The memory size in megabytes of the virtual machine.
'';
};
graphics = lib.mkOption {
type = lib.types.bool;
default = true;
2024-05-28 11:35:11 +00:00
description = ''
Whether to run QEMU with a graphics window, or in nographic mode.
Serial console will be enabled on both settings, but this will
change the preferred console.
'';
};
waypipe = lib.mkOption {
type = lib.types.bool;
default = false;
2024-05-28 11:35:11 +00:00
description = ''
Whether to use waypipe for native wayland passthrough, or not.
'';
};
};
# All important VM config variables needed by the vm runner
# this is really just a remapping of values defined elsewhere
# and therefore not intended to be set by the user
2024-06-17 10:42:28 +00:00
clan.core.vm.inspect = {
clan_name = lib.mkOption {
type = lib.types.str;
internal = true;
readOnly = true;
description = ''
the name of the clan
'';
};
memory_size = lib.mkOption {
type = lib.types.int;
internal = true;
readOnly = true;
description = ''
the amount of memory to allocate to the vm
'';
};
cores = lib.mkOption {
type = lib.types.int;
internal = true;
readOnly = true;
description = ''
the number of cores to allocate to the vm
'';
};
graphics = lib.mkOption {
type = lib.types.bool;
internal = true;
readOnly = true;
description = ''
whether to enable graphics for the vm
'';
};
waypipe = lib.mkOption {
type = lib.types.bool;
internal = true;
readOnly = true;
description = ''
whether to enable native wayland window passthrough with waypipe for the vm
'';
};
machine_icon = lib.mkOption {
type = lib.types.nullOr lib.types.path;
internal = true;
readOnly = true;
description = ''
the location of the clan icon
'';
};
machine_name = lib.mkOption {
type = lib.types.str;
internal = true;
readOnly = true;
description = ''
the name of the vm
'';
};
machine_description = lib.mkOption {
type = lib.types.nullOr lib.types.str;
internal = true;
readOnly = true;
description = ''
the description of the vm
'';
};
};
};
config = {
# for clan vm inspect
2024-06-17 10:42:28 +00:00
clan.core.vm.inspect = {
clan_name = config.clan.core.clanName;
machine_icon = config.clan.core.machineIcon or config.clan.core.clanIcon;
machine_name = config.clan.core.machineName;
machine_description = config.clan.core.machineDescription;
memory_size = config.clan.virtualisation.memorySize;
inherit (config.clan.virtualisation) cores graphics waypipe;
};
# for clan vm create
2023-09-28 16:27:06 +00:00
system.clan.vm = {
2024-03-17 18:48:49 +00:00
create = pkgs.writeText "vm.json" (
builtins.toJSON {
initrd = "${vmConfig.config.system.build.initialRamdisk}/${vmConfig.config.system.boot.loader.initrdFile}";
toplevel = vmConfig.config.system.build.toplevel;
regInfo = (pkgs.closureInfo { rootPaths = vmConfig.config.virtualisation.additionalPaths; });
inherit (config.clan.virtualisation) memorySize cores graphics;
}
);
};
virtualisation = lib.optionalAttrs (options.virtualisation ? cores) {
memorySize = lib.mkDefault config.clan.virtualisation.memorySize;
graphics = lib.mkDefault config.clan.virtualisation.graphics;
cores = lib.mkDefault config.clan.virtualisation.cores;
};
};
2023-09-14 14:57:19 +00:00
}