Incus

Table of Contents
├── 1. Installation
│ ├── Arch Linux
│ ├── Alpine Linux
│ ├── Ubuntu / Debian
│ └── Verify Installation
└── 4. Images
├── Default Remotes
├── Image Properties

Incus is a next-generation system container and virtual machine manager. It manages LXC containers and QEMU virtual machines through a unified command-line interface and REST API. Instances are persistent, full-system environments with their own init system, networking, and storage, distinct from the application containers that Docker and Podman manage.

Incus originates from a community fork of LXD. In 2023, Canonical transferred LXD development exclusively to its own commercial organisation and removed the project from Linux Containers governance. The Linux Containers community forked the codebase as Incus under the LXC Project umbrella. Incus is FOSS, independently governed, and carries no commercial licensing terms. It represents the correct choice for operators who require system container infrastructure without dependency on Canonical's commercial roadmap.


🔗1. Installation

🔗Arch Linux

Incus is available in the AUR. Install with an AUR helper:

yay -S incus

Or build manually:

git clone [https://aur.archlinux.org/incus.git](https://aur.archlinux.org/incus.git)
cd incus
makepkg -si

Enable and start the service:

sudo systemctl enable --now incus
sudo systemctl enable --now incus-user

Add your user to the incus-admin group:

sudo usermod -aG incus-admin $USER

Log out and back in for group membership to take effect.

🔗Alpine Linux

apk add incus incus-client
rc-update add incusd
rc-service incusd start

🔗Ubuntu / Debian

Canonical's repositories ship LXD, the proprietary fork. Incus requires the Zabbly repository:

curl -fsSL [https://pkgs.zabbly.com/key.asc](https://pkgs.zabbly.com/key.asc) | sudo gpg --dearmor -o /etc/apt/keyrings/zabbly.gpg
echo "deb [signed-by=/etc/apt/keyrings/zabbly.gpg] [https://pkgs.zabbly.com/incus/stable](https://pkgs.zabbly.com/incus/stable) $(lsb_release -cs) main" \
  | sudo tee /etc/apt/sources.list.d/zabbly-incus-stable.list
sudo apt update
sudo apt install incus
sudo adduser $USER incus-admin

🔗Verify Installation

incus --version
incus info

🔗2. Initial Configuration

Run the interactive initialisation on first use:

sudo incus admin init

The wizard configures storage pools, networking, clustering, and remote access. For a minimal single-node setup, the following answers produce a functional environment:

QuestionRecommended Answer
Clusteringno
Existing storage poolno
Storage backenddir (safe default) or zfs (recommended)
Remote access over networkno (unless required)
Automatic image updatesyes
YAML output of configoptional

For production use, ZFS provides snapshots, clones, and copy-on-write storage that the dir backend does not. Install ZFS before running incus admin init:

# Arch Linux
sudo pacman -S zfs-utils
sudo modprobe zfs

🔗3. Core Architecture

ComponentDefinition
InstanceA running container or virtual machine managed by Incus.
ImageA compressed file-system used as the base for new instances.
ProfileA named set of configuration options applied to instances. Multiple profiles stack.
Storage poolA named storage backend (zfs, btrfs, lvm, dir) hosting instance disks and images.
NetworkA managed bridge, VLAN, OVN overlay, or physical interface attached to instances.
ProjectA namespace isolating instances, images, profiles, and storage. Useful for multi-tenant environments.
RemoteA reference to another Incus server or a public image registry.

🔗4. Images

Incus instances launch from images. Images are distributed via remotes. The default remotes point to Linux Containers image servers.

🔗Default Remotes

incus remote list
Default RemoteContent
images:Community images (Alpine, Arch, Ubuntu, Rocky, Debian, and many others)
ubuntu:Official Ubuntu images
ubuntu-daily:Ubuntu daily builds

🔗Searching for Images

incus image list images:
incus image list images: alpine
incus image list images: arch
incus image list images: | grep -i rocky

🔗Image Properties

FieldMeaning
ALIASFriendly name for the image
FINGERPRINTSHA-256 hash identifying the image uniquely
PUBLICWhether the image is publicly accessible
DESCRIPTIONDistribution, version, and architecture
TYPECONTAINER or VIRTUAL-MACHINE
SIZECompressed image size
UPLOAD DATEWhen the image was cached locally

🔗Managing Local Images

CommandAction
incus image listList locally cached images
incus image info {alias}Show image metadata
incus image delete {fingerprint}Remove local image
incus image export {alias} {path}Export image to file
incus image import {path} --alias {name}Import image from file
incus image copy images:{alias} local: --alias {name}Copy remote image to local cache
incus image refreshUpdate cached images

🔗Publishing Instances as Images

Use incus publish to save a stopped container or virtual machine as a reusable image in your local image list. You can also publish from a snapshot.

CommandAction
incus publish {instance} --alias {alias}Create image from instance, assign alias
incus publish {instance}/{snapshot} --alias {alias}Create image from a snapshot
incus publish {instance} --public --alias {alias}Publish as a public image (visible to others)
incus publish {instance} --expiry 30dSet image to expire after 30 days
incus publish {instance} --reuseReplace existing image with same alias
# Publish a stopped container called "web-backup" as "my-website:1.0"
incus publish web-backup --alias my-website:1.0

# Publish from a snapshot
incus publish web-backup/snap0 --alias my-website:snap0

# List your published images
incus image list

Note: The source instance should be stopped unless you use --force, but forcing may produce inconsistent file-systems.

🔗Managing Image Aliases

Aliases give human-friendly names to image fingerprints. Use them to reference images in incus launch, incus copy, etc. without typing the full hash.

CommandAction
incus image alias listList all aliases on the local server
incus image alias list images:List aliases on a remote (e.g., images:)
incus image alias create {alias} {fingerprint}Assign an alias to an existing image
incus image alias delete {alias}Remove an alias
incus image alias rename {old} {new}Rename an existing alias
# List aliases you have defined locally
incus image alias list

# Create an alias "ubuntu-jammy" for image with fingerprint abc123...
incus image alias create ubuntu-jammy abc123...

# Delete an alias
incus image alias delete my-old-alias

# Rename an alias
incus image alias rename my-website my-website:stable

You can also assign aliases during incus publish, incus copy, or incus image import using the --alias flag:

incus publish my-container --alias my-container:v1
incus image copy local:my-container:v1 images: --alias public-container

🔗Building Custom Images

Incus accepts tarballs in its image format. The minimal structure requires a metadata.yaml and a root file-system tarball.

# BUILD A MINIMAL ALPINE IMAGE FOR IMPORT
mkdir -p rootfs
# populate rootfs with a base alpine system, then archive it
tar -czf rootfs.tar.gz -C rootfs .

# create metadata file
cat > metadata.yaml <<EOF
architecture: x86_64
creation_date: $(date +%s)
properties:
  description: Custom Alpine minimal
  os: Alpine
  release: edge
EOF

# bundle metadata and rootfs into an incus image tarball
tar -czf custom-alpine.tar.gz metadata.yaml rootfs.tar.gz

# import image into local cache with alias
incus image import custom-alpine.tar.gz --alias custom-alpine