vmsilo/modules/options.nix
Davíð Steinn Geirsson eb4e2ffcaa Add VM configuration options and migrate to --block
- Rename `disks` to `additionalDisks` with structured format
  (path, readOnly, enableDiscard, blockSize, devIdentifier, useDirect)
- Add custom boot options: rootDisk, kernel, initramfs, rootDiskReadonly
- Add kernelParams for extra kernel command line options
- Add gpu option (default: "context-types=cross-domain:virgl2")
- Add sharedDirectories for crosvm --shared-dir
- Add global crosvmLogLevel option (default: "info")
- Add --name argument to crosvm set to VM name
- Migrate deprecated --disk/--rwdisk to --block format
- Switch flake to nixos-unstable channel

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 19:09:51 +00:00

289 lines
8 KiB
Nix

# Option definitions for qubes-lite NixOS module
{
config,
pkgs,
lib,
...
}:
let
cfg = config.programs.qubes-lite;
# Disk configuration submodule for --block arguments
diskSubmodule = lib.types.submodule {
options = {
path = lib.mkOption {
type = lib.types.str;
description = "Path to the disk image or block device.";
example = "/tmp/data.qcow2";
};
readOnly = lib.mkOption {
type = lib.types.bool;
default = false;
description = "Whether the disk should be read-only.";
};
enableDiscard = lib.mkOption {
type = lib.types.bool;
default = true;
description = "Whether the disk should support the discard operation.";
};
blockSize = lib.mkOption {
type = lib.types.int;
default = 512;
description = "Reported block size of the disk in bytes.";
example = 4096;
};
devIdentifier = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
description = "Block device identifier (ASCII string, up to 20 characters).";
example = "datadisk";
};
useDirect = lib.mkOption {
type = lib.types.bool;
default = false;
description = "Use O_DIRECT mode to bypass page cache.";
};
};
};
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";
};
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 = lib.types.bool;
default = true;
description = "Enable networking for this VM.";
};
disposable = lib.mkOption {
type = lib.types.bool;
default = false;
description = "Enable auto-shutdown when idle. VM shuts down after idleTimeout seconds with no active commands.";
};
idleTimeout = lib.mkOption {
type = lib.types.int;
default = 60;
description = "Seconds to wait after last command exits before shutting down (only used when disposable=true).";
};
additionalDisks = lib.mkOption {
type = lib.types.listOf diskSubmodule;
default = [ ];
description = "Additional disks to attach to the VM.";
example = lib.literalExpression ''
[{
path = "/tmp/data.qcow2";
readOnly = true;
blockSize = 4096;
devIdentifier = "datadisk";
}]
'';
};
rootDisk = lib.mkOption {
type = lib.types.nullOr diskSubmodule;
default = null;
description = "Custom root disk. If not set, uses the built rootfs image.";
example = lib.literalExpression ''
{
path = "/path/to/custom-root.qcow2";
readOnly = 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 root disk should be read-only.";
};
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.str;
default = "context-types=cross-domain:virgl2";
description = "GPU configuration passed to crosvm's --gpu option.";
example = "context-types=cross-domain";
};
sharedDirectories = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
description = "Shared directories passed to crosvm's --shared-dir option.";
example = [ "/tmp/shared:shared:uid=1000" ];
};
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.attrs;
default = { };
description = "VM-specific NixOS configuration.";
example = lib.literalExpression ''
{
fileSystems."/home/user" = { device = "/dev/vdb"; fsType = "ext4"; };
}
'';
};
};
};
in
{
options.programs.qubes-lite = {
enable = lib.mkEnableOption "qubes-lite VM management";
enableBashIntegration = lib.mkEnableOption "Bash completion for qubes-lite commands" // {
default = true;
};
crosvmLogLevel = lib.mkOption {
type = lib.types.str;
default = "info";
description = "Log level for crosvm (error, warn, info, debug, trace).";
example = "debug";
};
user = lib.mkOption {
type = lib.types.str;
description = "User who owns TAP interfaces and runs VMs. Required.";
example = "david";
};
vmNetwork = lib.mkOption {
type = lib.types.str;
default = "172.16.200.0/24";
description = "Network CIDR for VM networking. Uses /31 point-to-point links.";
example = "10.0.0.0/24";
};
natEnable = lib.mkOption {
type = lib.types.bool;
default = false;
description = "Enable NAT for VM internet access.";
};
natInterface = lib.mkOption {
type = lib.types.str;
default = "";
description = "External interface for NAT (required if natEnable is true).";
example = "eth0";
};
guestPrograms = lib.mkOption {
type = lib.types.listOf lib.types.package;
default = [ ];
description = "Packages to include in all VM rootfs images.";
example = lib.literalExpression "[ pkgs.firefox pkgs.konsole ]";
};
guestConfig = lib.mkOption {
type = lib.types.attrs;
default = { };
description = "NixOS configuration applied to all VM rootfs images.";
example = lib.literalExpression ''
{
services.openssh.enable = true;
users.users.user.extraGroups = [ "wheel" ];
}
'';
};
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 ];
}]
'';
};
# Internal options for dependency injection from flake.nix
_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;
};
};
# Output: generated package with all scripts
package = lib.mkOption {
type = lib.types.package;
readOnly = true;
description = "Generated package containing VM launcher scripts.";
};
};
}