DEV Community

Sergey Baus
Sergey Baus

Posted on

Incus: system containers and VMs with one tool

If you know Docker and you know that virtual machines exist, Incus is easy to place: one tool that runs whole Linux systems in containers and, when you need it, real virtual machines. Same commands, and resource limits are set the same way, as instance options.

Virtual machines vs system containers, from the Incus docs

What it is

Incus is an open source manager for system containers, application containers and virtual machines. It started as a community fork of Canonical's LXD and is maintained by many of the same people who created LXD. It runs on any recent Linux distribution, and you drive it with the incus command line or its REST API.

System containers

A Docker container usually packages one application. A system container is a whole Linux system: systemd, a package manager, users, SSH, several services at once. Images are published for many distributions: Ubuntu, Debian, Fedora, Alpine, Arch, Rocky, NixOS and others.

A system container has no kernel of its own. It runs on the host kernel and is isolated with namespaces and cgroups. The docs describe the overhead as extremely low, so many of them fit on one machine.

incus launch images:debian/13 dev
incus exec dev -- bash
Enter fullscreen mode Exit fullscreen mode

Incus can also run regular application containers from OCI images, Docker Hub included.

Virtual machines

Some things don't belong in a container: a different OS such as Windows, your own kernel or kernel modules, full PCI passthrough. For those Incus starts a VM through QEMU. The commands stay the same, you just add --vm:

incus launch images:ubuntu/24.04 build --vm
incus console build --type vga
Enter fullscreen mode Exit fullscreen mode

A built-in agent gives VMs the same incus exec and file transfer as containers. The graphical console works through a SPICE client, even before the agent is running.

Limiting resources

Limits are ordinary instance options: limits.cpu (a number or a range of CPUs), limits.cpu.allowance (containers only: a percentage for a soft limit or a time slice like 25ms/100ms for a hard one), limits.memory, plus disk and network I/O. Usually you put them in a profile, a named set of options and devices that can be attached to any number of containers and VMs:

incus profile create small
incus profile set small limits.cpu=2 limits.memory=4GiB
incus launch images:ubuntu/24.04 web --profile default --profile small
Enter fullscreen mode Exit fullscreen mode

Incus also exposes metrics for every running instance (CPU, memory, network, disk, processes) on /1.0/metrics in Prometheus format.

The docs give a simple rule: if everything you need works with the host kernel, use a system container; if you need a different kernel or OS, use a VM.

What runs on my server

  • A persistent Ubuntu system container for a friend. He can SSH straight into it and use sudo inside, and everything survives restarts. Root inside maps to an unprivileged user on the host, and the server's internal services aren't reachable from the container. Its CPU and memory limits are ceilings without reservation.
  • A server for getbb.
  • GitHub Actions runners in VMs: Linux for private repos, a separate Linux VM for open source, and Windows Server for desktop builds. The Windows VM starts when jobs show up in the queue and shuts down after 15 minutes of idle.

Docs: https://linuxcontainers.org/incus/docs/main/

Top comments (0)