AshleyYakeley / NixVirt

LibVirt domain management for Nix
MIT License
192 stars 21 forks source link

NixVirt

NixVirt lets you declare virtual machines (libvirt domains) and associated objects in Nix.

Flake

NixVirt is a Nix flake, which you can obtain from FlakeHub. FlakeHub (Note that the master branch on GitHub is frequently broken.)

Add NixVirt to your own flake.nix:

{
  inputs.NixVirt =
  {
    url = "https://flakehub.com/f/AshleyYakeley/NixVirt/*.tar.gz";
    inputs.nixpkgs.follows = "nixpkgs";
  };

  outputs = { self, NixVirt }:
  {
    # Use in your outputs
  };
}

You should probably use inputs.nixpkgs.follows to keep NixVirt stuff at the same version as your system software, to prevent various version incompatibilities.

These are the available outputs:

nixosModules.default

A NixOS module with these options:

Note that NixOS already has options under virtualisation.libvirtd for controlling the libvirt daemon.

homeModules.default

The same as above, as a Home Manager module, except that virtualisation.libvirtd.enable must already be switched on in NixOS. You may want to use "qemu:///session" for the connection.

apps.x86_64-linux.virtdeclare

virtdeclare is a command-line tool for defining and controlling libvirt objects idempotently, used by the modules.

usage: virtdeclare [-h] [-v] --connect URI --type {domain,network} (--define PATH | --uuid ID | --name ID)
                   [--state {active,inactive}] [--auto]

Define and control libvirt objects idempotently.

options:
  -h, --help            show this help message and exit
  -v, --verbose         report actions to stderr
  --connect URI         connection URI (e.g. qemu:///session)
  --type {domain,network}
                        object type
  --define PATH         XML object definition file path
  --uuid ID             object UUID
  --name ID             object name
  --state {active,inactive}
                        state to put object in
  --auto                set autostart to match state

Currently virtdeclare only controls libvirt domains and networks.

packages.x86_64-linux.default

A package containing virtdeclare.

lib

Functions for creating libvirt object definition XML from Nix sets.

lib.domain.getXML

Create domain XML for a given structure (returns a string). The Nix structure roughly follows the XML format, but is currently missing elements. Please edit the file and create a PR for anything you need.

Example

See this file.

lib.domain.writeXML

Write domain XML for a given structure (returns a path).

lib.domain.templates

Templates for domains, suitable for passing to lib.domain.writeXML. These definitions are currently not stable, and are mostly for getting started with, so you should not depend on their precise configuration.

If you have suggestions for improvements, please create a PR.

lib.domain.templates.pc

A template function for a kinda basic Intel 440FX machine.

These are the arguments:

lib.domain.templates.q35

A template function for a kinda basic Intel Q35 machine.

These are the arguments:

lib.domain.templates.linux

A template function for a domain suitable for installing Linux on.

These are the arguments:

Example

In your Home Manager configuration:

virtualisation.libvirt.connections."qemu:///session".domains =
  [
    {
      definition = nixvirt.lib.domain.writeXML (nixvirt.lib.domain.templates.linux
        {
          name = "Penguin";
          uuid = "cc7439ed-36af-4696-a6f2-1f0c4474d87e";
          memory = { count = 6; unit = "GiB"; };
          storage_vol = { pool = "MyPool"; volume = "Penguin.qcow2"; }
        });
    }
  ];

lib.domain.templates.windows

A template function for a domain suitable for installing Windows 11 on. It supports Secure Boot via OVMF and an emulated TPM; you will want to switch on virtualisation.libvirt.swtpm.enable.

These are the arguments:

Example

In your Home Manager configuration:

virtualisation.libvirt.swtpm.enable = true;
virtualisation.libvirt.connections."qemu:///session".domains =
  [
    {
      definition = nixvirt.lib.domain.writeXML (nixvirt.lib.domain.templates.windows
        {
          name = "Bellevue";
          uuid = "def734bb-e2ca-44ee-80f5-0ea0f2593aaa";
          memory = { count = 8; unit = "GiB"; };
          storage_vol = { pool = "MyPool"; volume = "Bellevue.qcow2"; };
          install_vol = /home/ashley/VM-Storage/Win11_23H2_EnglishInternational_x64v2.iso;
          nvram_path = /home/ashley/VM-Storage/Bellevue.nvram;
          virtio_net = true;
          virtio_drive = true;
          install_virtio = true;
        });
    }
  ];

lib.network.getXML

Create network XML for a given structure (returns a string). The Nix structure roughly follows the XML format, but is currently missing elements. Please edit the file and create a PR for anything you need.

Example
lib.network.getXML
  {
    name = "default";
    uuid = "c4acfd00-4597-41c7-a48e-e2302234fa89";
    forward =
      {
        mode = "nat";
        nat = { port = { start = 1024; end = 65535; }; };
      };
    bridge = { name = "virbr0"; };
    mac = { address = "52:54:00:02:77:4b"; };
    ip =
      {
        address = "192.168.74.1";
        netmask = "255.255.255.0";
        dhcp = { range = { start = "192.168.74.2"; end = "192.168.74.254"; }; };
      };
  }

lib.network.writeXML

Write network XML for a given structure (returns a path).

lib.network.templates.bridge

A template function for a typical bridge to be created in qemu:///system. Domains created in qemu:///session will be able to use it.

These are the arguments:

Example

In your NixOS configuration:

virtualisation.libvirt.connections."qemu:///system".networks =
  [
    {
      definition = nixvirt.lib.network.writeXML (nixvirt.lib.network.templates.bridge
        {
          uuid = "70b08691-28dc-4b47-90a1-45bbeac9ab5a";
          subnet_byte = 71;
        });
      active = true;
    }
  ];

lib.pool.getXML

Create pool XML for a given structure (returns a string). The Nix structure roughly follows the XML format, but is currently missing elements. Please edit the file and create a PR for anything you need.

Example
lib.pool.getXML
{
  name = "MyPool";
  uuid = "650c5bbb-eebd-4cea-8a2f-36e1a75a8683";
  type = "dir";
  target = { path = "/home/ashley/VM-Storage/MyPool"; };
}

lib.pool.writeXML

Write volume XML for a given structure (returns a path).

lib.volume.getXML

Create volume XML for a given structure (returns a string). The Nix structure roughly follows the XML format, but is currently missing elements. Please edit the file and create a PR for anything you need.

Example
lib.volume.getXML
{
  name = "MainDisk";
  capacity = { count = 20; unit = "GB"; };
}

lib.volume.writeXML

Write volume XML for a given structure (returns a path).

lib.xml

Various functions for creating XML text.

lib.guest-install.virtio-win.iso

ISO disc image of virtio-win, for installing paravirtualised drivers, etc., inside Windows guests.