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:btrfsWe 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?yesWe 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?noneWe 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
8443on 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.14This will prompt you to confirm the remote server fingerprint and then ask you for the token (that was generated above).
11.12.13.14is the public IP of the server. -
Make the remote named
server1the default one, and test it:incus remote ls incus remote switch server1 incus remote ls incus lsNow all the
incuscommands 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-viewerBe aware that without Xpra, the GUI interface displayed by virt-vieweris 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