NixVM is a declarative approach to managing virtual machines by treating VM configurations and images as versioned, reproducible artifacts built on the Nix package manager. Instead of manually editing guest settings or imaging disks, you define machine states in Nix and materialize them consistently across hosts. This explainer covers core concepts, practical workflows, configuration patterns, integration options, and how NixVM relates to alternatives, with an emphasis on stability, composability, and auditability for long-lived infrastructure.
What NixVM is and who it is for
NixVM is a set of patterns and tooling that brings Nix reproducibility to virtual machines, whether you run them locally with QEMU or KVM or provision servers in a cloud or data center. It is useful when you need to reliably recreate identical environments, roll back to prior states, or manage many similar but slightly different VMs without configuration drift. Typical users include development teams, CI pipelines, and operations engineers who already rely on Nix for deterministic builds and want the same guarantees for infrastructure. While not a standalone hypervisor, NixVM complements solutions like NixOS, Docker, and cloud images by keeping VM artifacts declarative and versioned.
How NixVM works at a high level
At its core, NixVM encodes a virtual machine as a Nix derivation or flake that specifies the disk image, kernel, firmware, cloud-init data, and any baked-in packages and configuration. When you build or activate a VM definition, Nix computes a unique store address based on its exact contents; changing any file, package, or setting produces a different address and a new artifact. You can instantiate multiple VM derivations from a common base by overriding a small set of attributes, which keeps storage efficient while letting each variant remain immutable and traceable. NixVM workflows typically integrate with existing hypervisor tooling rather than replacing it, using Nix to drive QEMU/KVM, LXD, or cloud providers through declarative specifications.
Derivation-based images and address-based caching
Because each VM image is a Nix store artifact, you get automatic deduplication and content addressing. Two VMs that share the same base image and diverge only in a few overlay layers can reuse most of the same underlying store objects, saving disk space. Rollbacks are essentially pointer switches to an earlier store path, which makes recovery fast and deterministic. This model also enables reliable caching in shared environments, since the address changes only when the full dependency tree changes. For teams, this means centrally stored paths can be fetched once and reused across machines and CI runners without rebuilding everything from scratch.
Key concepts and terminology
- Declarative VM definition: A Nix expression or flake that specifies everything needed to instantiate a VM.
- Store derivation: A content-addressed unit that produces a VM disk, kernel, and configuration bundle.
- Overlay or diff layer: A writable layer on top of a shared base image for stateful changes.
- Flake inputs: External sources such as nix-community modules, shared flakes, or package sets that compose into your VM definition.
- Activation: The process of instantiating a derivation to create or start a VM using a hypervisor backend.
Basic workflows and practical examples
To use NixVM in practice, you start with a base module that defines a minimal VM, then extend it with packages, users, services, and network settings. A simple local workflow might express a VM as a NixOS-like configuration with hardware virtualization options, from which you build an image and launch it via QEMU. In more advanced setups, you parameterize VMs with environment-specific overlays so you can generate staging, testing, and production variants from a single source of truth. You can also integrate NixVM definitions into CI so that every merge produces a fresh, addressable VM artifact for integration tests. Because the definitions are code, you can lint them, review diffs, and keep them in the same repository as application code.
Example patterns (conceptual, not prescriptive)
Below is a simplified comparison of how similar VMs might be expressed with different goals in mind. Exact module names and options depend on your tooling and hypervisor choices.
| VM purpose | Core attributes | Use case |
|---|---|---|
| Development workstation | Minimal base packages, user config, shared folders, forwarded ports | Daily interactive use with quick iteration |
| CI runner | Hardened image, no persistent user state, cleanup on shutdown | Ephemeral builds and tests, reproducible results |
| Staging server | Near-production packages, monitoring agents, read-only except logs | Pre-production validation and performance checks |
| Reference golden image | Locked package set, signed configurations, baseline security settings | Standard baseline for clones and audits |
Integration and deployment options
NixVM does not mandate a single deployment path; it works alongside existing virtualization and cloud ecosystems. Locally, you can drive QEMU or KVM through NixOS module options or libvirt-derived tooling, storing VM artifacts in the Nix store or exporting them to disk images for other platforms. In data centers, you can combine Nix-defined images with tools like LXD, cloud-init, or infrastructure-as-code pipelines that consume Nix-built artifacts. Because the definitions are portable, you can version them in Git, generate images for multiple hypervisors, and apply the same declarative patches across environments. This makes it easier to audit changes, reproduce incidents, and keep configurations synchronized without manual diff-and-apply steps.
How NixVM relates to alternatives
NixVM is one approach among many for reproducible infrastructure, and it is most powerful when positioned within your broader stack rather than treated as a drop-in replacement for everything. Below is a concise relationship map to clarify tradeoffs and typical fit scenarios.
| Approach | Scope of reproducibility | Typical tradeoffs |
|---|---|---|
| NixVM (with QEMU/KVM) | VM disk and guest configuration as Nix derivations | Strong isolation, higher resource cost; best where full-OS reproducibility matters |
| NixOS on dedicated hardware or in cloud | Declarative host OS with live configuration managementLower overhead than VMs; limited by host kernel sharing | |
| Docker containers | Process-level isolation and image reproducibility | Lightweight and fast; less isolation and different security model |
| Packer or cloud AMI pipelines | Image-building automation, often imperative | Good for existing CI/CD; can diverge from source config unless codified in Nix |
| Terraform for infrastructure | Resource and network topology as code | Excellent for orchestration; does not manage OS packages or configs by itself |
In practice, teams often combine approaches: use NixVM for critical development and test VMs, NixOS for production servers, and container images for microservices. Keeping these definitions in the same Nix codebase reduces divergence and makes rollbacks and audits more straightforward.
Operational considerations and limitations
NixVM introduces new operational patterns you need to manage, such as deciding where store paths live, how to handle secrets, and how to integrate with provisioning and monitoring tools. Storage can grow if you retain many VM derivations, so consider retention policies and periodic garbage collection. Because hypervisor backends vary, not every NixVM feature works identically across QEMU, KVM, LXD, or cloud providers; you should validate device and networking behavior for your target environment. Finally, treat VM definitions as code: review diffs, include them in CI, and version them so you can reliably reproduce state and understand who changed what and when.