Labtris
Migration guide

Labtris and vrnetlab

vrnetlab solves a specific problem very neatly. Container orchestrators only know how to run containers, but most network operating systems ship as a disk image for a virtual machine. So vrnetlab builds a container that contains a VM: QEMU runs inside, a small supervisor handles the boot and the initial configuration, and the outside world sees something that looks and behaves like a container.

That is a clever answer to “my tool only speaks container”. Labtris does not have that problem. It runs QEMU itself, as a first-class node type alongside Docker, so a router VM is just a VM — there is nothing to wrap, and no second layer to debug.

If you already build vrnetlab images, the thing worth knowing is that the input to that build — the vendor qcow2 — is exactly what Labtris wants. You can skip the wrapper.

Last checked against srl-labs/vrnetlab, the fork containerlab uses, and the upstream vrnetlab/vrnetlab in October 2026. Comparisons go stale; if something here is wrong now, please say so.

At a glance

What changes if you switch.

The differences worth knowing before reading anything else. The concept map further down answers the other question — where each thing you already use ended up.

What is it?
vrnetlab
A build system that packages a VM as a container image.
Labtris
A runtime that boots the VM directly.
How many layers when it breaks?
vrnetlab
Docker → QEMU → guest.
Labtris
QEMU → guest.
What does it need from the host?
vrnetlab
A privileged container with /dev/kvm passed through.
Labtris
QEMU under an unprivileged service. Only netd is root, and only for netlink.
Getting an image
vrnetlab
Build it yourself per platform from a licensed qcow2. For most platforms there is no public registry, and the build is its own step that can fail.
Labtris
Point at the same qcow2 — the input to that build is what Labtris wants. Skip the wrapper.
First console output
vrnetlab
Telnet to a port the wrapper forwards, once it is listening.
Labtris
The guest’s own serial, from the first byte the firmware prints.
Snapshots
vrnetlab
Effectively no — the VM’s state lives inside a container whose lifecycle was not designed around savevm.
Labtris
Real savevm / loadvm, including RAM.
What the host thinks it is running
vrnetlab
A container — while the memory actually belongs to a VM inside it.
Labtris
A VM, accounted as one.

These are not really competitors. vrnetlab exists because container orchestrators only speak container, and it answers that well; Labtris runs QEMU itself, so the problem does not arise. Worth knowing which copy you have: the actively developed one is srl-labs/vrnetlab, the fork containerlab uses, while upstream vrnetlab/vrnetlab has been quiet since February 2026. Both are MIT.

What vrnetlab got right

Keep using these ideas.

  • It makes VMs portable into container-native tooling. If your orchestrator only speaks container, this is the way to run a vendor NOS in it.
  • The per-platform launch logic is real engineering: serial expect scripts, boot detection, initial config injection, interface ordering — all the parts that make a vendor image awkward.
  • One artefact. Once built, a vrnetlab image is a normal container image you can push to a registry and pull anywhere.
  • It is the reason containerlab can run SR OS, vMX, vQFX, CSR and friends at all.
Where the friction came from

The reasons to look elsewhere.

  • It is QEMU inside Docker. That needs a privileged container and /dev/kvm passed through, and when something misbehaves you are debugging two layers instead of one.
  • You have to build the image yourself from a licensed qcow2 — there is no public registry for most of them, and the build is a step that can fail on its own.
  • The console is whatever the wrapper exposes, usually telnet to a forwarded port, rather than the guest's own serial from its first byte.
  • Snapshots are not really available: the VM's state lives inside a container whose lifecycle is not designed around savevm.
  • Resource accounting is misleading — the host sees a container, the memory belongs to a VM inside it.
Concept map

What you know, and what it’s called here.

Same primitives, mostly. A few things are actually different — those get their own row.

  • What it is
    vrnetlab
    A build system that packages a VM as a container image
    Labtris
    A runtime that boots VMs directly
  • Layers
    vrnetlab
    Docker → QEMU → guest
    Labtris
    QEMU → guest
  • Privilege
    vrnetlab
    Privileged container with /dev/kvm passed in
    Labtris
    QEMU under an unprivileged service; only netd is root, and only for netlink
  • Getting an image
    vrnetlab
    Build it: vendor qcow2 + make, per platform
    Labtris
    Point at the qcow2. RAM, NIC model and disk bus come from the catalogue or from you
  • First console
    vrnetlab
    Telnet to a port the wrapper forwards
    Labtris
    The guest's own serial, from the first byte the firmware prints
  • Graphical guests
    vrnetlab
    Not the use case
    Labtris
    VNC through Guacamole, in the browser
  • Snapshots
    vrnetlab
    Effectively no
    Labtris
    Real savevm / loadvm, including RAM
  • Save a configured box
    vrnetlab
    Rebuild the image
    Labtris
    Stop it, Export as template — the disk is flattened into a reusable image
  • Interfaces
    vrnetlab
    The wrapper maps container veths to guest NICs
    Labtris
    veth straight into the VM's NICs, named by the guest's own scheme
  • Portability
    vrnetlab
    Strong — it is a container image
    Labtris
    Weaker — a saved image lives on the host that made it
  • Licensed images
    vrnetlab
    Yours to obtain and build
    Labtris
    Yours to obtain. Neither project redistributes them
Bringing your lab across

Importing existing topologies.

Use the qcow2, not the wrapper. Every vrnetlab image starts life as a vendor disk image that you already had to obtain. That file is what Labtris runs. Upload it from the browser or drop it in the image directory, set the RAM, the NIC model and the disk bus, and boot it.

The two settings that decide whether it boots are the ones vrnetlab’s per-platform code encodes for you. A guest with no virtio-blk driver will not boot from a virtio disk, and it fails silently at a blank console — 67 of the 182 QEMU appliances in the GNS3 registry need IDE instead. The same is true one layer up for the NIC. Labtris records both per image and lets you override them per node; importing a GNS3 appliance definition fills them in for you.

Running a vrnetlab container as-is is not supported. In principle it is a Docker image like any other, but it wants privilege and a KVM device, and nesting QEMU inside a container that Labtris started is not a path that has been tested. Do not assume it works — use the disk image.

If you came here from containerlab, the vr-* kinds in a .clab.yml import as labelled placeholders with a note saying the image is built locally from a vendor qcow2. The topology and the wiring survive; you point the nodes at the disk images.

Try Labtris.

Private beta: ask for access, install with the token you get back. No telemetry, no lock-in; the code you receive is MIT.