Auto-assign sequential VM IDs instead of requiring manual specification
VM IDs (used for vsock CIDs and TAP name truncation) are now automatically assigned starting from 3 based on list position, removing the need for users to specify them. Also removes the constraints that IDs must be odd numbers in range 3-255. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
b0b0809577
commit
c80a8c807a
8 changed files with 20 additions and 56 deletions
|
|
@ -331,7 +331,6 @@ Two filter tiers (child is a strict subset of main):
|
|||
};
|
||||
|
||||
nixosVms = [{
|
||||
id = 3;
|
||||
name = "banking";
|
||||
color = "#2ecc71"; # Window decoration color (default: "red")
|
||||
waylandProxy = "wayland-proxy-virtwl"; # or "sommelier" (default: "wayland-proxy-virtwl")
|
||||
|
|
|
|||
30
README.md
30
README.md
|
|
@ -54,7 +54,6 @@ Import the module and configure VMs in your NixOS configuration:
|
|||
|
||||
nixosVms = [
|
||||
{
|
||||
id = 3;
|
||||
name = "banking";
|
||||
memory = 4096;
|
||||
cpus = 4;
|
||||
|
|
@ -71,7 +70,6 @@ Import the module and configure VMs in your NixOS configuration:
|
|||
guestPrograms = with pkgs; [ firefox konsole ];
|
||||
}
|
||||
{
|
||||
id = 5;
|
||||
name = "shopping";
|
||||
memory = 2048;
|
||||
cpus = 2;
|
||||
|
|
@ -88,7 +86,6 @@ Import the module and configure VMs in your NixOS configuration:
|
|||
guestPrograms = with pkgs; [ firefox konsole ];
|
||||
}
|
||||
{
|
||||
id = 7;
|
||||
name = "personal";
|
||||
memory = 4096;
|
||||
cpus = 4;
|
||||
|
|
@ -123,7 +120,6 @@ Import the module and configure VMs in your NixOS configuration:
|
|||
|
||||
| Option | Type | Default | Description |
|
||||
|--------|------|---------|-------------|
|
||||
| `id` | int | required | VM ID (odd number 3-255). Used for vsock CID |
|
||||
| `name` | string | required | VM name for scripts |
|
||||
| `memory` | int | `1024` | Memory allocation in MB |
|
||||
| `cpus` | int | `2` | Number of virtual CPUs |
|
||||
|
|
@ -263,9 +259,9 @@ Each VM's `color` option controls its KDE window decoration color, providing a v
|
|||
|
||||
```nix
|
||||
nixosVms = [
|
||||
{ id = 3; name = "banking"; color = "#2ecc71"; ... } # Green
|
||||
{ id = 5; name = "shopping"; color = "#3498db"; ... } # Blue
|
||||
{ id = 7; name = "untrusted"; color = "red"; ... } # Red (default)
|
||||
{ name = "banking"; color = "#2ecc71"; ... } # Green
|
||||
{ name = "shopping"; color = "#3498db"; ... } # Blue
|
||||
{ name = "untrusted"; color = "red"; ... } # Red (default)
|
||||
];
|
||||
```
|
||||
|
||||
|
|
@ -356,15 +352,6 @@ Interface names are user-specified via `network.interfaces` attrset keys. Names
|
|||
|
||||
PCI slots are assigned alphabetically by interface name (sorted position + 22). For example, with interfaces `{ internal = ...; wan = ...; }`, `internal` gets PCI slot 22 (`00:16.0`) and `wan` gets slot 23 (`00:17.0`).
|
||||
|
||||
### ID Requirements
|
||||
|
||||
VM IDs must be:
|
||||
- Odd numbers (3, 5, 7, 9, ...)
|
||||
- In range 3-255
|
||||
- Unique across all VMs
|
||||
|
||||
IDs are used for vsock CIDs (not for IP addressing).
|
||||
|
||||
### NAT
|
||||
|
||||
When `hostNetworking.nat.enable = true`, the module configures:
|
||||
|
|
@ -381,7 +368,6 @@ To use `vm-shell --ssh`, configure SSH keys in per-VM `guestConfig`:
|
|||
```nix
|
||||
programs.vmsilo = {
|
||||
nixosVms = [{
|
||||
id = 3;
|
||||
name = "dev";
|
||||
guestConfig = {
|
||||
users.users.user.openssh.authorizedKeys.keys = [ "ssh-ed25519 AAAA..." ];
|
||||
|
|
@ -399,7 +385,6 @@ Since interface names are the attrset keys, you can reference them directly:
|
|||
|
||||
```nix
|
||||
{
|
||||
id = 3;
|
||||
name = "banking";
|
||||
network.interfaces.wan = {
|
||||
type = "tap";
|
||||
|
|
@ -442,7 +427,6 @@ in {
|
|||
programs.vmsilo = {
|
||||
nixosVms = [
|
||||
{
|
||||
id = 3;
|
||||
name = "dev";
|
||||
network = mkTapNetwork "10.0.0.254/24" "10.0.0.1/24";
|
||||
guestPrograms = commonGuestPrograms;
|
||||
|
|
@ -452,7 +436,6 @@ in {
|
|||
additionalDisks = [{ path = "/dev/mapper/main-dev-home"; ro = false; }];
|
||||
}
|
||||
{
|
||||
id = 5;
|
||||
name = "banking";
|
||||
network = mkTapNetwork "10.0.1.254/24" "10.0.1.1/24";
|
||||
guestPrograms = commonGuestPrograms;
|
||||
|
|
@ -469,7 +452,6 @@ VMs are offline by default (no `network.interfaces`). For sensitive data that sh
|
|||
|
||||
```nix
|
||||
{
|
||||
id = 13;
|
||||
name = "vault";
|
||||
memory = 2048;
|
||||
# No network.interfaces = completely offline
|
||||
|
|
@ -484,7 +466,6 @@ VMs can communicate with each other via `network.interfaces` with `type = "vm-sw
|
|||
```nix
|
||||
nixosVms = [
|
||||
{
|
||||
id = 3;
|
||||
name = "router";
|
||||
network.interfaces = {
|
||||
# TAP for internet access
|
||||
|
|
@ -503,7 +484,6 @@ nixosVms = [
|
|||
};
|
||||
}
|
||||
{
|
||||
id = 5;
|
||||
name = "banking";
|
||||
network.interfaces.internal = {
|
||||
type = "vm-switch";
|
||||
|
|
@ -513,7 +493,6 @@ nixosVms = [
|
|||
};
|
||||
}
|
||||
{
|
||||
id = 7;
|
||||
name = "shopping";
|
||||
network.interfaces.internal = {
|
||||
type = "vm-switch";
|
||||
|
|
@ -539,7 +518,6 @@ VMs that auto-shutdown when idle to save memory:
|
|||
|
||||
```nix
|
||||
{
|
||||
id = 9;
|
||||
name = "untrusted";
|
||||
memory = 4096;
|
||||
autoShutdown = { enable = true; after = 60; }; # Shutdown 60 seconds after last command exits
|
||||
|
|
@ -579,13 +557,11 @@ programs.vmsilo = {
|
|||
isolatedPciDevices = [ "01:00.0" "02:00.0" ];
|
||||
|
||||
nixosVms = [{
|
||||
id = 3;
|
||||
name = "sys-usb";
|
||||
memory = 1024;
|
||||
pciDevices = [{ path = "01:00.0"; }]; # USB controller
|
||||
}
|
||||
{
|
||||
id = 5;
|
||||
name = "sys-net";
|
||||
memory = 1024;
|
||||
pciDevices = [{ path = "02:00.0"; }]; # Network card
|
||||
|
|
|
|||
|
|
@ -64,7 +64,6 @@
|
|||
|
||||
nixosVms = [
|
||||
{
|
||||
id = 3;
|
||||
name = "testvm";
|
||||
memory = 4096;
|
||||
cpus = 4;
|
||||
|
|
@ -93,7 +92,6 @@
|
|||
guestPrograms = commonGuestPrograms;
|
||||
}
|
||||
{
|
||||
id = 5;
|
||||
name = "netvm";
|
||||
autoStart = true;
|
||||
memory = 512;
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ in
|
|||
config = lib.mkIf cfg.enable {
|
||||
assertions =
|
||||
let
|
||||
vmIds = map (vm: vm.id) cfg.nixosVms;
|
||||
vmNames = map (vm: vm.name) cfg.nixosVms;
|
||||
in
|
||||
[
|
||||
|
|
@ -35,19 +34,11 @@ in
|
|||
assertion = cfg.hostNetworking.nat.enable -> cfg.hostNetworking.nat.interface != "";
|
||||
message = "programs.vmsilo.hostNetworking.nat.interface must be set when hostNetworking.nat.enable is true";
|
||||
}
|
||||
{
|
||||
assertion = lib.length vmIds == lib.length (lib.unique vmIds);
|
||||
message = "VM IDs must be unique";
|
||||
}
|
||||
{
|
||||
assertion = lib.length vmNames == lib.length (lib.unique vmNames);
|
||||
message = "VM names must be unique";
|
||||
}
|
||||
]
|
||||
++ map (vm: {
|
||||
assertion = vm.id >= 3 && vm.id <= 255 && lib.mod vm.id 2 == 1;
|
||||
message = "VM '${vm.name}' has invalid id ${toString vm.id}. Must be odd number 3-255.";
|
||||
}) cfg.nixosVms
|
||||
# PCI passthrough assertions
|
||||
++ lib.concatMap (
|
||||
vm:
|
||||
|
|
|
|||
|
|
@ -173,6 +173,9 @@
|
|||
in
|
||||
if lib.stringLength fullName <= maxLen then fullName else "${truncatedName}-${ifIndexStr}";
|
||||
|
||||
# Auto-assign sequential VM IDs starting from 3 based on list position
|
||||
assignVmIds = vms: lib.imap0 (idx: vm: vm // { id = idx + 3; }) vms;
|
||||
|
||||
# Sanitize VM name for use in device IDs (alphanumeric + underscore only)
|
||||
sanitizeName =
|
||||
name:
|
||||
|
|
|
|||
|
|
@ -16,8 +16,11 @@ let
|
|||
generateMac
|
||||
sortedInterfaceList
|
||||
makeTapName
|
||||
assignVmIds
|
||||
;
|
||||
|
||||
vms = assignVmIds cfg.nixosVms;
|
||||
|
||||
# Get effective MAC for an interface (uses user-specified interface name)
|
||||
getEffectiveIfaceMac =
|
||||
vm: ifName: iface:
|
||||
|
|
@ -30,7 +33,7 @@ let
|
|||
lib.concatMap (iface: lib.optional (isVmSwitchIface iface) iface.vmNetwork.name) (
|
||||
lib.attrValues vm.network.interfaces
|
||||
)
|
||||
) cfg.nixosVms
|
||||
) vms
|
||||
);
|
||||
|
||||
# Get VMs that are part of a specific vm-switch network
|
||||
|
|
@ -41,7 +44,7 @@ let
|
|||
lib.any (iface: isVmSwitchIface iface && iface.vmNetwork.name == netName) (
|
||||
lib.attrValues vm.network.interfaces
|
||||
)
|
||||
) cfg.nixosVms;
|
||||
) vms;
|
||||
|
||||
# Find the interface name for a VM on a specific network
|
||||
getVmNetworkIfaceName =
|
||||
|
|
@ -79,7 +82,7 @@ let
|
|||
makeTapName vm.name vm.id (idxToIfIndex idx);
|
||||
}
|
||||
) (sortedInterfaceList vm.network.interfaces)
|
||||
) cfg.nixosVms
|
||||
) vms
|
||||
);
|
||||
in
|
||||
{
|
||||
|
|
|
|||
|
|
@ -168,12 +168,6 @@ let
|
|||
|
||||
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.";
|
||||
|
|
@ -595,7 +589,6 @@ in
|
|||
description = "List of NixOS-based VMs to create.";
|
||||
example = lib.literalExpression ''
|
||||
[{
|
||||
id = 3;
|
||||
name = "banking";
|
||||
memory = 4096;
|
||||
cpus = 4;
|
||||
|
|
|
|||
|
|
@ -25,8 +25,11 @@ let
|
|||
sortedInterfaceList
|
||||
sanitizeName
|
||||
makeTapName
|
||||
assignVmIds
|
||||
;
|
||||
|
||||
vms = assignVmIds cfg.nixosVms;
|
||||
|
||||
# User UID/GID and runtime directory for explicit paths (system services need these)
|
||||
userUid = config.users.users.${cfg.user}.uid;
|
||||
userGid = config.users.groups.${config.users.users.${cfg.user}.group}.gid;
|
||||
|
|
@ -399,10 +402,10 @@ let
|
|||
# Generate shell case statement for VM dispatch
|
||||
mkVmCase = makeCase: ''
|
||||
case "$VM_NAME" in
|
||||
${lib.concatMapStringsSep "\n " makeCase cfg.nixosVms}
|
||||
${lib.concatMapStringsSep "\n " makeCase vms}
|
||||
*)
|
||||
echo "Unknown VM: $VM_NAME" >&2
|
||||
echo "Available VMs: ${lib.concatMapStringsSep ", " (vm: vm.name) cfg.nixosVms}" >&2
|
||||
echo "Available VMs: ${lib.concatMapStringsSep ", " (vm: vm.name) vms}" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
|
@ -422,7 +425,7 @@ let
|
|||
|
||||
if [ ! -S "$SOCKET" ]; then
|
||||
echo "Unknown VM or socket not active: $VM_NAME" >&2
|
||||
echo "Available VMs: ${lib.concatMapStringsSep ", " (vm: vm.name) cfg.nixosVms}" >&2
|
||||
echo "Available VMs: ${lib.concatMapStringsSep ", " (vm: vm.name) vms}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
|
@ -543,11 +546,9 @@ in
|
|||
config = lib.mkIf cfg.enable {
|
||||
# Set internal options for other modules to consume
|
||||
programs.vmsilo._internal = {
|
||||
vmScripts = lib.listToAttrs (map (vm: lib.nameValuePair vm.name (mkVmScript vm)) cfg.nixosVms);
|
||||
vmScripts = lib.listToAttrs (map (vm: lib.nameValuePair vm.name (mkVmScript vm)) vms);
|
||||
|
||||
proxyScripts = lib.listToAttrs (
|
||||
map (vm: lib.nameValuePair vm.name (mkProxyScript vm)) cfg.nixosVms
|
||||
);
|
||||
proxyScripts = lib.listToAttrs (map (vm: lib.nameValuePair vm.name (mkProxyScript vm)) vms);
|
||||
|
||||
userScripts = {
|
||||
vm-run = vmRunScript;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue