Instead of passing raw crosvm attrsets, sound is now configured with two booleans: sound.playback (default true) and sound.capture (default false, implies playback). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
876 lines
28 KiB
Nix
876 lines
28 KiB
Nix
# Option definitions for vmsilo NixOS module
|
|
{
|
|
config,
|
|
pkgs,
|
|
lib,
|
|
...
|
|
}:
|
|
|
|
let
|
|
cfg = config.programs.vmsilo;
|
|
|
|
# Shared route submodule type for IPv4/IPv6 routes
|
|
routeSubmodule = lib.types.attrsOf (
|
|
lib.types.submodule {
|
|
options.via = lib.mkOption {
|
|
type = lib.types.str;
|
|
description = "Gateway address for this route.";
|
|
};
|
|
}
|
|
);
|
|
|
|
# Network interface configuration submodule (for vm.network.interfaces)
|
|
networkInterfaceSubmodule = lib.types.submodule {
|
|
options = {
|
|
type = lib.mkOption {
|
|
type = lib.types.enum [
|
|
"tap"
|
|
];
|
|
default = "tap";
|
|
description = "Interface type: 'tap' for host tap interface.";
|
|
};
|
|
|
|
macAddress = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.str;
|
|
default = null;
|
|
description = "MAC address. Auto-generated from SHA1('<vmName>-<ifName>') if null.";
|
|
example = "52:ab:cd:ef:12:34";
|
|
};
|
|
|
|
tap = lib.mkOption {
|
|
type = lib.types.nullOr (
|
|
lib.types.submodule {
|
|
options = {
|
|
name = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.str;
|
|
default = null;
|
|
description = "TAP interface name on host. Defaults to '<vmname>-<ifIndex>'.";
|
|
};
|
|
hostAddress = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.str;
|
|
default = null;
|
|
description = "Host-side IP address with prefix (e.g., '10.0.0.254/24'). If null, the TAP is created without a host IP. Mutually exclusive with bridge.";
|
|
example = "10.0.0.254/24";
|
|
};
|
|
bridge = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.str;
|
|
default = null;
|
|
description = "Bridge name to add this TAP interface to (via networking.bridges). Mutually exclusive with hostAddress.";
|
|
example = "br0";
|
|
};
|
|
};
|
|
}
|
|
);
|
|
default = null;
|
|
description = "TAP interface configuration. Required when type = 'tap'.";
|
|
};
|
|
|
|
dhcp = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
description = "Enable DHCP for this interface.";
|
|
};
|
|
|
|
addresses = lib.mkOption {
|
|
type = lib.types.listOf lib.types.str;
|
|
default = [ ];
|
|
description = "Static IPv4 addresses with prefix (e.g., '10.0.0.1/24').";
|
|
example = [ "10.0.0.1/24" ];
|
|
};
|
|
|
|
routes = lib.mkOption {
|
|
type = routeSubmodule;
|
|
default = { };
|
|
description = "IPv4 routes. Keys are destination CIDRs, values have 'via' gateway.";
|
|
example = lib.literalExpression ''{ "0.0.0.0/0" = { via = "10.0.0.254"; }; }'';
|
|
};
|
|
|
|
v6Addresses = lib.mkOption {
|
|
type = lib.types.listOf lib.types.str;
|
|
default = [ ];
|
|
description = "Static IPv6 addresses with prefix.";
|
|
example = [ "fc00::2/64" ];
|
|
};
|
|
|
|
v6Routes = lib.mkOption {
|
|
type = routeSubmodule;
|
|
default = { };
|
|
description = "IPv6 routes. Keys are destination CIDRs, values have 'via' gateway.";
|
|
example = lib.literalExpression ''{ "::/0" = { via = "fc00::1"; }; }'';
|
|
};
|
|
};
|
|
};
|
|
|
|
# Network configuration submodule (for vm.network)
|
|
networkSubmodule = lib.types.submodule {
|
|
options = {
|
|
nameservers = lib.mkOption {
|
|
type = lib.types.listOf lib.types.str;
|
|
default = [ ];
|
|
description = "DNS nameservers for this VM.";
|
|
example = [
|
|
"8.8.8.8"
|
|
"1.1.1.1"
|
|
];
|
|
};
|
|
|
|
interfaces = lib.mkOption {
|
|
type = lib.types.attrsOf networkInterfaceSubmodule;
|
|
default = { };
|
|
description = "Network interfaces for this VM. Keys are guest-visible interface names.";
|
|
};
|
|
};
|
|
};
|
|
|
|
# Type for attribute values in crosvm argument attrsets
|
|
attrValueType = lib.types.oneOf [
|
|
lib.types.str
|
|
lib.types.int
|
|
lib.types.bool
|
|
];
|
|
|
|
# Type for crosvm argument attrsets (used for gpu, sound, etc.)
|
|
crosvmAttrsetType = lib.types.attrsOf attrValueType;
|
|
|
|
# Type for free-form attrsets (disks, pciDevices, sharedDirectories, vhostUser)
|
|
freeformAttrsetType = lib.types.attrsOf (lib.types.nullOr attrValueType);
|
|
|
|
vmSubmodule = lib.types.submodule {
|
|
options = {
|
|
name = lib.mkOption {
|
|
type = lib.types.str;
|
|
description = "VM name. Used for TAP interface naming and scripts.";
|
|
example = "banking";
|
|
};
|
|
|
|
color = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "red";
|
|
description = ''
|
|
Window decoration color for this VM. Used in wayland security context.
|
|
Supported formats: named colors ("red", "green"), hex ("#FF0000"), RGB ("rgb(255,0,0)").
|
|
'';
|
|
example = "#3498db";
|
|
};
|
|
|
|
waylandProxy = lib.mkOption {
|
|
type = lib.types.enum [
|
|
"wayland-proxy-virtwl"
|
|
"sommelier"
|
|
];
|
|
default = "wayland-proxy-virtwl";
|
|
description = "Wayland proxy to use in the guest VM.";
|
|
example = "sommelier";
|
|
};
|
|
|
|
memory = lib.mkOption {
|
|
type = lib.types.int;
|
|
default = 1024;
|
|
description = "Memory allocation in MB.";
|
|
example = 4096;
|
|
};
|
|
|
|
cpus = lib.mkOption {
|
|
type = lib.types.int;
|
|
default = 2;
|
|
description = "Number of virtual CPUs.";
|
|
example = 4;
|
|
};
|
|
|
|
network = lib.mkOption {
|
|
type = networkSubmodule;
|
|
default = { };
|
|
description = "Network configuration for this VM.";
|
|
example = lib.literalExpression ''
|
|
{
|
|
nameservers = [ "8.8.8.8" ];
|
|
interfaces = {
|
|
wan = {
|
|
type = "tap";
|
|
tap.hostAddress = "10.0.0.254/24";
|
|
addresses = [ "10.0.0.1/24" ];
|
|
routes."0.0.0.0/0" = { via = "10.0.0.254"; };
|
|
};
|
|
};
|
|
}
|
|
'';
|
|
};
|
|
|
|
autoShutdown = lib.mkOption {
|
|
type = lib.types.submodule {
|
|
options = {
|
|
enable = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
description = "Enable auto-shutdown when idle. VM shuts down after autoShutdown.after seconds with no active commands.";
|
|
};
|
|
|
|
after = lib.mkOption {
|
|
type = lib.types.int;
|
|
default = 60;
|
|
description = "Seconds to wait after last command exits before shutting down.";
|
|
};
|
|
};
|
|
};
|
|
default = { };
|
|
description = "Auto-shutdown configuration for idle VMs.";
|
|
};
|
|
|
|
autoStart = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
description = "Start this VM automatically at boot instead of on-demand via socket activation.";
|
|
};
|
|
|
|
rootOverlay = lib.mkOption {
|
|
type = lib.types.submodule {
|
|
options = {
|
|
type = lib.mkOption {
|
|
type = lib.types.enum [
|
|
"qcow2"
|
|
"tmpfs"
|
|
];
|
|
default = "qcow2";
|
|
description = "Overlay upper layer type: 'qcow2' (disk-backed, default) or 'tmpfs' (RAM-backed).";
|
|
};
|
|
|
|
size = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "10G";
|
|
description = "Maximum size of ephemeral disk (qcow2 only). Parsed by qemu-img create.";
|
|
example = "20G";
|
|
};
|
|
};
|
|
};
|
|
default = { };
|
|
description = "Root overlay configuration. Controls where VM writes go.";
|
|
};
|
|
|
|
dependsOn = lib.mkOption {
|
|
type = lib.types.listOf lib.types.str;
|
|
default = [ ];
|
|
description = "List of VM names to start when this VM starts.";
|
|
};
|
|
|
|
additionalDisks = lib.mkOption {
|
|
type = lib.types.listOf freeformAttrsetType;
|
|
default = [ ];
|
|
description = ''
|
|
Additional disks to attach to the VM. Each attrset requires `path` (positional).
|
|
Other keys are passed directly to crosvm --block (e.g., ro, sparse, block-size, id).
|
|
'';
|
|
example = lib.literalExpression ''
|
|
[{
|
|
path = "/tmp/data.qcow2";
|
|
ro = false;
|
|
sparse = true;
|
|
block-size = 4096;
|
|
id = "datadisk";
|
|
}]
|
|
'';
|
|
};
|
|
|
|
rootDisk = lib.mkOption {
|
|
type = lib.types.nullOr freeformAttrsetType;
|
|
default = null;
|
|
description = ''
|
|
Custom root disk. If not set, uses the built rootfs image with rootDiskReadonly.
|
|
Requires `path` (positional). Other keys are passed directly to crosvm --block.
|
|
'';
|
|
example = lib.literalExpression ''
|
|
{
|
|
path = "/path/to/custom-root.qcow2";
|
|
ro = true;
|
|
}
|
|
'';
|
|
};
|
|
|
|
kernel = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.path;
|
|
default = null;
|
|
description = "Custom kernel image. If not set, uses the built rootfs kernel.";
|
|
example = "/path/to/bzImage";
|
|
};
|
|
|
|
initramfs = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.path;
|
|
default = null;
|
|
description = "Custom initramfs. If not set, uses the built rootfs initrd.";
|
|
example = "/path/to/initrd";
|
|
};
|
|
|
|
rootDiskReadonly = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = true;
|
|
description = "Whether the built rootfs should be read-only. Ignored when rootDisk is set.";
|
|
};
|
|
|
|
copyChannel = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
description = "Include a NixOS channel in the rootfs image, built from the same nixpkgs revision used to build the VM.";
|
|
};
|
|
|
|
sharedHome = lib.mkOption {
|
|
type = lib.types.either lib.types.bool lib.types.str;
|
|
default = true;
|
|
description = ''
|
|
Share a host directory as /home/user in the guest via virtiofs.
|
|
Set to true for default path (/shared/<vmname>), a string for a custom host path, or false to disable.
|
|
'';
|
|
example = "/data/vms/banking-home";
|
|
};
|
|
|
|
kernelParams = lib.mkOption {
|
|
type = lib.types.listOf lib.types.str;
|
|
default = [ ];
|
|
description = "Extra kernel command line parameters.";
|
|
example = [
|
|
"acpi=off"
|
|
"debug"
|
|
];
|
|
};
|
|
|
|
gpu = lib.mkOption {
|
|
type = lib.types.either lib.types.bool crosvmAttrsetType;
|
|
default = true;
|
|
description = ''
|
|
GPU configuration. Set to false to disable, true for default config,
|
|
or an attrset for custom --gpu options.
|
|
'';
|
|
example = lib.literalExpression ''
|
|
{
|
|
context-types = "cross-domain:virgl2";
|
|
width = 1920;
|
|
height = 1080;
|
|
}
|
|
'';
|
|
};
|
|
|
|
sound = {
|
|
playback = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = true;
|
|
description = "Enable sound playback.";
|
|
};
|
|
capture = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
description = "Enable sound capture. Implies playback.";
|
|
};
|
|
};
|
|
|
|
sharedDirectories = lib.mkOption {
|
|
type = lib.types.attrsOf (
|
|
lib.types.submodule {
|
|
options = {
|
|
path = lib.mkOption {
|
|
type = lib.types.str;
|
|
description = "Host directory path to share with the guest.";
|
|
};
|
|
threadPoolSize = lib.mkOption {
|
|
type = lib.types.int;
|
|
default = 0;
|
|
description = "Thread pool size for virtiofsd.";
|
|
};
|
|
xattr = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = true;
|
|
description = "Enable extended attributes.";
|
|
};
|
|
posixAcl = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = true;
|
|
description = "Enable POSIX ACLs. Incompatible with translateUid/translateGid.";
|
|
};
|
|
readonly = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
description = "Share as read-only.";
|
|
};
|
|
inodeFileHandles = lib.mkOption {
|
|
type = lib.types.enum [
|
|
"never"
|
|
"prefer"
|
|
"mandatory"
|
|
];
|
|
default = "prefer";
|
|
description = "Inode file handles mode.";
|
|
};
|
|
cache = lib.mkOption {
|
|
type = lib.types.enum [
|
|
"auto"
|
|
"always"
|
|
"never"
|
|
"metadata"
|
|
];
|
|
default = "auto";
|
|
description = "Cache policy.";
|
|
};
|
|
allowMmap = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
description = "Allow memory-mapped I/O.";
|
|
};
|
|
enableReaddirplus = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = true;
|
|
description = "Enable readdirplus. When false, passes --no-readdirplus.";
|
|
};
|
|
writeback = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
description = "Enable writeback caching.";
|
|
};
|
|
allowDirectIo = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
description = "Allow direct I/O.";
|
|
};
|
|
logLevel = lib.mkOption {
|
|
type = lib.types.enum [
|
|
"error"
|
|
"warn"
|
|
"info"
|
|
"debug"
|
|
"trace"
|
|
"off"
|
|
];
|
|
default = "info";
|
|
description = "virtiofsd log level.";
|
|
};
|
|
killprivV2 = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = true;
|
|
description = ''
|
|
Enable FUSE_HANDLE_KILLPRIV_V2. Avoids duplicating work around
|
|
stripping SUID/SGID bits off binaries when written to by non-root.
|
|
'';
|
|
};
|
|
uidMap = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.str;
|
|
default = null;
|
|
description = ''
|
|
Map a range of UIDs from the host into the namespace,
|
|
given as ":namespace_uid:host_uid:count:". Done by user namespace.
|
|
'';
|
|
};
|
|
gidMap = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.str;
|
|
default = null;
|
|
description = ''
|
|
Map a range of GIDs from the host into the namespace,
|
|
given as ":namespace_gid:host_gid:count:". Done by user namespace.
|
|
'';
|
|
};
|
|
translateUid = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.str;
|
|
default = null;
|
|
description = ''
|
|
Translate UIDs between guest and host internally by virtiofsd,
|
|
given as "<type>:<source base>:<target base>:<count>".
|
|
Incompatible with posixAcl.
|
|
'';
|
|
};
|
|
translateGid = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.str;
|
|
default = null;
|
|
description = ''
|
|
Translate GIDs between guest and host internally by virtiofsd,
|
|
given as "<type>:<source base>:<target base>:<count>".
|
|
Incompatible with posixAcl.
|
|
'';
|
|
};
|
|
preserveNoatime = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
description = "Preserve O_NOATIME flag on files.";
|
|
};
|
|
};
|
|
}
|
|
);
|
|
default = { };
|
|
description = ''
|
|
Shared directories via virtiofsd. Keys are used as the virtiofs tag.
|
|
Each entry runs a dedicated virtiofsd process connected to crosvm via vhost-user.
|
|
'';
|
|
example = lib.literalExpression ''
|
|
{
|
|
home = {
|
|
path = "/tmp/host_shared_dir";
|
|
xattr = true;
|
|
posixAcl = true;
|
|
};
|
|
}
|
|
'';
|
|
};
|
|
|
|
vhostUser = lib.mkOption {
|
|
type = lib.types.listOf freeformAttrsetType;
|
|
default = [ ];
|
|
description = ''
|
|
vhost-user devices for --vhost-user. Each attrset is formatted as key=value pairs.
|
|
'';
|
|
example = lib.literalExpression ''
|
|
[{
|
|
type = "net";
|
|
socket = "/path/to/vhost-user.sock";
|
|
}]
|
|
'';
|
|
};
|
|
|
|
pciDevices = lib.mkOption {
|
|
type = lib.types.listOf freeformAttrsetType;
|
|
default = [ ];
|
|
description = ''
|
|
PCI devices to pass through via --vfio. Each attrset requires `path` (BDF or sysfs path).
|
|
BDF format ("01:00.0" or "0000:01:00.0") is auto-converted to sysfs path.
|
|
Other keys are passed as key=value pairs (e.g., iommu=on).
|
|
Devices must also be listed in isolatedPciDevices.
|
|
'';
|
|
example = lib.literalExpression ''
|
|
[{
|
|
path = "01:00.0";
|
|
iommu = "on";
|
|
}]
|
|
'';
|
|
};
|
|
|
|
guestPrograms = lib.mkOption {
|
|
type = lib.types.listOf lib.types.package;
|
|
default = [ ];
|
|
description = "VM-specific packages to include in the rootfs.";
|
|
example = lib.literalExpression "[ pkgs.firefox ]";
|
|
};
|
|
|
|
guestConfig = lib.mkOption {
|
|
type = lib.types.either lib.types.deferredModule (lib.types.listOf lib.types.deferredModule);
|
|
default = [ ];
|
|
description = ''
|
|
VM-specific NixOS configuration modules.
|
|
|
|
Accepts a single NixOS module or a list of modules. Each module can be
|
|
an attribute set, a module function ({config, pkgs, lib, ...}: { ... }),
|
|
or a path to a module file.
|
|
'';
|
|
example = lib.literalExpression ''
|
|
# Single attrset
|
|
{ services.openssh.enable = true; }
|
|
|
|
# Single module function
|
|
{ config, pkgs, ... }: {
|
|
services.openssh.enable = true;
|
|
}
|
|
|
|
# List of modules
|
|
[
|
|
./my-guest-module.nix
|
|
{ services.openssh.enable = true; }
|
|
({ config, pkgs, ... }: { environment.systemPackages = [ pkgs.vim ]; })
|
|
]
|
|
'';
|
|
};
|
|
|
|
crosvm = lib.mkOption {
|
|
type = lib.types.submodule {
|
|
options = {
|
|
logLevel = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.str;
|
|
default = null;
|
|
description = "Per-VM log level override. If null, uses global crosvm.logLevel.";
|
|
example = "debug";
|
|
};
|
|
|
|
extraArgs = lib.mkOption {
|
|
type = lib.types.listOf lib.types.str;
|
|
default = [ ];
|
|
description = "Per-VM extra arguments passed to crosvm before 'run'. Appended to global crosvm.extraArgs.";
|
|
example = [
|
|
"--syslog-tag"
|
|
"banking"
|
|
];
|
|
};
|
|
|
|
extraRunArgs = lib.mkOption {
|
|
type = lib.types.listOf lib.types.str;
|
|
default = [ ];
|
|
description = "Per-VM extra arguments passed to crosvm after 'run'. Appended to global crosvm.extraRunArgs.";
|
|
example = [ "--disable-sandbox" ];
|
|
};
|
|
};
|
|
};
|
|
default = { };
|
|
description = "Per-VM crosvm configuration.";
|
|
};
|
|
};
|
|
};
|
|
|
|
in
|
|
{
|
|
options.programs.vmsilo = {
|
|
enable = lib.mkEnableOption "vmsilo VM management";
|
|
|
|
enableBashIntegration = lib.mkEnableOption "Bash completion for vmsilo commands" // {
|
|
default = true;
|
|
};
|
|
|
|
crosvm = lib.mkOption {
|
|
type = lib.types.submodule {
|
|
options = {
|
|
logLevel = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "info";
|
|
description = "Log level for crosvm (error, warn, info, debug, trace).";
|
|
example = "debug";
|
|
};
|
|
|
|
extraArgs = lib.mkOption {
|
|
type = lib.types.listOf lib.types.str;
|
|
default = [ ];
|
|
description = "Extra arguments passed to crosvm before 'run' subcommand.";
|
|
example = [
|
|
"--syslog-tag"
|
|
"vmsilo"
|
|
];
|
|
};
|
|
|
|
extraRunArgs = lib.mkOption {
|
|
type = lib.types.listOf lib.types.str;
|
|
default = [ ];
|
|
description = "Extra arguments passed to crosvm after 'run' subcommand.";
|
|
example = [ "--disable-sandbox" ];
|
|
};
|
|
};
|
|
};
|
|
default = { };
|
|
description = "Global crosvm configuration.";
|
|
};
|
|
|
|
schedulerIsolation = lib.mkOption {
|
|
type = lib.types.enum [
|
|
"full"
|
|
"vm"
|
|
"off"
|
|
];
|
|
default = "full";
|
|
description = ''
|
|
Mitigate hyperthreading attacks using scheduler thread isolation.
|
|
- "full": vCPU threads may not share a core with any other thread (including other vCPUs of the same VM). Sets --core-scheduling=true.
|
|
- "vm": vCPU threads may share a core with other vCPU threads from the same VM, but not threads from other VMs or the host. Sets --per-vm-core-scheduling.
|
|
- "off": No mitigations. Sets --core-scheduling=false.
|
|
'';
|
|
};
|
|
|
|
user = lib.mkOption {
|
|
type = lib.types.str;
|
|
description = "User who owns TAP interfaces and runs VMs. Required.";
|
|
example = "david";
|
|
};
|
|
|
|
hostNetworking = lib.mkOption {
|
|
type = lib.types.submodule {
|
|
options = {
|
|
nat = {
|
|
enable = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
description = "Enable NAT for VM internet access.";
|
|
};
|
|
interface = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "";
|
|
description = "External interface for NAT (required if nat.enable is true).";
|
|
example = "eth0";
|
|
};
|
|
};
|
|
};
|
|
};
|
|
default = { };
|
|
description = "Host networking configuration for NAT.";
|
|
};
|
|
|
|
isolatedPciDevices = lib.mkOption {
|
|
type = lib.types.listOf lib.types.str;
|
|
default = [ ];
|
|
description = ''
|
|
PCI devices to isolate from the host using vfio-pci.
|
|
Accepts BDF format: "01:00.0" or "0000:01:00.0".
|
|
These devices will be claimed by vfio-pci at early boot.
|
|
|
|
Note: For maximum reliability, also blacklist native drivers
|
|
using boot.blacklistedKernelModules.
|
|
'';
|
|
example = [
|
|
"01:00.0"
|
|
"02:00.0"
|
|
];
|
|
};
|
|
|
|
nixosVms = lib.mkOption {
|
|
type = lib.types.listOf vmSubmodule;
|
|
default = [ ];
|
|
description = "List of NixOS-based VMs to create.";
|
|
example = lib.literalExpression ''
|
|
[{
|
|
name = "banking";
|
|
memory = 4096;
|
|
cpus = 4;
|
|
guestPrograms = [ pkgs.firefox ];
|
|
}]
|
|
'';
|
|
};
|
|
|
|
vmsilo-tray = lib.mkOption {
|
|
type = lib.types.submodule {
|
|
options = {
|
|
logLevel = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "info";
|
|
description = "Log level for vmsilo-tray host and guest daemons (error, warn, info, debug, trace).";
|
|
example = "debug";
|
|
};
|
|
};
|
|
};
|
|
default = { };
|
|
description = "Tray proxy configuration.";
|
|
};
|
|
|
|
vmsilo-balloond = lib.mkOption {
|
|
type = lib.types.submodule {
|
|
options = {
|
|
logLevel = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "info";
|
|
description = "Log level for vmsilo-balloond (error, warn, info, debug, trace).";
|
|
example = "debug";
|
|
};
|
|
|
|
pollInterval = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "2s";
|
|
description = "Policy evaluation interval (e.g. \"2s\", \"1s\", \"500ms\").";
|
|
example = "1s";
|
|
};
|
|
|
|
criticalHostPercent = lib.mkOption {
|
|
type = lib.types.int;
|
|
default = 5;
|
|
description = "Host critical threshold as percentage of total RAM.";
|
|
example = 10;
|
|
};
|
|
|
|
criticalGuestAvailable = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "256m";
|
|
description = "Guest critical threshold — hard floor for guest free memory. Balloon inflation will never push guest free memory below this value (e.g. \"256m\", \"400m\").";
|
|
example = "400m";
|
|
};
|
|
|
|
guestAvailableBias = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "400m";
|
|
description = "Guest bias term — soft cushion above the critical floor that scales with balloon fullness, discouraging inflation as the guest approaches the floor (e.g. \"300m\", \"500m\").";
|
|
example = "500m";
|
|
};
|
|
|
|
minPollInterval = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "250ms";
|
|
description = "Minimum poll interval under memory pressure (e.g. \"250ms\", \"500ms\").";
|
|
example = "500ms";
|
|
};
|
|
|
|
psiCeiling = lib.mkOption {
|
|
type = lib.types.int;
|
|
default = 25;
|
|
description = "PSI avg10 percentage that maps to the minimum poll interval (0-100).";
|
|
example = 50;
|
|
};
|
|
|
|
extraArgs = lib.mkOption {
|
|
type = lib.types.listOf lib.types.str;
|
|
default = [ ];
|
|
description = "Extra command line arguments to pass to vmsilo-balloond.";
|
|
example = [ "--some-flag" ];
|
|
};
|
|
};
|
|
};
|
|
default = { };
|
|
description = "VM balloon memory management daemon configuration.";
|
|
};
|
|
|
|
# Internal options for dependency injection from flake.nix and inter-module communication
|
|
_internal = {
|
|
crosvm = lib.mkOption {
|
|
type = lib.types.package;
|
|
description = "crosvm package (injected by flake).";
|
|
internal = true;
|
|
};
|
|
|
|
wayland-proxy-virtwl = lib.mkOption {
|
|
type = lib.types.package;
|
|
description = "wayland-proxy-virtwl package (injected by flake).";
|
|
internal = true;
|
|
};
|
|
|
|
sommelier = lib.mkOption {
|
|
type = lib.types.package;
|
|
description = "sommelier package (injected by flake).";
|
|
internal = true;
|
|
};
|
|
|
|
vmsilo-balloond = lib.mkOption {
|
|
type = lib.types.package;
|
|
description = "vmsilo-balloond package (injected by flake).";
|
|
internal = true;
|
|
};
|
|
|
|
vmsilo-tray = lib.mkOption {
|
|
type = lib.types.package;
|
|
description = "vmsilo-tray package (injected by flake).";
|
|
internal = true;
|
|
};
|
|
|
|
# Generated scripts (set by scripts.nix, consumed by services.nix and package.nix)
|
|
vmScripts = lib.mkOption {
|
|
type = lib.types.attrsOf lib.types.path;
|
|
description = "VM launcher scripts (name -> script path).";
|
|
internal = true;
|
|
default = { };
|
|
};
|
|
|
|
proxyScripts = lib.mkOption {
|
|
type = lib.types.attrsOf lib.types.path;
|
|
description = "Proxy scripts (name -> script path).";
|
|
internal = true;
|
|
default = { };
|
|
};
|
|
|
|
userScripts = lib.mkOption {
|
|
type = lib.types.attrsOf lib.types.path;
|
|
description = "User-facing scripts (vm-run, vm-start, etc).";
|
|
internal = true;
|
|
default = { };
|
|
};
|
|
|
|
desktopFilesPackage = lib.mkOption {
|
|
type = lib.types.package;
|
|
description = "Package containing .desktop files for VM apps.";
|
|
internal = true;
|
|
};
|
|
|
|
bashCompletionScript = lib.mkOption {
|
|
type = lib.types.path;
|
|
description = "Bash completion script for vm-* commands.";
|
|
internal = true;
|
|
};
|
|
};
|
|
|
|
# Output: generated package with all scripts
|
|
package = lib.mkOption {
|
|
type = lib.types.package;
|
|
readOnly = true;
|
|
description = "Generated package containing VM launcher scripts.";
|
|
};
|
|
};
|
|
}
|