# virtme-ng: boot a freshly built kernel inside a snapshot of your own system

> virtme-ng builds a Linux kernel from source with a minimal config and boots it under QEMU on a copy-on-write view of your running system, so a crash costs nothing. The payoff is a kernel test cycle in minutes, paid for with a stripped configuration and a dependency on KVM for usable speed.

**arighi/virtme-ng** — Quickly build and run kernels inside a virtualized snapshot of your live system

- Repository: https://github.com/arighi/virtme-ng
- Stars: 907 · Forks: 97
- Language: Python
- License: GPL-2.0
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/arighi-virtme-ng

## The problem: a kernel test cycle measured in reboots

Building a Linux kernel from source takes long enough that the interesting part of the work is what you do with the result. A kernel that has just been compiled has to be installed, rebooted into, tested and then, if it misbehaves, booted back into something that works. On a machine that is also your daily driver, that cycle is both slow and risky.

virtme-ng attacks the second half of the problem. It is a tool that lets you recompile and test a kernel starting from source code, and it does so by starting the new kernel inside a virtualized environment that the documentation describes as an exact copy-on-write copy of your live system. Because the guest writes to a copy-on-write layer rather than to your files, you can destroy the entire filesystem inside the guest, crash the kernel, and do whatever else the test demands without touching the host.

The audience is kernel developers, their CI systems, and anyone who has to test a specific kernel tag or branch on a workstation. The project is based on virtme, written by Andy Lutomirski, and the kernel version string you get in the guest carries the virtme suffix, so the lineage is visible in the output.

The cost of the speed is stated plainly in the documentation. Kernels produced with virtme-ng lack a lot of features, on purpose, to keep the build time at a minimum while still giving you a kernel that can run your tests.

## The mechanism: a minimal config, QEMU, and a copy-on-write filesystem

Three pieces do the work. First, a minimal kernel configuration is produced, with the bare minimum support needed to boot inside QEMU. Second, the selected kernel is built. Third, it is started under QEMU using the host filesystem as a copy-on-write snapshot.

The ordering matters. Because the config is minimal, the build is fast, and because the filesystem is a snapshot, the boot is cheap and disposable. The documentation notes that if a .config is not already available, virtme-ng will automatically create a minimum one with the features required to boot the instance, and that a bare vng --kconfig writes that minimal config into the current kernel build directory.

The guest is brought up by a small helper binary, virtme-ng-init, written in Rust and built statically. The setup file explains why static linking is not optional: the same virtme-ng-init has to work across different root filesystems when the --root DIR option is used. The Rust build is driven by cargo:

```python
args = ["cargo", "install", "--path", ".", "--root", root]
```

So the toolchain is a Python program plus a Rust helper plus QEMU, and the build machinery knows which of those pieces to compile based on an environment variable. The Makefile treats the helper binary as its default target and drives the Python build to produce it.

## Installing from pip, from source, or from your distribution

virtme-ng is packaged in most major distributions, and the project points at a repology status page listing the versions each repository carries. The documentation warns that a distribution version may not be the latest stable release with new features and bug fixes, and invites help with packaging.

The stable release is also on pypi, and the install is:

```console
$ pip install virtme-ng
```

That path does not pull in the dependencies, which the documentation tells you to install yourself. Building from source is the option that gives you the statically linked helper:

```console
$ git clone https://github.com/arighi/virtme-ng.git
$ cd virtme-ng
$ BUILD_VIRTME_NG_INIT=1 pip3 install .
```

The BUILD_VIRTME_NG_INIT variable is the switch. On Debian and Ubuntu the documentation asks for extra packages for a proper source build:

```console
  $ sudo apt install python3-pip flake8 pylint cargo rustc qemu-system-x86
```

Users of uv can install the tool the same way:

```console
$ BUILD_VIRTME_NG_INIT=1 uv tool install .
```

You can also skip installation entirely and run from the source directory, optionally building the helper first with make for a faster boot. The documentation's example of that is simply:

```console
$ ./vng --help
```

The Makefile has an install_only_top target that installs with BUILD_VIRTME_NG_INIT=0, which is the lighter variant if you do not need the Rust helper.

## The quick start: build a tag, then boot it without rebooting

The documentation walks through a full cycle starting from a clean checkout of the kernel tree. The commands are run in the kernel source directory:

```console
$ uname -r
5.19.0-23-generic
$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
$ cd linux
$ vng --build --commit v6.2-rc4
```

After the build, the same command starts the new kernel inside the snapshot:

```console
$ vng
```

The banner it prints identifies the kernel version it booted, and a second uname -r inside the guest shows it running the new kernel rather than the host's:

```console
$ uname -r
6.2.0-rc4-virtme
```

The -rc4 suffix and the -virtme suffix are both meaningful. The first is the tag you asked for, and the second marks the kernel as a virtme build. You type exit to return to the real system, and nothing you did inside the guest touched the host.

The shorter forms exist too. A build from a clean local kernel source directory is vng -b, and naming a specific tag is done by adding a commit argument:

```console
   $ vng -b -c v6.1-rc3
```

And if you only want the config without building anything, vng --kconfig writes the minimal .config into the current build directory.

## KVM decides whether this is usable or painful

The performance question is settled by hardware virtualization, and the documentation is direct about it. You need a much better experience if KVM is enabled, which means bare metal with VT-x or SVM enabled, or a virtual machine that supports nested virtualization. On some distributions you have to be a member of the kvm group.

Without KVM you fall back to emulation. Using VirtualBox or most VPS providers will do that, and the result is a slow test cycle that partly defeats the point of the tool. The documentation also covers the continuous integration case, noting that KVM is available on the larger Linux runners on GitHub Actions, that it has to be enabled manually, and pointing at the project's own workflow file and at a commit using it with Docker.

