HASH df43606f2e0f
DATE 2025-05-03
SUBJECT virtualization: nixos install vm script init
FILES 3 CHANGED
HASH df43606f2e0f
DATE 2025-05-03
SUBJECT virtualization: nixos install vm
script init
FILES 3 CHANGED
┌─ hosts/ooksdesk/default.nix ───────────────────────────────────────────────┐
│ diff --git a/hosts/ooksdesk/default.nix b/hosts/ooksdesk/default.nix │
│ index 0452446..549c5f8 100644 │
│ --- a/hosts/ooksdesk/default.nix │
│ +++ b/hosts/ooksdesk/default.nix │
│ @@ -36,6 +36,9 @@ │
│ editor = "nvim"; │
│ multiplexer = "zellij"; │
│ }; │
│ + virtualization = { │
│ + ooknet-install-vm.enable = true; │
│ + }; │
│ }; │
│ boot.kernelPackages = pkgs.linuxPackages_xanmod_latest; │
│ │
└────────────────────────────────────────────────────────────────────────────────────┘
┌─ hosts/ooksdesk/default.nix ─────────┐
│ diff --git a/hosts/ooksdesk/default.nix b/ho │
│ sts/ooksdesk/default.nix │
│ index 0452446..549c5f8 100644 │
│ --- a/hosts/ooksdesk/default.nix │
│ +++ b/hosts/ooksdesk/default.nix │
│ @@ -36,6 +36,9 @@ │
│ editor = "nvim"; │
│ multiplexer = "zellij"; │
│ }; │
│ + virtualization = { │
│ + ooknet-install-vm.enable = true; │
│ + }; │
│ }; │
│ boot.kernelPackages = pkgs.linuxPackages_ │
│ xanmod_latest; │
│ │
└──────────────────────────────────────────────┘
┌─ modules/nixos/workstation/virtualization/default.nix ─────────────────────┐
│ diff --git a/modules/nixos/workstation/virtualization/default.nix b/modules/nixos/ │
│ workstation/virtualization/default.nix │
│ index 9c7be83..03eb893 100644 │
│ --- a/modules/nixos/workstation/virtualization/default.nix │
│ +++ b/modules/nixos/workstation/virtualization/default.nix │
│ @@ -1,5 +1,6 @@ │
│ { │
│ imports = [ │
│ ./virt-manager.nix │
│ + ./ooknet-install-vm.nix │
│ ]; │
│ } │
└────────────────────────────────────────────────────────────────────────────────────┘
┌─ ...on/virtualization/default.nix ───┐
│ diff --git a/modules/nixos/workstation/virtu │
│ alization/default.nix b/modules/nixos/workst │
│ ation/virtualization/default.nix │
│ index 9c7be83..03eb893 100644 │
│ --- a/modules/nixos/workstation/virtualizati │
│ on/default.nix │
│ +++ b/modules/nixos/workstation/virtualizati │
│ on/default.nix │
│ @@ -1,5 +1,6 @@ │
│ { │
│ imports = [ │
│ ./virt-manager.nix │
│ + ./ooknet-install-vm.nix │
│ ]; │
│ } │
└──────────────────────────────────────────────┘
┌─ modules/nixos/workstation/virtualization/ooknet-install-vm.nix ───────────┐
│ diff --git a/modules/nixos/workstation/virtualization/ooknet-install-vm.nix b/modu │
│ les/nixos/workstation/virtualization/ooknet-install-vm.nix │
│ new file mode 100644 │
│ index 0000000..1048aaa │
│ --- /dev/null │
│ +++ b/modules/nixos/workstation/virtualization/ooknet-install-vm.nix │
│ @@ -0,0 +1,204 @@ │
│ +{ │
│ + pkgs, │
│ + lib, │
│ + config, │
│ + self, │
│ + ... │
│ +}: let │
│ + inherit (builtins) toFile; │
│ + inherit (lib) mkIf mkEnableOption mkOption; │
│ + inherit (lib.types) path string int; │
│ + inherit (self.nixosConfigurations.ooksinstall.config.image) filePath; │
│ + inherit (config.ooknet.host) admin; │
│ + iso = self.images.ooksinstall; │
│ + checkSudo = │
│ + if config.virtualisation.libvirtd.qemu.runAsRoot │
│ + then '' │
│ + if [ "$EUID" -ne 0 ]; then │
│ + log error "Sudo not provided: set 'virtualisation.libvirtd.qemu.runAsRoot │
│ = false;' to use without sudo." │
│ + exit 1 │
│ + fi │
│ + '' │
│ + else ""; │
│ + networkConfig = toFile "ooknet-install-network.xml" '' │
│ + <network> │
│ + <name>${cfg.network.name}</name> │
│ + <bridge name='${cfg.network.bridgeName}' stp='on' delay='0'/> │
│ + <forward mode='nat'/> │
│ + <ip address='${cfg.network.ip}' netmask='255.255.255.0'> │
│ + <dhcp> │
│ + <range start='${cfg.network.ipRange.start}' end='${cfg.network.ipRange. │
│ end}'/> │
│ + <host mac='${cfg.macAddress}' name='${cfg.name}' ip='${cfg.ipAddress}'/ │
│ > │
│ + </dhcp> │
│ + </ip> │
│ + </network> │
│ + ''; │
│ + cfg = config.ooknet.virtualization.ooknet-install-vm; │
│ +in { │
│ + options.ooknet.virtualization = { │
│ + ooknet-install-vm = { │
│ + enable = mkEnableOption "Enable virtual installation testing environment"; │
│ + isoPath = mkOption { │
│ + type = path; │
│ + default = "${iso}/${filePath}"; │
│ + description = "Path to iso to use"; │
│ + }; │
│ + name = mkOption { │
│ + type = string; │
│ + default = "ooknet-install-test"; │
│ + description = "Name of virtual machine"; │
│ + }; │
│ + user = mkOption { │
│ + type = string; │
│ + default = admin.name; │
│ + description = "SSH user to connect to virtual machine"; │
│ + example = "root"; │
│ + }; │
│ + macAddress = mkOption { │
│ + type = string; │
│ + default = "52:55:00:11:22:33"; │
│ + }; │
│ + ipAddress = mkOption { │
│ + type = string; │
│ + default = cfg.network.ipRange.start; │
│ + description = "IP address to assign to the virtual machine"; │
│ + }; │
│ + ram = mkOption { │
│ + type = int; │
│ + default = 2048; │
│ + description = "Amount of RAM to assign to the virtual machine"; │
│ + example = 2048; │
│ + }; │
│ + vcpus = mkOption { │
│ + type = int; │
│ + default = 2; │
│ + description = "Amount of cores to assign to the virtual machine"; │
│ + example = 4; │
│ + }; │
│ + storage = mkOption { │
│ + type = int; │
│ + default = 10; │
│ + description = "Amount in GB of storage to assign to the virtual machine"; │
│ + example = 10; │
│ + }; │
│ + network = { │
│ + name = mkOption { │
│ + type = string; │
│ + default = "ooknet-install-network"; │
│ + description = "Name of virtual network"; │
│ + }; │
│ + bridgeName = mkOption { │
│ + type = string; │
│ + default = "virbr1"; │
│ + description = "Name of virtual network bridge"; │
│ + }; │
│ + ip = mkOption { │
│ + type = string; │
│ + default = "192.168.150.1"; │
│ + }; │
│ + ipRange = { │
│ + start = mkOption { │
│ + type = string; │
│ + default = "192.168.150.2"; │
│ + }; │
│ + end = mkOption { │
│ + type = string; │
│ + default = "192.168.150.2"; │
│ + }; │
│ + }; │
│ + }; │
│ + }; │
│ + }; │
│ + config = mkIf cfg.enable { │
│ + environment.systemPackages = [ │
│ + (pkgs.writeShellApplication { │
│ + name = "ooknet-test-vm"; │
│ + runtimeInputs = [ │
│ + pkgs.gum │
│ + ]; │
│ + text = '' │
│ + set -e │
│ + │
│ + log() { │
│ + local type="$1" │
│ + local message="$2" │
│ + gum log --structured --level "$type" "$message" │
│ + } │
│ + │
│ + ${checkSudo} │
│ + │
│ + NAME=${cfg.name} │
│ + IMAGE_PATH="/var/lib/libvirt/images/$NAME.img" │
│ + │
│ + buildVM() { │
│ + log info "Setting up virtual network..." │
│ + if ! virsh net-info ${cfg.network.name} >/dev/null 2>&1; then │
│ + virsh net-define ${networkConfig} >/dev/null │
│ + log info "Network defined..." │
│ + else │
│ + log warn "Network was already defined..." │
│ + destroyNetwork │
│ + virsh net-define ${networkConfig} >/dev/null │
│ + fi │
│ + virsh net-start ${cfg.network.name} >/dev/null || true │
│ + log info "Network started..." │
│ + │
│ + log info "Building $NAME VM..." │
│ + gum spin --spinner dot --title "Installing VM..." -- \ │
│ + virt-install \ │
│ + -n "$NAME" \ │
│ + --ram=${toString cfg.ram} \ │
│ + --vcpus=${toString cfg.vcpus} \ │
│ + --disk path="$IMAGE_PATH",bus=virtio,size=${toString cfg.storage} \ │
│ + --graphics none \ │
│ + --cdrom ${cfg.isoPath} \ │
│ + --network network=${cfg.network.name},mac=${cfg.macAddress} \ │
│ + --noautoconsole; │
│ + } │
│ + │
│ + destroyNetwork() { │
│ + virsh net-destroy ${cfg.network.name} │
│ + log info "Network destroyed"; │
│ + virsh net-undefine ${cfg.network.name} │
│ + log info "Network undefined" │
│ + } │
│ + │
│ + destroyVM() { │
│ + log warn "Shutting VM down..." │
│ + virsh destroy "$NAME" >/dev/null || true │
│ + log warn "Deleting VM..." │
│ + virsh undefine "$NAME" --remove-all-storage >/dev/null │
│ + log info "VM successfully removed..." │
│ + } │
│ + │
│ + gum log --structured --level info "Checking if image already exists..." │
│ + │
│ + if virsh list --all | grep -q "\b$NAME\b"; then │
│ + log info "$NAME VM Found:" │
│ + if gum confirm "Remove existing $NAME VM?"; then │
│ + destroyVM │
│ + buildVM │
│ + else │
│ + log info "Aborting VM creation..." │
│ + exit 0 │
│ + fi │
│ + elif [ -f "$IMAGE_PATH" ]; then │
│ + log warn "Disk Image for '$NAME' exists without VM" │
│ + if gum confirm "Would you like to remove the orphaned disk?"; then │
│ + rm -f "$IMAGE_PATH" │
│ + buildVM │
│ + else │
│ + log error "Cannot create VM while orphaned disk exists" │
│ + exit 1 │
│ + fi │
│ + else │
│ + buildVM │
│ + fi │
│ + │
│ + log info "VM successfully created" │
│ + log info "Connect with: ssh ${cfg.user}@${cfg.ipAddress}" │
│ + ''; │
│ + }) │
│ + ]; │
│ + }; │
│ +} │
└────────────────────────────────────────────────────────────────────────────────────┘
┌─ ...ization/ooknet-install-vm.nix ───┐
│ diff --git a/modules/nixos/workstation/virtu │
│ alization/ooknet-install-vm.nix b/modules/ni │
│ xos/workstation/virtualization/ooknet-instal │
│ l-vm.nix │
│ new file mode 100644 │
│ index 0000000..1048aaa │
│ --- /dev/null │
│ +++ b/modules/nixos/workstation/virtualizati │
│ on/ooknet-install-vm.nix │
│ @@ -0,0 +1,204 @@ │
│ +{ │
│ + pkgs, │
│ + lib, │
│ + config, │
│ + self, │
│ + ... │
│ +}: let │
│ + inherit (builtins) toFile; │
│ + inherit (lib) mkIf mkEnableOption mkOptio │
│ n; │
│ + inherit (lib.types) path string int; │
│ + inherit (self.nixosConfigurations.ooksins │
│ tall.config.image) filePath; │
│ + inherit (config.ooknet.host) admin; │
│ + iso = self.images.ooksinstall; │
│ + checkSudo = │
│ + if config.virtualisation.libvirtd.qemu. │
│ runAsRoot │
│ + then '' │
│ + if [ "$EUID" -ne 0 ]; then │
│ + log error "Sudo not provided: set ' │
│ virtualisation.libvirtd.qemu.runAsRoot = fal │
│ se;' to use without sudo." │
│ + exit 1 │
│ + fi │
│ + '' │
│ + else ""; │
│ + networkConfig = toFile "ooknet-install-ne │
│ twork.xml" '' │
│ + <network> │
│ + <name>${cfg.network.name}</name> │
│ + <bridge name='${cfg.network.bridgeNam │
│ e}' stp='on' delay='0'/> │
│ + <forward mode='nat'/> │
│ + <ip address='${cfg.network.ip}' netma │
│ sk='255.255.255.0'> │
│ + <dhcp> │
│ + <range start='${cfg.network.ipRan │
│ ge.start}' end='${cfg.network.ipRange.end}'/ │
│ > │
│ + <host mac='${cfg.macAddress}' nam │
│ e='${cfg.name}' ip='${cfg.ipAddress}'/> │
│ + </dhcp> │
│ + </ip> │
│ + </network> │
│ + ''; │
│ + cfg = config.ooknet.virtualization.ooknet │
│ -install-vm; │
│ +in { │
│ + options.ooknet.virtualization = { │
│ + ooknet-install-vm = { │
│ + enable = mkEnableOption "Enable virtu │
│ al installation testing environment"; │
│ + isoPath = mkOption { │
│ + type = path; │
│ + default = "${iso}/${filePath}"; │
│ + description = "Path to iso to use"; │
│ + }; │
│ + name = mkOption { │
│ + type = string; │
│ + default = "ooknet-install-test"; │
│ + description = "Name of virtual mach │
│ ine"; │
│ + }; │
│ + user = mkOption { │
│ + type = string; │
│ + default = admin.name; │
│ + description = "SSH user to connect │
│ to virtual machine"; │
│ + example = "root"; │
│ + }; │
│ + macAddress = mkOption { │
│ + type = string; │
│ + default = "52:55:00:11:22:33"; │
│ + }; │
│ + ipAddress = mkOption { │
│ + type = string; │
│ + default = cfg.network.ipRange.start │
│ ; │
│ + description = "IP address to assign │
│ to the virtual machine"; │
│ + }; │
│ + ram = mkOption { │
│ + type = int; │
│ + default = 2048; │
│ + description = "Amount of RAM to ass │
│ ign to the virtual machine"; │
│ + example = 2048; │
│ + }; │
│ + vcpus = mkOption { │
│ + type = int; │
│ + default = 2; │
│ + description = "Amount of cores to a │
│ ssign to the virtual machine"; │
│ + example = 4; │
│ + }; │
│ + storage = mkOption { │
│ + type = int; │
│ + default = 10; │
│ + description = "Amount in GB of stor │
│ age to assign to the virtual machine"; │
│ + example = 10; │
│ + }; │
│ + network = { │
│ + name = mkOption { │
│ + type = string; │
│ + default = "ooknet-install-network │
│ "; │
│ + description = "Name of virtual ne │
│ twork"; │
│ + }; │
│ + bridgeName = mkOption { │
│ + type = string; │
│ + default = "virbr1"; │
│ + description = "Name of virtual ne │
│ twork bridge"; │
│ + }; │
│ + ip = mkOption { │
│ + type = string; │
│ + default = "192.168.150.1"; │
│ + }; │
│ + ipRange = { │
│ + start = mkOption { │
│ + type = string; │
│ + default = "192.168.150.2"; │
│ + }; │
│ + end = mkOption { │
│ + type = string; │
│ + default = "192.168.150.2"; │
│ + }; │
│ + }; │
│ + }; │
│ + }; │
│ + }; │
│ + config = mkIf cfg.enable { │
│ + environment.systemPackages = [ │
│ + (pkgs.writeShellApplication { │
│ + name = "ooknet-test-vm"; │
│ + runtimeInputs = [ │
│ + pkgs.gum │
│ + ]; │
│ + text = '' │
│ + set -e │
│ + │
│ + log() { │
│ + local type="$1" │
│ + local message="$2" │
│ + gum log --structured --level "$ │
│ type" "$message" │
│ + } │
│ + │
│ + ${checkSudo} │
│ + │
│ + NAME=${cfg.name} │
│ + IMAGE_PATH="/var/lib/libvirt/imag │
│ es/$NAME.img" │
│ + │
│ + buildVM() { │
│ + log info "Setting up virtual ne │
│ twork..." │
│ + if ! virsh net-info ${cfg.netwo │
│ rk.name} >/dev/null 2>&1; then │
│ + virsh net-define ${networkCon │
│ fig} >/dev/null │
│ + log info "Network defined..." │
│ + else │
│ + log warn "Network was already │
│ defined..." │
│ + destroyNetwork │
│ + virsh net-define ${networkCon │
│ fig} >/dev/null │
│ + fi │
│ + virsh net-start ${cfg.network.n │
│ ame} >/dev/null || true │
│ + log info "Network started..." │
│ + │
│ + log info "Building $NAME VM..." │
│ + gum spin --spinner dot --title │
│ "Installing VM..." -- \ │
│ + virt-install \ │
│ + -n "$NAME" \ │
│ + --ram=${toString cfg.ram} \ │
│ + --vcpus=${toString cfg.vcpus} │
│ \ │
│ + --disk path="$IMAGE_PATH",bus │
│ =virtio,size=${toString cfg.storage} \ │
│ + --graphics none \ │
│ + --cdrom ${cfg.isoPath} \ │
│ + --network network=${cfg.netwo │
│ rk.name},mac=${cfg.macAddress} \ │
│ + --noautoconsole; │
│ + } │
│ + │
│ + destroyNetwork() { │
│ + virsh net-destroy ${cfg.network │
│ .name} │
│ + log info "Network destroyed"; │
│ + virsh net-undefine ${cfg.networ │
│ k.name} │
│ + log info "Network undefined" │
│ + } │
│ + │
│ + destroyVM() { │
│ + log warn "Shutting VM down..." │
│ + virsh destroy "$NAME" >/dev/nul │
│ l || true │
│ + log warn "Deleting VM..." │
│ + virsh undefine "$NAME" --remove │
│ -all-storage >/dev/null │
│ + log info "VM successfully remov │
│ ed..." │
│ + } │
│ + │
│ + gum log --structured --level info │
│ "Checking if image already exists..." │
│ + │
│ + if virsh list --all | grep -q "\b │
│ $NAME\b"; then │
│ + log info "$NAME VM Found:" │
│ + if gum confirm "Remove existing │
│ $NAME VM?"; then │
│ + destroyVM │
│ + buildVM │
│ + else │
│ + log info "Aborting VM creatio │
│ n..." │
│ + exit 0 │
│ + fi │
│ + elif [ -f "$IMAGE_PATH" ]; then │
│ + log warn "Disk Image for '$NAME │
│ ' exists without VM" │
│ + if gum confirm "Would you like │
│ to remove the orphaned disk?"; then │
│ + rm -f "$IMAGE_PATH" │
│ + buildVM │
│ + else │
│ + log error "Cannot create VM w │
│ hile orphaned disk exists" │
│ + exit 1 │
│ + fi │
│ + else │
│ + buildVM │
│ + fi │
│ + │
│ + log info "VM successfully created │
│ " │
│ + log info "Connect with: ssh ${cfg │
│ .user}@${cfg.ipAddress}" │
│ + ''; │
│ + }) │
│ + ]; │
│ + }; │
│ +} │
└──────────────────────────────────────────────┘
[ BACK TO LOG ]
──────────────────────────────────────────────────────────────────────────────────────
OOKNET
────────────────────────────────────────────────
OOKNET