incus-contrib/incusos/README.md

11 KiB

IncusOS Tools

Scripts for building IncusOS installation media and seed configurations.

Overview

Script Purpose
incusos-iso Build customized IncusOS ISO/IMG images using the flasher-tool
incusos-seed Generate seed archives (tar or FAT) for installation customization

Both scripts support automatic client certificate injection from the local Incus installation, so the freshly installed system is immediately manageable.

Prerequisites

Required:

  • flasher-tool -- the official IncusOS image builder (used by incusos-iso)

    # Requires Go 1.22+
    go install github.com/lxc/incus-os/incus-osd/cmd/flasher-tool@latest
    export PATH="${GOPATH:-$HOME/go}/bin:$PATH"
    

    The incusos-iso script will offer to install it automatically if Go is available.

Recommended:

  • Incus client -- for automatic client certificate detection. Any version works (certificates are read from disk), but 6.3+ has the most complete CLI. See notes/incus-version-compatibility.md for install instructions per platform.
    Platform Install command Notes
    macOS brew install incus Client only (no daemon on macOS)
    Debian/Ubuntu apt install incus-client Use Zabbly repo for latest
    Arch Linux pacman -S incus Full daemon+client (no client-only split)
    Any (source) go install github.com/lxc/incus/v6/cmd/incus@latest Requires Go 1.22+

Optional:

  • mtools / dosfstools -- for creating FAT seed images (incusos-seed --format fat)
  • jq or python3 -- for parsing the CDN index (cross-architecture builds)
  • curl -- for downloading images from the CDN

incusos-iso

Wrapper around the official flasher-tool that adds:

  • Cross-architecture builds -- build aarch64 images on x86_64 and vice versa
  • Automatic seed generation -- no need to manually create seed files
  • Client certificate injection -- auto-detects your local Incus certificate
  • Batch mode -- generate all common ISO variants in one command
  • Sensible defaults -- minimal flags needed for common use cases

Quick Start

# Build a default IncusOS ISO for the current architecture
./incusos-iso

# Incus with default configuration (ZFS pool, bridge, port 8443)
./incusos-iso --defaults

# Operations Center for aarch64
./incusos-iso --arch aarch64 --app operations-center --defaults

# Build a USB image instead of ISO
./incusos-iso --format img --defaults

# Generate all variants (2 arches x 2 apps x 2 default modes = 8 images)
./incusos-iso --batch

# Preview what would be built
./incusos-iso --batch --dry-run

Options Reference

-a, --arch ARCH          x86_64 or aarch64 (default: auto-detect)
-A, --app APP            incus or operations-center (default: incus)
-d, --defaults           Apply default config (ZFS pool, bridge, port 8443)
-c, --cert FILE          Client certificate PEM file (default: auto-detect)
    --no-cert            Skip certificate injection
-F, --format FORMAT      iso or img (default: iso)
-o, --output FILE        Output filename (default: auto-generated)
-C, --channel CHANNEL    stable or testing (default: stable)
-s, --seed FILE          Use pre-built seed tar (skip seed generation)
-i, --image FILE         Use local base image (skip CDN download)
-b, --batch              Generate all common variants
    --batch-arches LIST  Architectures for batch (default: x86_64,aarch64)
    --batch-apps LIST    Apps for batch (default: incus,operations-center)
    --output-dir DIR     Output directory for batch (default: .)
    --disk-target ID     Target disk pattern (e.g. "virtio-*")
    --force-install      Overwrite existing installation
    --force-reboot       Auto-reboot after installation
    --missing-tpm        Allow install without TPM 2.0
    --missing-secureboot Allow install without Secure Boot
    --hostname NAME      Set system hostname
    --dry-run            Show what would happen
-q, --quiet              Suppress info output
-h, --help               Full help text
-V, --version            Show version

Output Naming Convention

Auto-generated filenames follow the pattern:

incusos-{app}-{defaults|bare}-{arch}.{iso|img}

Examples:

  • incusos-incus-defaults-x86_64.iso
  • incusos-ops-center-bare-aarch64.iso
  • incusos-incus-defaults-x86_64.img

Batch Mode Matrix

With --batch, the following variants are generated:

# Architecture Application Defaults Filename
1 x86_64 Incus yes incusos-incus-defaults-x86_64.iso
2 x86_64 Incus no incusos-incus-bare-x86_64.iso
3 x86_64 Ops Center yes incusos-ops-center-defaults-x86_64.iso
4 x86_64 Ops Center no incusos-ops-center-bare-x86_64.iso
5 aarch64 Incus yes incusos-incus-defaults-aarch64.iso
6 aarch64 Incus no incusos-incus-bare-aarch64.iso
7 aarch64 Ops Center yes incusos-ops-center-defaults-aarch64.iso
8 aarch64 Ops Center no incusos-ops-center-bare-aarch64.iso

Customize with --batch-arches and --batch-apps:

# Only x86_64 Incus variants
./incusos-iso --batch --batch-arches x86_64 --batch-apps incus

incusos-seed

Generates IncusOS seed archives containing the YAML configuration files that customize an IncusOS installation. Output can be:

  • tar archive (default) -- for use with flasher-tool --seed
  • FAT image -- for use as an external SEED_DATA partition/disk

Quick Start

# Standalone Incus with defaults and auto-detected certificate
./incusos-seed --defaults

# Operations Center seed
./incusos-seed --app operations-center --defaults --cert ~/.config/incus/client.crt

# Cluster node (no defaults) targeting virtio disks
./incusos-seed --disk-target 'virtio-*' --force-install --force-reboot

# FAT image for external boot media
./incusos-seed --format fat --defaults --output seed.img

# Preview generated YAML without creating files
./incusos-seed --defaults --dry-run

Options Reference

-A, --app APP            incus or operations-center (default: incus)
-d, --defaults           Apply default configuration
-c, --cert FILE          Client certificate PEM file (default: auto-detect)
    --no-cert            Skip certificate injection
-o, --output FILE        Output file (default: incusos-seed.tar)
-f, --format FORMAT      tar or fat (default: tar)
    --fat-size SIZE      FAT image size in MiB (default: 10)
    --disk-target ID     Target disk pattern
    --force-install      Overwrite existing installation
    --force-reboot       Auto-reboot after installation
    --missing-tpm        Allow install without TPM 2.0
    --missing-secureboot Allow install without Secure Boot
    --hostname NAME      Set hostname
    --domain NAME        Set domain
    --dns SERVERS        Comma-separated DNS servers
    --channel CHANNEL    stable or testing (default: stable)
    --auto-reboot        Auto-reboot for updates
    --dry-run            Preview YAML output
-q, --quiet              Suppress info output
-h, --help               Full help text
-V, --version            Show version

Seed Files Reference

The following YAML files are generated inside the archive:

File Always Description
install.yaml yes Installation target, security, reboot settings
applications.yaml yes Application selection
incus.yaml when app=incus Incus preseed (defaults, certificates)
operations-center.yaml when app=ops-center Operations Center config
network.yaml when network opts set Hostname, DNS, static IP
update.yaml when non-default Update channel, auto-reboot

Using the FAT Image (SEED_DATA)

The FAT output format creates a small disk image labeled SEED_DATA that can be attached to a VM as a secondary disk. IncusOS detects this label at boot and reads the seed configuration from it.

This is useful for the "pristine image" workflow:

  1. Download one uncustomized IncusOS ISO
  2. Generate per-node seed images with incusos-seed --format fat
  3. Boot each VM with both the ISO and the node-specific seed image
# Generate seeds for three cluster nodes
for i in 1 2 3; do
    ./incusos-seed --format fat \
        --hostname "node-${i}" \
        --disk-target 'virtio-*' \
        --force-install \
        --output "seed-node-${i}.img"
done

Client Certificate Auto-Detection

Both scripts automatically look for a client certificate in this order:

  1. ~/.config/incus/client.crt (on-disk, works with all Incus versions)
  2. ~/snap/incus/common/config/client.crt (snap installations)
  3. ~/.config/lxc/client.crt (legacy LXC path)
  4. incus remote get-client-certificate (CLI fallback, requires Incus >= 6.3)

The file-based detection is preferred because incus remote get-client-certificate was added in Incus 6.3 and is not available in the 6.0 LTS shipped by Debian stable.

If no certificate exists yet, run incus remote list to trigger auto-generation of a client keypair at ~/.config/incus/client.{crt,key}.

Override with --cert FILE or disable with --no-cert.

Incus Version Compatibility

Feature 6.0 LTS (Debian stable) 6.3+ (Zabbly, Homebrew, Arch)
Certificate on disk ~/.config/incus/client.crt ~/.config/incus/client.crt
get-client-certificate CLI not available available
incus admin os commands not available available
Script cert auto-detection works (reads file directly) works (reads file directly)

These scripts work with any Incus version because they read the certificate file from disk rather than relying on newer CLI commands.

For full installation instructions per platform, see notes/incus-version-compatibility.md.

After Installation

With an injected certificate, the remote is already trusted:

incus remote add my-server <ip-address>
incus remote list

For web UI access, export a PKCS#12 bundle and import it into your browser:

openssl pkcs12 -export \
    -inkey ~/.config/incus/client.key \
    -in ~/.config/incus/client.crt \
    -out ~/.config/incus/client.pfx

Examples

See the examples/ directory for sample seed configurations:

Security Notes

  • TPM 2.0 and Secure Boot are required by default. Use --missing-tpm and --missing-secureboot only for lab environments or VMs that lack these features.
  • All storage pools are automatically encrypted by IncusOS.
  • Retrieve encryption recovery keys after installation with: incus admin os system security show
  • Keep recovery keys safe -- they are needed if TPM state changes.