The QEMU requirement is QEMU 1.6 or higher, with 1.4 and 1.5 partially supported through what the documentation calls a rather ugly kludge.

Beyond that, the optional pieces are worth knowing. A statically linked busybox binary somewhere in your path may be needed depending on the options you use. virtiofsd 1.7.0 or higher improves filesystem performance inside the guest. socat is needed for the --console and --console-client options, and those require the host kernel to support VSOCK through CONFIG_VHOST_VSOCK. sshd is needed for --ssh and --ssh-client. Shell completion is missing when you install from pip or from source, and shtab can supply it.

## The JSON configuration file and what vng --clean will not delete

Configuration lives in a JSON file, and three locations are consulted in order of preference: $HOME/.config/virtme-ng/virtme-ng.conf, $HOME/.virtme-ng.conf, and /etc/virtme-ng.conf. Any value you leave out falls back to the built-in default, so a partial file is valid.

The default file looks like this:

```json
  {
      "default_opts": {},
      "clean_exclude": [],
      "systemd": {
          "masks": ["getty@"],
          "fstab": "/dev/null"
      }
  }
```

The systemd section is what makes the guest bootable without touching the host's mount table. getty@ is masked so the console does not try to start a login prompt, and fstab points at /dev/null so nothing from the host's fstab is mounted inside the guest.

The other key, clean_exclude, is the one with teeth. It is a list of patterns excluded from vng --clean, and each pattern is passed as a -e argument to git clean. To keep a semantic code database around across cleans, for instance, you would write:

```json
  {
      "clean_exclude": [".semcode.db"]
  }
```

That is a small feature with a large blast radius if you get it wrong, since vng --clean removes untracked files from the tree and anything you have not excluded will go with them.

## The Python version, the licence and the release history

The prose and the packaging disagree about the minimum Python version, and the packaging is the one that matters. The requirements section says you need Python 3.8 or higher, while the project metadata declares requires-python = ">=3.10". Anyone on 3.8 or 3.9 should expect pip to refuse the install rather than a runtime failure later.

The licence is GPL-2.0, which matters more here than it would for a small script, because the project is a fork in spirit of virtme, and the man page metadata credits both authors, virtme-ng by Andrea Righi and the original virtme by Andy Lutomirski. The repository also carries a DCO-1.1.txt file, so contributions are made under the Developer Certificate of Origin rather than a signed-off-by style. A fork of a GPL-2.0 project inherits the copyleft obligations, and this is not a licence to read as legal advice, but it does mean a distribution of modified virtme-ng has to keep the terms.

On maintenance, the project is not archived and the last push was on 2026-10-17. The tags are v1.42 on 2026-10-13, v1.41 on 2026-04-05 and v1.40 on 2025-12-01, so the gap between 1.40 and 1.41 was about four months and the gap before 1.42 was six months. There is also an optional extra called mcp in the project metadata, which pulls in mcp>=0.9.0 and anyio>=4.0.0, and a vng-mcp entry at the top of the tree, so the tool has a machine interface alongside its command line.

## Conclusion

Adopt virtme-ng if you build kernels regularly and want to test them without rebooting or risking your working system, and if you have hardware virtualization available. Do not adopt it as a general purpose virtual machine manager, since the generated kernel is deliberately stripped of features, and do not expect the shipped configuration file to be sufficient on a distribution that needs more than a getty mask and a null fstab. Before you start, check that KVM is available and that you are on Python 3.10 or newer, since the packaging requires it even though the prose says 3.8.

## FAQ

### What does virtme-ng do and how is it different from virtme?

virtme-ng builds a Linux kernel from source with a minimal config and boots it under QEMU on a copy-on-write snapshot of your live system, so changes inside the guest do not affect the host. It is based on virtme, written by Andy Lutomirski, and adds features such as a config file, a Rust based virtme-ng-init helper and an optional MCP interface.

### How do I install virtme-ng from source?

Clone the repository, change into the directory and run BUILD_VIRTME_NG_INIT=1 pip3 install ., which also builds the statically linked virtme-ng-init helper with cargo. The documentation lists python3-pip, flake8, pylint, cargo, rustc and qemu-system-x86 as the extra packages needed on Debian and Ubuntu.

### Does virtme-ng need KVM to be fast?

The documentation says you will have a much better experience if KVM is enabled, which means bare metal with VT-x or SVM, or a VM with nested virtualization. Using VirtualBox or most VPS providers falls back to emulation, and you may need to be a member of the kvm group on some distributions.

### How do I keep a file from being deleted by vng --clean?

Add it to the clean_exclude list in the JSON configuration file, for example {"clean_exclude": [".semcode.db"]}. Each pattern is passed as a -e argument to git clean, and the configuration can live in $HOME/.config/virtme-ng/virtme-ng.conf, $HOME/.virtme-ng.conf or /etc/virtme-ng.conf.

### Which Python version does virtme-ng need?

The project metadata declares requires-python = ">=3.10", while the requirements section in the prose says Python 3.8 or higher. The packaging requirement is the one pip enforces, so use 3.10 or newer.

## Sources

- [arighi/virtme-ng on GitHub](https://github.com/arighi/virtme-ng)
- [Issues](https://github.com/arighi/virtme-ng/issues)
- [License: GPL-2.0](https://github.com/arighi/virtme-ng/blob/main/LICENSE)
- [README](https://github.com/arighi/virtme-ng/blob/main/README.md)
- [Releases](https://github.com/arighi/virtme-ng/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/arighi-virtme-ng
