Shares a host directory as /home/user in guest VMs via virtiofs, enabled by default. Accepts true (/shared/<vmname>), a custom path string, or false to disable. Host directory is created with correct uid:gid ownership at VM start. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
732 lines
23 KiB
Nix
732 lines
23 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 [
|
|
"vm-switch"
|
|
"tap"
|
|
];
|
|
default = "vm-switch";
|
|
description = "Interface type: 'vm-switch' for VM-to-VM networking, '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";
|
|
};
|
|
|
|
vmNetwork = lib.mkOption {
|
|
type = lib.types.nullOr (
|
|
lib.types.submodule {
|
|
options = {
|
|
name = lib.mkOption {
|
|
type = lib.types.str;
|
|
description = "Network name for vm-switch.";
|
|
example = "internal";
|
|
};
|
|
receiveBroadcast = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
description = "Whether this VM receives broadcast traffic on this network.";
|
|
};
|
|
routes = lib.mkOption {
|
|
type = lib.types.listOf lib.types.str;
|
|
default = [ ];
|
|
description = "CIDR prefixes this VM advertises to the network (e.g. \"192.168.1.0/24\"). Used for subnet routing via longest-prefix-match.";
|
|
example = [
|
|
"192.168.1.0/24"
|
|
"10.0.0.0/8"
|
|
];
|
|
};
|
|
};
|
|
}
|
|
);
|
|
default = null;
|
|
description = "VM-switch network configuration. Required when type = 'vm-switch'.";
|
|
};
|
|
|
|
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 = {
|
|
id = lib.mkOption {
|
|
type = lib.types.int;
|
|
description = "VM ID (odd number 3-255). Used for IP address and vsock CID.";
|
|
example = 3;
|
|
};
|
|
|
|
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.";
|
|
};
|
|
|
|
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 = lib.mkOption {
|
|
type = lib.types.either lib.types.bool crosvmAttrsetType;
|
|
default = false;
|
|
description = ''
|
|
Sound configuration. Set to false to disable, true for default PulseAudio config,
|
|
or an attrset for custom --virtio-snd options.
|
|
'';
|
|
example = lib.literalExpression ''
|
|
{
|
|
backend = "pulse";
|
|
capture = true;
|
|
}
|
|
'';
|
|
};
|
|
|
|
sharedDirectories = lib.mkOption {
|
|
type = lib.types.listOf freeformAttrsetType;
|
|
default = [ ];
|
|
description = ''
|
|
Shared directories for --shared-dir. Each attrset requires `path` and `tag`.
|
|
Other keys are passed as key=value pairs with colon separator.
|
|
'';
|
|
example = lib.literalExpression ''
|
|
[{
|
|
path = "/tmp/shared";
|
|
tag = "shared";
|
|
type = "fs";
|
|
uid = 1000;
|
|
}]
|
|
'';
|
|
};
|
|
|
|
vhostUser = lib.mkOption {
|
|
type = lib.types.listOf freeformAttrsetType;
|
|
default = [ ];
|
|
description = ''
|
|
vhost-user devices for --vhost-user. Each attrset is formatted as key=value pairs.
|
|
Typically auto-populated from vmNetwork with type=net.
|
|
'';
|
|
example = lib.literalExpression ''
|
|
[{
|
|
type = "net";
|
|
socket = "/run/vm-switch/internet/banking/client.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.attrs (lib.types.functionTo lib.types.attrs);
|
|
default = { };
|
|
description = ''
|
|
VM-specific NixOS configuration.
|
|
|
|
Can be an attrset or a function. If a function, it receives vmConfig
|
|
(the VM configuration with enriched interfaces including computed name fields).
|
|
'';
|
|
example = lib.literalExpression ''
|
|
# As attrs
|
|
{ fileSystems."/home/user" = { device = "/dev/vdb"; fsType = "ext4"; }; }
|
|
|
|
# As function (access interface names via attrset keys)
|
|
vmConfig: {
|
|
networking.firewall.interfaces.wan.allowedTCPPorts = [ 22 ];
|
|
}
|
|
'';
|
|
};
|
|
|
|
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.";
|
|
};
|
|
|
|
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 ''
|
|
[{
|
|
id = 3;
|
|
name = "banking";
|
|
memory = 4096;
|
|
cpus = 4;
|
|
guestPrograms = [ pkgs.firefox ];
|
|
}]
|
|
'';
|
|
};
|
|
|
|
vm-switch = lib.mkOption {
|
|
type = lib.types.submodule {
|
|
options = {
|
|
logLevel = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "info";
|
|
description = "Log level for vm-switch (error, warn, info, debug, trace).";
|
|
example = "debug";
|
|
};
|
|
|
|
bufferSize = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "256k";
|
|
description = "Ring buffer data region size per peer (e.g. \"256k\", \"131072\").";
|
|
example = "512k";
|
|
};
|
|
|
|
fqCodelTarget = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "5ms";
|
|
description = "FQ-CoDel target sojourn time (e.g. \"5ms\", \"10ms\").";
|
|
example = "10ms";
|
|
};
|
|
|
|
fqCodelInterval = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "100ms";
|
|
description = "FQ-CoDel measurement interval (e.g. \"100ms\", \"1s\").";
|
|
example = "100ms";
|
|
};
|
|
|
|
fqCodelLimit = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "2m";
|
|
description = "FQ-CoDel hard byte limit per peer (e.g. \"2m\", \"1048576\").";
|
|
example = "4m";
|
|
};
|
|
|
|
fqCodelQuantum = lib.mkOption {
|
|
type = lib.types.int;
|
|
default = 1514;
|
|
description = "FQ-CoDel DRR quantum in bytes (bytes per round per flow).";
|
|
example = 3028;
|
|
};
|
|
|
|
extraArgs = lib.mkOption {
|
|
type = lib.types.listOf lib.types.str;
|
|
default = [ ];
|
|
description = "Extra command line arguments to pass to vm-switch.";
|
|
example = [ "--some-flag" ];
|
|
};
|
|
};
|
|
};
|
|
default = { };
|
|
description = "VM-switch 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;
|
|
};
|
|
|
|
vm-switch = lib.mkOption {
|
|
type = lib.types.package;
|
|
description = "vm-switch 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.";
|
|
};
|
|
};
|
|
}
|