Incus

Related articles
Linux Containers
LXD
Incus
is a manager/hypervisor for containers (via
LXC
) and virtual-machines (via
QEMU
).
It is a fork of
LXD
by the original maintainers. Documentation from the
LXD
wiki page is still largely relevant and encouraged reading.
Installation
Install
the
incus
package, then
enable
the
incus.socket
.
Alternatively, you can
enable/start
the
incus.service
directly, in case you want instances to autostart for example.
To delegate container creation to users,
enable/start
the
incus-user.socket
unit. See
#Accessing Incus as an unprivileged user
for group delegation.
The split package
incus-tools
provides a
few related utilities
.
Migrating from LXD
If you wish to migrate from an existing LXD installation, you should do so at this point, as the migration tool will only run against an empty target Incus server.
After verifying that both the
lxc info
and
incus info
commands are running correctly, read the upstream
documentation
about the process, and afterwards run the migration tool:
# lxd-to-incus
Configuration
Unprivileged containers
Incus launches
unprivileged containers by default
(see
Linux Containers#Privileged or unprivileged
for an explanation of the difference).
For this to work, you need to setup an appropriate range of sub{u,g}ids for the
root
user
[1]
: unlike
e.g.
podman
, Incus uses a daemon that needs to run as root.
[2]
Verify the content of both
/etc/subuid
and
/etc/subgid
, and if needed add a
contiguous range of at least 10M UID/GID
for the root user:
# usermod -v 1000000-1000999999 -w 1000000-1000999999 root
Then
restart
incus
.
For the alternative, see
LXD#Privileged containers
.
Accessing Incus as an unprivileged user
From the
official documentation
:
"Access to Incus is controlled through two groups:
incus
allows basic user access, no configuration and all actions restricted to a per-user project.
incus-admin
allows full control over Incus."
To have a normal user capable of launching and operating instances,
add the user
to the
incus
group.
To give a normal user full control over Incus without having to use
sudo
,
add the user
to
incus-admin
.
Warning
Anyone added to the
incus-admin
group is root equivalent. For more information, see
[3]
and
[4]
.
Initialize Incus config
Before it can be used, Incus' config needs to be initialized:
# incus admin init
Note
This command cannot be successfully run without root access or a user in the
incus-admin
group.
From the
official documentation
:
For simple configurations, you can run this command as a normal user. However, some more advanced operations during the initialization process (for example, joining an existing cluster) require root privileges. In this case, run the command with sudo or as root.
This will start an interactive configuration guide in the terminal, that covers different topics like storages, networks etc. You can find an overview in the official
Getting Started Guide
.
Adding a web UI
The
lxd-ui
browser frontend has been patched to fit Incus. These patches are found in the debian package source.
[5]
To make use of this UI install the
incus-ui
package.
Then set the address and port for the webserver:
$ incus config set core.https_address=127.0.0.1:8443
And
restart
Incus.
Another available option is to run the web server with the following command:
$ incus webui
For this option, see
incus webui
Usage
Overview of commands
You can get an overview of all available commands by typing:
$ incus
Create a container
Container are based on images, that are downloaded from image servers or remote LXD servers.
You can see the list of already added servers with:
$ incus remote list
Note
An image server can be referred to by using the name displayed in the
NAME
column on the left,
e.g.
images
in the following examples.
You can list all images on a server with
incus image list
server-name
:
, for example:
Tip
It is recommended to pipe the output of the following command through a pager like
less
due the high number of images available.
$ incus image list images:
This will show you all images on one of the default servers:
images.linuxcontainers.org
You can also search for images by adding terms like the distribution name:
$ incus image list images:debian
Launch a container with an image from a specific server with:
$ incus launch
servername
:
imagename
For example to create a randomly named container instance from the Ubuntu Noble image from the default server:
$ incus launch images:ubuntu/noble
To specify a name for the instance simply add it afterwards,
e.g.
:
$ incus launch images:archlinux/current/amd64 arch
will create an amd64 Arch container named
arch
.
Arch Linux container configuration
Disabling udev in unprivileged containers
When running unprivileged Arch Linux containers, systemd's udev services will generate numerous "Permission denied" errors during boot and package updates (particularly when
mkinitcpio
runs). This occurs because udev attempts to write to
/sys/devices/*/uevent
files owned by the host.
These errors result from an inappropriate default configuration of Arch container images for unpriviledged operation — the container functions correctly.
As per the
systemd Container Interface
,
systemd-udevd
is not intended to run in unprivileged containers. Mask the udev services inside the container:
# systemctl mask \
  systemd-udevd.service \
  systemd-udevd-control.socket \
  systemd-udevd-kernel.socket \
  systemd-udevd-varlink.socket \
  systemd-udev-trigger.service \
  systemd-udev-load-credentials.service
Note
This is only appropriate for unprivileged containers. Privileged containers with device passthrough may require udev.
After masking, restart the container:
$ incus restart
container_name
Tips and tricks
Access the containers by name on the host
This assumes that you are using the default bridge that it is named
incusbr0
and that you are using
systemd-resolved
.
# systemd-resolve --interface incusbr0 --set-domain '~incus' --set-dns $(incus network get incusbr0 ipv4.address | cut -d / -f 1)
You can now access the containers by name:
$ ping
containername
.incus
To make this change permanent,
edit
the
incus.service
systemd unit to include an
ExecStartPost
directive, which runs the command after launch:
/etc/systemd/system/incus.service.d/access_by_name.conf
[Service]
ExecStartPost=/bin/sh -c 'systemd-resolve --interface incusbr0 --set-domain "~incus" --set-dns $(incus network get incusbr0 ipv4.address | cut -d / -f 1)'
Troubleshooting
Starting a virtual machine fails
If you see the error:
Error: Couldn't find one of the required UEFI firmware files: [{code:OVMF_CODE.4MB.fd vars:OVMF_VARS.4MB.ms.fd} {code:OVMF_CODE.2MB.fd vars:OVMF_VARS.2MB.ms.fd} {code:OVMF_CODE.fd vars:OVMF_VARS.ms.fd} {code:OVMF_CODE.fd vars:qemu.nvram}]
It's because Arch Linux does not distribute secure boot signed ovmf firmware. To boot virtual machines, you need to disable secure boot for the time being:
$ incus launch ubuntu:18.04 test-vm --vm -c security.secureboot=false
This can also be added to the default profile by doing:
$ incus profile set default security.secureboot=false
Network connectivity issues
The official documentation provides instructions on
how to configure your firewall
.
Tip
Multiple programs may influence the
nftables
on a single system beyond dedicated firewalls, including VPNs and other virtualization software. Run
nft list ruleset
to show all currently active rules.
Incus creates and manages its own network interfaces, and
NetworkManager
may interfere in some cases. It may be a good idea to add any entry to ignore
lxcbr*
devices using the instructions in
NetworkManager#Ignore specific devices
.
Docker
's default configuration breaks networking in Incus. Consult the
official documentation
if Docker and Incus need to run on the same machine.
Incus does not respect Shell's environment proxy variables
Examples are
incus launch
or
incus image
commands not using value of
*_proxy
/
*_PROXY
variables
when downloading images.
Incus implements a server-client paradigm. It simply means that operations are done by
incusd
acting as the
Incus server
— usually running in the background, unless invoked from an interactive shell. And
incus
commandline interface is used to communicate with Incus server acting as the
Incus client
.
That makes
incusd
, typically started as a service, not inheriting shell's environment variables of the client. But respecting variables of the environment that it's invoked from, instead.
[6]
In Arch Linux, Incus server is started by systemd.
There can be many workarounds to this difficulty, following exist some examples. See Incus's
issue#574
for more information.
Temporary
Import Shell variables to systemd's environment
First,
export
*_PROXY
variables:
$ export
ALL
_PROXY="socks://
proxy_server_address
:
port
/"
Import them to systemd's environment:
# systemctl import-environment
ALL
_PROXY
Re/start
incus.service
unit.
Tip
Use
systemctl unset-environment
command to unset a variable and
restart
the service.
Persistent
Edit incus service unit
If you want Incus daemon to always start with some static environment variables, like
*_proxy
, you can use
Environment
directive of
systemd
.
systemctl set-property
command cannot manipulate
Environment
directive.
Edit
incus.service
and add
Environment
key with appropriate
variable=value
pair. For example:
/etc/systemd/system/incus.service.d/environment.conf
[Service]
Environment=
ALL
_PROXY="socks://
proxy_server_address
:
port
/"
Use Incus core.proxy options
One can make Incus server use a desired proxy with
configuring
Incus's server with
core.proxy
options. For instance:
# incus config set core.proxy_http "
proxy_address
:
proxy_port
"
Note
core.proxy
options have global scopes. I.e. they apply to cluster members, immediately.
Uninstall
Stop
and disable the services. Then
uninstall
the
incus
package.
If you want to remove all data:
# rm -r /var/lib/incus
If you used any of the example networking configuration, you should remove those as well.
See also
The official Incus homepage
Official documentation
Getting Started Guide
Official Forum
The Incus GitHub repository