Setup Incus
1. Install
Incus can normally be installed from a package, like this:
apt install --yes incus
# or, for debian 12 (bookworm):
# apt install --yes incus/bookworm-backports
We also need to install btrfs-progs
, since we are going to use a
Btrfs storage backend with incus:
apt install --yes btrfs-progs
2. Initialize
Before we can create containers, we need to initialize Incus:
incus admin init
We use the default answers for almost all the questions. The important questions are these:
-
Name of the storage backend to use:
btrfs
We are using btrfs for the storage backend, because we need to install Docker inside the container, and only this filesystem supports it efficiently. Besides, deduplication features of Btrfs make it possible to use less disk space (or to use the disk space more efficiently).
-
Would you like to use an existing empty block device?
yes
We are using the second disk as a storage for the Incus containers.
-
Path to the existing block device:
/dev/nvme1n1
-
What IPv6 address should be used?
none
We are disabling IPv6 for the containers; we don’t need it.
3. Networking
The connection of the Incus containers to the Internet goes through
the host. The bridge network incusbr0
can be thought as a switch,
which provides DHCP service for the containers that are connected to
it. It also works as a gateway for them and provides NAT.
3.1. Fix the firewall
In firewalld
(that is installed on the server), any interface
that is not explicitly added to a zone, is added to the default zone,
which is the zone public
. This zone is meant for the interfaces that
are facing the public internet, so it has restrictions.
The bridge interface of Incus (incusbr0
) is also added by default to
the restricted public
zone. As a result, DHCP requests are blocked,
and the containers cannot get an IP.
Let’s fix this problem by adding the bridge interface to the trusted
zone, where everything is allowed:
firewall-cmd --zone=trusted --list-all
firewall-cmd --zone=trusted \
--add-interface=incusbr0 --permanent
firewall-cmd --reload
firewall-cmd --zone=trusted --list-all
Let’s make sure that forwarding is enabled:
firewall-cmd --permanent --direct --add-rule \
ipv4 filter FORWARD 0 -j ACCEPT
firewall-cmd --reload
firewall-cmd --direct --get-all-rules
3.2. Limit DHCP range
Incus containers usually get an automatic IP from the DHCP that is
provided by incusbr0
. Sometimes we need to set a fixed IP to some
containers. To avoid any possible IP conflicts between the fixed IP
and the automatic IPs issued by DHCP, we should limit the range of the
DHCP IPs, and make sure that the fixed IPs are outside the DHCP range.
Let’s modify the DHCP range on the configuration of incusbr0
:
incus network show incusbr0
incus network get incusbr0 ipv4.address
incus network set incusbr0 \
ipv4.dhcp.ranges 10.148.0.2-10.148.0.200
incus network get incusbr0 ipv4.dhcp.ranges
incus network show incusbr0
4. Access
4.1. From non-root user
To access Incus from a user other than root, add that user to the
group incus
:
adduser user1
adduser user1 incus
In this case user1
can use Incus, but is limited only to his own
workspace (cannot access containers of other users).
If you add user1
to the group incus-admin
instead, it is going
have full access to the Incus server (same access as root
):
adduser user1 incus-admin
4.2. Remotely
We can connect to the Incus server from a local machine, for example a laptop, and manage it remotely.
-
On the local machine, install Incus (but don’t initialize it with
incus admin init
). -
On the server, allow access to Incus on port
8443
:incus config set core.https_address :8443
-
Make sure that the port
8443
on the server is open:firewall-cmd --zone=public --add-port=8443/tcp --permanent firewall-cmd --reload firewall-cmd --zone=public --list-ports
-
On the server, generate a trust token for
client1
:incus config trust add client1
-
On the local machine, add a remote, like this:
incus remote add server1 11.12.13.14
This will prompt you to confirm the remote server fingerprint and then ask you for the token (that was generated above).
11.12.13.14
is the public IP of the server. -
Make the remote named
server1
the default one, and test it:incus remote ls incus remote switch server1 incus remote ls incus ls
Now all the
incus
commands on the local laptop will be executed by default on the remote Incus server. -
On the local machine (laptop) install also
virt-viewer
(orspice-client-gtk
), which is needed to access the VGA console of the virtual machines:apt install virt-viewer
Be aware that without Xpra, the GUI interface displayed by virt-viewer
is not smooth but slow and lagish.
5. Manage Btrfs
Incus uses the second disk (/dev/nvme1n1
) as a storage, which is
formated with Btrfs. This filesystem is the most suitable and
efficient for our needs (because it supports copy-on-write,
deduplication, etc.) However it is a little bit diffrent from the
traditional ext2/ext3/ext4, and we may have some problems if we don’t
know how to manage it properly.
5.1. Disable quotas
Quotas are usually used to restrict the size of home directories of users. In our server we don’t have multiple users, so we don’t need them. Besides, quotas in Btrfs, in the current implementation, may cause high CPU utilization and performance issues, especially when creating or deleting snapshots.
So, let’s make sure to disable them:
# mount the disk used as a storage by incus
mkdir mnt
mount /dev/nvme1n1 mnt
ls mnt/
# disable quotas
btrfs qgroup show mnt/
btrfs quota disable mnt/
btrfs qgroup show mnt/
# unmount
umount mnt
ls mnt/
rmdir mnt/
5.2. Balance
See: Balance Btrfs
5.3. Deduplicate
See: Deduplicate Btrfs