Linux Setup Guide - mensfeld/code-on-incus GitHub Wiki

COI's install script (install.sh) works across Linux distributions, but Incus itself requires some distro-specific setup. This guide covers what you need beyond the standard install.

Universal Steps

These apply to all distributions:

# 1. Install COI
curl -fsSL https://raw.githubusercontent.com/mensfeld/code-on-incus/master/install.sh | bash

# 2. Build the COI image
coi build

# 3. Start coding
coi shell

The install script handles Incus initialization, idmap configuration, firewalld setup, and ZFS storage automatically. The sections below cover manual setup for cases where the script can't auto-detect your environment.

Arch Linux / CachyOS / Manjaro

Incus is available in the official Arch repositories.

Install Incus

sudo pacman -S incus

Enable the Service

sudo systemctl enable --now incus.service

Add User to Groups

sudo usermod -aG incus-admin $USER
# Log out and back in for group changes to take effect

Note: Some Arch-based distributions may also require the incus group (in addition to incus-admin). If you get permission errors, try: sudo usermod -aG incus incus-admin $USER.

Initialize Incus

sudo incus admin init --auto

This creates the default bridge network (incusbr0), storage pool, and profile devices. If you need more control:

# Manual setup (equivalent to --auto)
incus network create incusbr0 ipv4.address=auto ipv4.nat=true ipv6.address=none
incus storage create default dir
incus profile device add default root disk path=/ pool=default
incus profile device add default eth0 nic name=eth0 network=incusbr0

Fix Subordinate UID/GID Mapping

Arch does not ship with subordinate UID/GID ranges for root by default. Without this, Incus cannot create unprivileged containers and you'll see:

"System doesn't have a functional idmap setup"

# Add subordinate ranges for root
echo "root:1000000:1000000000" | sudo tee -a /etc/subuid
echo "root:1000000:1000000000" | sudo tee -a /etc/subgid

# Restart Incus to pick up the changes
sudo systemctl restart incus.service

The COI install script detects and offers to fix this automatically.

Enable Firewalld

Firewalld is required for COI's network isolation modes (restricted, allowlist). Without it, only mode = "open" works.

sudo pacman -S firewalld
sudo systemctl enable --now firewalld
sudo firewall-cmd --permanent --add-masquerade
sudo firewall-cmd --reload

If your bridge isn't getting trusted zone treatment (containers can't get IP addresses):

sudo firewall-cmd --zone=trusted --add-interface=incusbr0 --permanent
sudo firewall-cmd --reload

Verify Setup

coi health

Fedora / RHEL / CentOS Stream

Install Incus

Incus is available via the Zabbly repository on RHEL-based systems:

sudo dnf install incus
sudo systemctl enable --now incus.service
sudo usermod -aG incus-admin $USER
sudo incus admin init --auto

Firewalld

Fedora ships with firewalld enabled by default. Enable masquerade for container internet access:

sudo firewall-cmd --permanent --add-masquerade
sudo firewall-cmd --zone=trusted --add-interface=incusbr0 --permanent
sudo firewall-cmd --reload

Idmap

Fedora typically ships with correct /etc/subuid and /etc/subgid entries. Verify:

grep root /etc/subuid /etc/subgid

If empty, add the ranges as shown in the Arch section above.

openSUSE

sudo zypper install incus
sudo systemctl enable --now incus.service
sudo usermod -aG incus-admin $USER
sudo incus admin init --auto

Firewalld is the default firewall on openSUSE. Enable masquerade:

sudo firewall-cmd --permanent --add-masquerade
sudo firewall-cmd --zone=trusted --add-interface=incusbr0 --permanent
sudo firewall-cmd --reload

Ubuntu / Debian

Ubuntu and Debian are the primary target for COI. The install script handles everything automatically.

Note: Ubuntu ships Incus 6.0.x in its main repository, which may lack required idmapping support. If you see idmap errors, install Incus >= 6.1 from the Zabbly repository.

sudo apt install -y incus
sudo systemctl enable --now incus.service
sudo usermod -aG incus-admin $USER
sudo incus admin init --auto

The install script automatically detects ufw (Ubuntu's default firewall) and offers to replace it with firewalld, which COI requires for network isolation.

Common Issues Across Distros

"System doesn't have a functional idmap setup"

Add subordinate UID/GID ranges for root and restart Incus:

echo "root:1000000:1000000000" | sudo tee -a /etc/subuid
echo "root:1000000:1000000000" | sudo tee -a /etc/subgid
sudo systemctl restart incus.service

Containers Can't Get IP Addresses

Ensure the Incus bridge is in the firewalld trusted zone:

sudo firewall-cmd --zone=trusted --add-interface=incusbr0 --permanent
sudo firewall-cmd --reload

"firewalld is not available or not running"

Either install and enable firewalld (see distro-specific sections above) or use open network mode:

# ~/.coi/config.toml
[network]
mode = "open"

Verify Everything

coi health --verbose

This checks Incus setup, permissions, security posture, network configuration, and monitoring prerequisites.