Skip to content

Incus

The Incus extension adds the Incus daemon, CLI, and web UI to a Frostyard bootc image, with its own QEMU for virtual machines. Use it to run system containers and virtual machines on the host. Every image carries the extension’s definition, switched off. The extension itself is not in the image: Updex turns it on and downloads it with one command.

You need:

  • A Frostyard bootc image. Every image built on Base has systemd-sysext and frostyard-updex.
  • Root access to enable, update, and remove the extension. Checks that change nothing run without sudo.
  • Network access to https://repository.frostyard.org/ext/incus/.
  • Free space in /var for the extension and for the storage your containers and virtual machines will use.
  • CPU virtualization switched on in the firmware, if you want virtual machines. The extension brings QEMU and OVMF; the firmware settings are up to you.
  • A backup or export of any existing containers, virtual machines, and storage pools.

Incus has no published test results on Frostyard images yet. Try it on a machine you can spare first.

Pick Incus for system containers and virtual machines. Incus runs as a system service: it creates and runs workloads, manages storage and networks, and listens on a local socket. Pick Docker for application containers instead.

Docker and Incus use different daemons and sockets. Running both on one host is not a supported setup; test your exact combination before you rely on it.

The extension works on Floe, the server image, as well as on the desktops. It carries the graphical libraries that Floe does not have, and each build checks that they are present.

The extension does not give you a package manager, and it does not replace an Incus you installed some other way.

See what Updex found:

Terminal window
updex components
updex features list --component=incus

incus appears as a component, with its feature disabled.

Enable Incus and download it now:

Terminal window
sudo updex features enable incus --now

Updex downloads the image, checks its checksum and signature, links it, and refreshes the merged extensions. A missing or bad signature stops the command; Updex never installs an unsigned image. Without --now, Updex only marks the feature enabled, and the next update downloads it.

Enabling writes one file in /etc: /etc/sysupdate.incus.d/incus.feature.d/00-updex.conf.

Check that Incus is merged and its services are up:

Terminal window
systemd-sysext status
systemctl status incus.socket incus-startup.service incus-sysext-setup.service

systemd-sysext status lists incus. Check the socket and the setup service first. incus.service starts on demand through incus.socket.

incus-sysext-setup.service gives root a subordinate UID and GID range with usermod, so user namespaces work without a manual step. It runs after systemd-sysusers and systemd-tmpfiles, and before the Incus sockets and incus-startup.service.

A merge does not prove that setup completed. At boot, reload-sysext.service runs systemd-sysusers, systemd-tmpfiles --create --graceful, a systemd-sysctl replay of the inotify, fs.aio-max-nr, and kernel.keys limits, and systemctl daemon-reload after the merge. A refresh by Updex v2.1.3 and later also runs systemd-sysusers and systemd-tmpfiles --create. After an interactive --now merge, the systemd-sysctl replay waits for the next boot, and systemd may not have loaded the new units yet. If the rdma group, the files in /etc, or incus-sysext-setup.service are missing, reboot and check again.

If enable --now exits with a refresh error (refresh_error in JSON), the download worked, but the activation did not. If the output says activation did not finish, the extension is merged, but users and groups can be missing: reboot. Otherwise the merge state is unknown: reboot. A sudo systemd-sysext refresh by hand does not create users and groups. Then run the two checks above again.

See whether an update exists:

Terminal window
updex features check --component=incus

This changes nothing. It shows one row for each enabled feature. A feature you have not enabled has no row, so a missing row does not mean “up to date”. If Updex cannot fetch or verify a manifest, that row shows UPDATE=error and the command exits non-zero. Treat an error row as unknown, not as up to date.

Install the newest version:

Terminal window
sudo updex features update --component=incus

Updex downloads and verifies the new image, switches the link, deletes older versions, and refreshes the merge. Add --no-vacuum to keep older versions. To see what would change, without changing anything:

Terminal window
sudo updex --dry-run features update --component=incus

The refresh swaps /usr under the running system, and the Incus daemon can restart. Stop or migrate containers and virtual machines first if a restart would hurt them. Your containers, virtual machines, and storage pools live outside the extension. An update does not touch them, and it does not back them up. Check your storage pool configuration to see where they are.

Once you enable Incus, it updates on its own: new versions are staged and become active at the next boot. To opt out for the whole host, run sudo systemctl mask --now updex-update.timer. See Automatic updates.

To take one update at the next boot without the timer, run sudo updex features update --no-refresh --component=incus, then reboot.

Roll back with sudo updex features rollback incus. It takes effect at the next boot. Updex then holds updates until a newer version is published. To stop future updates instead, see below. To remove the extension, use the remove command below. Your containers, virtual machines, and storage pools stay outside the extension either way. See Roll back.

A rollback to an older Incus release can break Incus. After an upgrade, Incus updates its database, and an older Incus can treat that database as invalid. Read Upgrade Incus before you roll back.

Stop future updates:

Terminal window
sudo updex features disable incus

This only sets Enabled=false. Incus stays merged, and the link /var/lib/extensions/incus.raw stays. The next boot merges the version that the link names. LINKED in updex features list shows it. To go back to the version you run now, roll back first. Updex and the timer skip it from now on.

Remove Incus now:

Terminal window
sudo updex features disable incus --now --force

This unmerges all extensions on the host, deletes the Incus image, and merges the rest again. Running containers and virtual machines can stop immediately. Stop or migrate your workloads first, and reboot when the command finishes.

Without --force, Updex refuses while Incus is merged: Extension incus (version ...) is active. Removing requires --force and a reboot to take effect.

Removal takes away the daemon, the CLI, the web UI, and their units. Your containers, virtual machines, storage pools, and other data in /var stay. Manage or delete them yourself. Enabling Incus again does not restart your workloads or bring back a missing storage pool.

