Incus - Ubuntu 26.04 Installation
Incus is a modern, open-source system container and virtual machine manager. It serves as a community-driven fork of Canonical’s LXD, providing a unified experience for running and managing full Linux systems inside containers or virtual machines. It is designed to be secure, scalable, and suitable for both development and production environments, including homelabs and data centers.
What is new in Incus 7.0 LTS
Incus 7.0 LTS is the second long-term support release after the 6.0 LTS line. A few items in the release notes affect this guide directly:
- CGroup v1 support removed. The host kernel must be running CGroup v2 (the default on every Ubuntu LTS shipped after 22.04 and on 22.04 with a recent kernel).
- xtables removed. Incus 7.0 uses nftables only. Any custom iptables rules around the bridge need to be ported.
- Built-in S3 endpoint. The MinIO dependency is gone. Object storage on a custom volume is now a native daemon feature.
- NBD-based backup API and dirty bitmap support. Faster incremental backups for instances with large block volumes.
- Higher minimum kernel. 6.0 LTS supported older kernels. 7.0 LTS expects the kernel features that ship in Ubuntu 22.04’s HWE stack and newer.
Prerequisites
- A fresh or close-to-fresh Ubuntu host. Tested on Ubuntu 26.04 (Resolute) and 24.04 LTS (Noble).
- Root or sudo access.
- 2 GB of RAM minimum for the host. Containers add as little as 20 MB each; full VMs add 256 MB and up.
- 10 GB of free disk on the partition that holds /var/lib/incus. The default dir backend writes there.
- Outbound HTTPS to pkgs.zabbly.com and the public images.linuxcontainers.org mirror.
If the host will also run KVM virtual machines through Incus, the CPU needs hardware virtualisation. Confirm with this one-liner, which prints vmx on Intel or svm on AMD:
1
grep -oE '(vmx|svm)' /proc/cpuinfo | sort -u
You should get either VMX or SVM as the output depending on your chipset. An empty output means containers will work but incus launch –vm will fail. Enable VT-x or AMD-V in the BIOS, or, when the host is itself a Proxmox VM, set the CPU type to host.
Step 1: Add the Zabbly Stable Repository
Zabbly is the upstream package repository maintained by Stéphane Graber, the Incus lead. It ships current Incus on Ubuntu 22.04, 24.04, and 26.04 with the same package names, and it carries 7.0 LTS as the current stable branch. The Ubuntu archive carries Incus too (on 24.04 and 26.04 only) but holds the older 6.0 LTS line and does not ship the incus-ui-canonical web UI. Zabbly is the recommended path on all three releases.
Install the bootstrap packages and create the keyrings directory:
1
2
3
sudo apt update
sudo apt install -y curl gpg ca-certificates
sudo mkdir -p /etc/apt/keyrings
Download the Zabbly signing key into /etc/apt/keyrings/:
1
sudo curl -fsSL https://pkgs.zabbly.com/key.asc -o /etc/apt/keyrings/zabbly.asc
Confirm the fingerprint matches 4EFC 5906 96CB 15B8 7C73 A3AD 82CC 8797 C838 DCFD. This is the value Zabbly publishes on the repository README:
1
gpg --show-keys --with-colons /etc/apt/keyrings/zabbly.asc | awk -F: '/^fpr:/{print $10; exit}'
Write the Deb822-format sources file. The $VERSION_CODENAME shell expansion picks jammy on 22.04, noble on 24.04, or resolute on 26.04 automatically, so the same block works on all three:
1
2
3
4
5
6
7
8
9
sudo sh -c 'cat > /etc/apt/sources.list.d/zabbly-incus-stable.sources <<EOF
Enabled: yes
Types: deb
URIs: https://pkgs.zabbly.com/incus/stable
Suites: $(. /etc/os-release && echo ${VERSION_CODENAME})
Components: main
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/zabbly.asc
EOF'
Refresh the package cache and check that Incus 7.0 is now the install candidate:
1
2
sudo apt update
apt-cache policy incus | head -8
On Ubuntu 26.04 the candidate looks like 1:7.2-ubuntu26.04-202607101631; on 24.04 it is 1:7.2-ubuntu24.04-…; on 22.04 1:7.2-ubuntu22.04-… Same upstream Incus 7.0 across all three.
Step 2: Install Incus and the CLI Tools
Install the daemon, the canonical web UI, the extras pack that ships lxd-to-incus, and the full QEMU stack for virtual machine support:
1
sudo apt install incus incus-extra qemu-system -y
Start the Incus service:
1
sudo systemctl enable --now incus.service
Confirm both the client and the server report 7.0.0. The service should show active (running) with incusd as the main process. This is what a clean install looks like on Ubuntu 26.04:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
user@incus:~$ incus version
Client version: 7.2
Server version: 7.2
user@incus:~$ systemctl status incus.service --no-pager
● incus.service - Incus - Daemon
Loaded: loaded (/usr/lib/systemd/system/incus.service; indirect; preset: enabled)
Active: active (running) since Sat 2026-07-18 11:20:47 PDT; 7h ago
Invocation: 49f0c11f47c942ca98079f962b559b3a
TriggeredBy: ● incus.socket
Main PID: 1521 (incusd)
Tasks: 69
Memory: 3.4G (peak: 3.4G)
CPU: 33min 38.444s
CGroup: /system.slice/incus.service
├─1521 incusd --group incus-admin --logfile /var/log/incus/incusd.log
└─1764 /opt/incus/bin/qemu-system-x86_64 -S -name homeassistant -uuid 19b50376-f425-4526-be9d-612c5b549557 -daemonize -cpu host,hv_passthroug…
Add your shell user to the incus-admin group so you can drive the daemon without sudo every time:
1
2
sudo usermod -aG incus-admin [YourUser]
newgrp incus-admin
Note: If you are on Ubuntu 26.04, the newgrp command is not installed by default. You need to install the util-linux-extra package:
1 sudo apt install util-linux-extra -y
Install ZFS-Utilities and BTRFS for the Storage Pools and LZ4 compression for Backups
1
sudo apt install zfsutils-linux btrfs-progs lz4 -y
Step 3: Setup the Network Interface
Setup a static IP and Bridge interface for Incus
Display your interface and current IP
1
2
3
4
# ip -br -c a
lo UNKNOWN 127.0.0.1/8 ::1/128
enp0s31f6 UP 192.168.1.10/24
Make note of the interface name next to the servers IP address. In this case enp0s31f6
Edit the IP configuration file:
1
sudo nano /etc/netplan/00-installer-config.yaml
Replace with this (modify to suite your settings)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
network:
ethernets:
enp0s31f6: # <-- Your Servers Interface: must match the name below
dhcp4: false
dhcp6: false
version: 2
bridges:
bridge0:
interfaces: [enp0s31f6] # <-- Your Servers Interface: must match the name above
addresses: [192.168.x.x/24] # <-- Set this to the IP you want for this machine
routes:
- to: default
via: 192.168.x.x # <-- This is your router gateway address
nameservers:
addresses:
- 192.168.x.x # <-- This is your DNS server's IP
search:
- home.local
parameters:
stp: true
forward-delay: 4
dhcp4: no
Verify the interface configuration:
1
sudo netplan try
Response:
bridge0: reverting custom parameters for bridges and bonds is not supported Please carefully review the configuration and use ‘netplan apply’ directly.
Apply the interface configuration:
1
sudo netplan apply
Step 4: Initialize Incus
Incus needs one initialization pass to lay down a default storage pool, a managed bridge, a default profile, etc.
1
sudo incus admin init
- Would you like to use clustering? (yes/no) [default=no]: [Enter]
- Do you want to configure a new storage pool? (yes/no) [default=yes]: [Enter]
- Name of the new storage pool [default=default]: [Enter]
- Name of the storage backend to use (lvm, truenas, zfs, btrfs, dir) [default=zfs]: btrfs
- Create a new BTRFS pool? (yes/no) [default=yes]: [Enter]
- Would you like to use an existing empty block device (e.g. a disk or partition)? (yes/no) [default=no]: [Enter]
- Size in GiB of the new loop device (1GiB minimum) [default=30GiB]: 150GiB ## Set to whatever size you need
- Would you like to create a new local network bridge? (yes/no) [default=yes]: no
- Would you like to use an existing bridge or host interface? (yes/no) [default=no]: yes
- Name of the existing bridge or host interface: bridge0
- Would you like the server to be available over the network? (yes/no) [default=no]: yes
- Address to bind to (not including port) [default=all]: [Enter]
- Port to bind to [default=8443]: [Enter]
- Would you like stale cached images to be updated automatically? (yes/no) [default=yes]: [Enter]
- Would you like a YAML “init” preseed to be printed? (yes/no) [default=no]: [Enter]
Verify the default resources came up:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
user@incus:~$ incus storage list
+---------+--------+-------------+---------+---------+
| NAME | DRIVER | DESCRIPTION | USED BY | STATE |
+---------+--------+-------------+---------+---------+
| default | btrfs | | 1 | CREATED |
+---------+--------+-------------+---------+---------+
user@incus:~$ incus network list
+-----------+----------+---------+------+------+-------------+---------+-------+
| NAME | TYPE | MANAGED | IPV4 | IPV6 | DESCRIPTION | USED BY | STATE |
+-----------+----------+---------+------+------+-------------+---------+-------+
| bridge0 | bridge | NO | | | | 1 | |
+-----------+----------+---------+------+------+-------------+---------+-------+
| enp0s31f6 | physical | NO | | | | 0 | |
+-----------+----------+---------+------+------+-------------+---------+-------+
| lo | loopback | NO | | | | 0 | |
+-----------+----------+---------+------+------+-------------+---------+-------+
Default Incus storage pool and bridge0 bridge after incus admin init. The bridge picks a free 10.0.0.0/8 subnet for IPv4 and a ULA for IPv6, runs its own DHCP via dnsmasq, and NATs out through the host. New instances attach to it automatically through the default profile.
Create Bridge Profile
1
incus profile create bridgeprofile
Add devices and connection details to the profile which will be used by any containers it’s applied to:
1
incus profile device add bridgeprofile eth0 nic nictype=bridged parent=bridge0
Uninstall
To remove Incus, stop and delete every instance, then purge the packages and the data directory.
CAUTION: This is destructive and irreversible
1 2 3 4 5 6 7 8 9 for i in $(incus list -c n --format csv); do incus stop "$i" --force 2>/dev/null incus delete "$i" done sudo apt purge -y incus incus-base incus-client incus-extra incus-ui-canonical sudo rm -rf /var/lib/incus /etc/apt/sources.list.d/zabbly-incus-stable.sources sudo rm -f /etc/apt/keyrings/zabbly.asc sudo apt update sudo apt autoremove
