VM Helper Functions
VM Helper Functions
Section titled “VM Helper Functions”The lib.ghaf.vm namespace provides utilities for VM composition, configuration propagation, and evaluation within the Ghaf framework.
Overview
Section titled “Overview”lib.ghaf.vm = { mkSpecialArgs # Create specialArgs for VM evaluation mkHostConfig # Create host-derived configuration for a VM getConfig # Get inner NixOS config from a microvm entry applyVmConfig # Build modules list from vmConfig for extendModules};Function Reference
Section titled “Function Reference”mkSpecialArgs
Section titled “mkSpecialArgs”Creates the specialArgs attribute set passed to VM module evaluation. This makes globalConfig, hostConfig, inputs, and lib available to all VM modules.
Signature:
mkSpecialArgs :: { lib, inputs, globalConfig, hostConfig?, extraArgs? } -> AttrSetParameters:
| Name | Type | Required | Description |
|---|---|---|---|
lib | AttrSet | Yes | Extended lib with ghaf functions |
inputs | AttrSet | Yes | Flake inputs |
globalConfig | AttrSet | Yes | Global config value (from config.ghaf.global-config) |
hostConfig | AttrSet | No | Host-specific config (from lib.ghaf.vm.mkHostConfig) |
extraArgs | AttrSet | No | Additional specialArgs to include |
Returns: AttrSet suitable for specialArgs in lib.nixosSystem or extendModules.
Example:
let specialArgs = lib.ghaf.vm.mkSpecialArgs { inherit lib inputs; globalConfig = config.ghaf.global-config; hostConfig = lib.ghaf.vm.mkHostConfig { inherit config; vmName = "gui-vm"; }; };inlib.nixosSystem { inherit specialArgs; modules = [ ./guivm-base.nix ];}mkHostConfig
Section titled “mkHostConfig”Creates the host-derived configuration for a specific VM. This extracts VM-specific information (networking, kernel, hardware passthrough, user config) from the host configuration.
Signature:
mkHostConfig :: { config, vmName, extraConfig? } -> AttrSetParameters:
| Name | Type | Required | Description |
|---|---|---|---|
config | AttrSet | Yes | Full host NixOS configuration |
vmName | String | Yes | Name of the VM (e.g., “gui-vm”, “net-vm”) |
extraConfig | AttrSet | No | Additional config to merge |
Returns: AttrSet with VM-specific host-derived values.
Example:
hostConfig = lib.ghaf.vm.mkHostConfig { inherit config; vmName = "gui-vm";};Returned Structure:
{ vmName = "gui-vm"; vmType = "gui"; # vmName without "-vm" suffix
kernel = { ... }; # ghaf.kernel.<vmType> settings qemu = { ... }; # ghaf.qemu.<vmType> settings
passthrough = { qemuExtraArgs = [ ... ]; # Hardware passthrough args vmUdevExtraRules = "..."; # Udev rules for passthrough };
sharedVmDirectory = "/..."; # Shared directory path
microvmBoot = { enable = bool; # microvm-boot enabled };
hardware = { devices = { ... }; # Hardware device definitions };
users = { ... }; # User configuration common = { ... }; # Common namespace settings
networking = { hosts = { ... }; # All VM host entries thisVm = { ... }; # This VM's network config };
givc = { cliArgs = "..."; # GIVC CLI arguments enableTls = bool; # TLS enabled };
security = { sshKeys = { ... }; # SSH key configuration };
appvms = { ... }; # AppVM configurations (for launcher) guivm = { applications = [ ... ]; # GUI VM applications };
reference = { services = { ... }; # Reference services config };}getConfig
Section titled “getConfig”Retrieves the inner NixOS config from a microvm.vms entry. Handles both evaluatedConfig and legacy config patterns.
Signature:
getConfig :: vmEntry -> AttrSet | nullParameters:
| Name | Type | Description |
|---|---|---|
vmEntry | AttrSet | Entry from config.microvm.vms.<name> |
Returns: The VM’s inner NixOS config, or null if not available.
Example:
# Get GUI VM's inner configlet guivmEntry = config.microvm.vms.gui-vm; guivmConfig = lib.ghaf.vm.getConfig guivmEntry;inguivmConfig.services.foo.enableNotes:
- Prefers
evaluatedConfigover legacyconfigpattern - Returns
vmEntry.evaluatedConfig.configifevaluatedConfigis set - Falls back to
vmEntry.config.configfor legacy VMs - Returns
nullif neither is available
applyVmConfig
Section titled “applyVmConfig”Builds a list of modules from ghaf.hardware.definition and ghaf.virtualization.vmConfig for use with extendModules. This applies resource allocation (mem/vcpu) and extra modules.
Signature:
applyVmConfig :: { config, vmName } -> [ Module ]Parameters:
| Name | Type | Description |
|---|---|---|
config | AttrSet | Host NixOS configuration |
vmName | String | VM name without -vm suffix (e.g., “guivm”, “netvm”) |
Returns: List of modules to pass to extendModules.
Module Merge Order (highest priority last):
- Base module (e.g., guivm-base.nix) - sets mkDefault values
- resourceModule - applies
vmConfig.mem/vcpu - hwModules -
hardware.definition.<vm>.extraModules - vmConfigModules -
vmConfig.<vm>.extraModules(highest priority)
Example:
# In a profile moduleguivmBase.extendModules { modules = lib.ghaf.vm.applyVmConfig { inherit config; vmName = "guivm"; };};What it returns:
# If vmConfig.guivm = { mem = 4096; vcpu = 4; extraModules = [ myModule ]; }# And hardware.definition.guivm = { extraModules = [ hwModule ]; }# Returns:[ { microvm.mem = 4096; microvm.vcpu = 4; } # resourceModule hwModule # from hardware.definition myModule # from vmConfig]Usage Patterns
Section titled “Usage Patterns”Pattern 1: Creating a VM Base in a Profile
Section titled “Pattern 1: Creating a VM Base in a Profile”Profiles create VM bases and export them for downstream extension. The profile also applies vmConfig (resource allocation, hardware modules) and sets evaluatedConfig on the VM module. Targets and references may override evaluatedConfig via extendModules.
{ config, lib, pkgs, inputs, ... }:let hostGlobalConfig = config.ghaf.global-config;
guivmBase = lib.nixosSystem { specialArgs = lib.ghaf.vm.mkSpecialArgs { inherit lib inputs; globalConfig = hostGlobalConfig; hostConfig = lib.ghaf.vm.mkHostConfig { inherit config; vmName = "gui-vm"; }; }; modules = [ inputs.self.nixosModules.guivm-base # Base configuration here ]; };in{ # Export for downstream extension options.ghaf.profiles.laptop-x86.guivmBase = lib.mkOption { type = lib.types.unspecified; default = guivmBase; description = "GUI VM base configuration"; };
# Set evaluatedConfig with vmConfig applied # Pass the full system result (not .config) to evaluatedConfig config.ghaf.virtualization.microvm.guivm.evaluatedConfig = guivmBase.extendModules { modules = lib.ghaf.vm.applyVmConfig { inherit config; vmName = "guivm"; }; };}Pattern 2: Downstream Extension with extendModules
Section titled “Pattern 2: Downstream Extension with extendModules”# In downstream project (e.g., ghaf-fmo-laptop){ config, lib, inputs, ... }:let hostGlobalConfig = config.ghaf.global-config;in{ # Extend the upstream guivmBase ghaf.virtualization.microvm.guivm.evaluatedConfig = config.ghaf.profiles.laptop-x86.guivmBase.extendModules { modules = [ # Add FMO-specific modules ../services ../programs { ghaf.reference.personalize.keys.enable = true; } ] # Apply vmConfig (mem, vcpu, extraModules) ++ lib.ghaf.vm.applyVmConfig { inherit config; vmName = "guivm"; };
# Update specialArgs for extended modules specialArgs = lib.ghaf.vm.mkSpecialArgs { inherit lib inputs; globalConfig = hostGlobalConfig; hostConfig = lib.ghaf.vm.mkHostConfig { inherit config; vmName = "gui-vm"; }; }; };}Pattern 3: AppVM with Extensions
Section titled “Pattern 3: AppVM with Extensions”# Using the extensions option for feature modules{ config, lib, pkgs, ... }:{ ghaf.virtualization.microvm.appvm.vms.chrome.extensions = [ ({ pkgs, ... }: { ghaf.appvm.applications = [{ name = "Getting Started"; description = "Introduction guide"; packages = [ pkgs.ghaf-intro ]; command = "ghaf-intro"; }]; }) ];}See Also
Section titled “See Also”- Configuration Propagation - How globalConfig/hostConfig work
- VM Composition - extendModules pattern
- Features API - Feature management utilities