If the refresh at the end fails, the remaining extensions may stay unmerged. Run sudo systemd-sysext refresh, or reboot. If the output says activation did not finish, they are merged, but their users and groups can be missing: reboot.

Incus runs privileged workloads. The extension creates the rdma group, the runtime directories, and the alternatives links that its tools expect. The dnsmasq user that owns /run/dnsmasq and /var/lib/misc comes from Base.

The extension copies its default files into /etc only when they are missing. Your edits to /etc/default/incus or the libvirt configuration survive reboots and updates. The defaults stay in /usr/share/factory/etc. The extension carries only the /etc files it names, not a copy of the build machine’s /etc. The QEMU network helpers, /etc/qemu-ifup and /etc/qemu-ifdown, come from Base, not from the extension.

The extension ships virt-viewer, the client for incus console --type=vga. Graphical consoles use the display support in the bundled QEMU under /usr/incus. Incus always uses its own QEMU in /usr/incus/bin. Do not replace it with a host package, and do not expect a change to the host’s qemu-system-x86_64 to affect Incus.

Symptom Check Fix
incus launch --vm says virtual machines are not supported Run incus info and look for the QEMU driver, for example driver: lxc | qemu If only lxc is present, the bundled QEMU runtime is not loading. Check that the extension is merged and that its libraries load (next row).
The bundled QEMU fails with a missing shared library LD_LIBRARY_PATH=/usr/incus/lib/ ldd /usr/incus/bin/qemu-system-x86_64 This extension build does not match your Base. Install a corrected extension. Do not patch /usr by hand.
The setup service did not run systemctl status incus-sysext-setup.service and its journal The service runs once per boot and skips when /run/incus-sysext-setup.done exists. Check that file.
incus.socket is inactive systemctl status incus.socket and systemd-sysext status Check that the extension is merged and the preset applied. After a staged update, refresh or reboot.
enable --now exits non-zero after the download The output shows Error: sysext refresh failed (refresh_error with --json) If the output says activation did not finish, reboot. Otherwise reboot too: a refresh by hand does not create the extension’s users and groups. Then check systemd-sysext status.
A manifest or signature check fails updex features check --component=incus Check the network and the published manifest. Never turn verification off.
Containers or VMs stopped during an update The journal shows the daemon restart after the /usr refresh Drain or migrate workloads before you update by hand. Back up storage first.

Do not repair the extension with apt. If a merged image is missing files, the fix is a corrected extension build.

Item What you get
Build package requests incus, incus-extra, incus-ui-canonical, dnsmasq-base, genisoimage, virt-viewer, librsvg2-common
Version The image file name carries the incus version
Image file incus_<version>_<os>_<arch>.raw.zst; .raw.xz, .raw.gz, and .raw also work
Download From https://repository.frostyard.org/ext/incus/, signature required (Verify=true), into /var/lib/extensions.d/
Services incus.socket, incus-user.socket, incus-lxcfs.service, incus-startup.service, and incus-sysext-setup.service
Activation 40-incus.preset enables the services. 10-incus.conf starts incus-sysext-setup.service, the two sockets, and incus-startup.service at boot. The setup service pulls in incus-lxcfs.service
Setup incus-sysext-setup.service runs a repeatable script once per boot, then writes /run/incus-sysext-setup.done
Configuration Defaults for /etc/default/incus, logrotate, needrestart, libvirt, and the VTE profile scripts
Users and directories The rdma group, plus runtime directories and alternatives links. The dnsmasq user comes from Base

The active image is the link /var/lib/extensions/incus.raw. It points to the chosen file in /var/lib/extensions.d/. The transfer file names a second link, CurrentSymlink=incus.raw, but Updex deletes that one (/var/lib/extensions.d/incus.raw) when it installs.

The checked catalog snapshot is generated, and its version changes with each sync. The source builds revision 5 (SYSEXT_REVISION=5). The revision is the +r number at the end of the version.

The incus package comes from the Frostyard APT repository, https://repository.frostyard.org/debian/. It is Frostyard’s rebuild of Zabbly’s package, and it bundles QEMU, OVMF, swtpm, and virtiofsd under /usr/incus. incusd puts /usr/incus/bin first in its PATH, so it runs /usr/incus/bin/qemu-system-x86_64, not Debian’s /usr/bin/qemu-system-x86_64.

The package row is what the build asks for. It does not promise that every request ships in the image: Base already ships qemu-system-x86, qemu-utils, and ovmf, and the image holds only what Base does not have.

Since revision 4, the extension ships no Debian QEMU or OVMF. It drops qemu-kvm, qemu-utils, qemu-system-gui, qemu-system-modules-spice, ovmf, and ipxe-qemu, which Incus never used. A build guard keeps it so: any extension build that ships Base’s QEMU, OVMF, or SeaBIOS files fails. Revision 3 images carried the Debian qemu-kvm, qemu-system-gui, qemu-system-modules-spice, and ipxe-qemu. These Debian leftovers are separate from the bundled /usr/incus runtime, which Incus uses.

Each build checks that the GTK3 and media libraries that the bundled QEMU and virt-viewer need are present. A smaller Base can still break an older Incus image: this has happened once, and a rebuild restored the libraries.

Updex picks the image that matches your OS version (%w in the file name) and your architecture (%a). The catalog lists versions, not architectures, so it does not tell you which architectures exist. A Base with a different composition can break the image even when the OS version and architecture match. The build check protects the build, not a host with a different Base.

Reviewed 2026-10-27; Updex facts reviewed 2026-10-30. snosi commit b2858ca0222814c395cf8248db98f3e096d57dc9; Updex v2.1.3 commit 2661e987faac986f2594d1d9bbbadf1bf3053f5b.