Incus Setup

Incus ist ein schlankes und leistungsstarkes Tool um Linux Container und Virtuelle Maschinen zu verwalten. Man kann es sowohl auf dem lokalen System für kleine Tests bis hin zu großen Clustern mit vielen Containern/VMs nutzen. Es gibt auch eine Weboberfläche, die ich selbst aber noch nie genutzt habe, viel praktischer finde ich die intuitive Bedienung über die Kommandozeile.

Der Artikel soll zeigen wie einfach man sich auf einen Debian Trixie (13) System eine lokale “Cloud” aufbauen kann.

Installation

Unter Debian Trixie (13) ist Incus schnell mit dem Paket incus installiert.

1sudo apt install incus

Für das initiale Setup erstellt man sich am besten eine preseed.yml.

 1cluster: null
 2config:
 3  images.auto_update_interval: '0'
 4networks:
 5  - name: br1
 6    project: default
 7    type: bridge
 8    config:
 9      dns.domain: local.example.net
10      dns.mode: managed
11projects:
12  - name: user-1000
13    config:
14      restricted.devices.disk.paths: ''
15      restricted.networks.access: br1
16storage_pools:
17  - name: default
18    description: ''
19    driver: dir
20    config: {}

Es soll kein Cluster werden sondern nur eine single Installation. Es wird eine Netzwerk bridge br1 angelegt, eine eigene DNS Domain und Incus gesagt es soll diese Domain über Dnsmasq verwalten.

Mit dem Project user-1000 (dem eigenen User mit der ID 1000) die Berechtigung lokale Verzeichnisse in einen Container einzuhängen und das Netzwerk br1 zu nutzen.

Wie folgt die Konfiguration einlesen.

1cat preseed.yml | sudo incus admin init --preseed

Den eigenen User (username) noch in die Gruppe incus mit aufnehmen.

1sudo adduser username incus

Nun für den eigenen User das default profile anpassen. Dafür am einfachsten das Profil im Editor mit folgendem Befehl öffnen.

1incus profile edit default

Im Profil dann die devices anpassen.

 1config: {}
 2description: Default Incus profile for project user-1000
 3devices:
 4  eth0:
 5    name: eth0
 6    network: br1
 7    type: nic
 8  root:
 9    path: /
10    pool: default
11    type: disk
12    size: 10GB
13name: default
14used_by: []
15project: user-1000

Das Netzwerkinterface eth0 der Container/VMs wird an die Bridge br1 gebunden. Die Daten der Instance legen wir im lokalen Dateisystem ab, hier kann man auch noch mit size die Größe angeben (default 10GB).

Mit folgendem Befehl startet man nun einen Container

1incus launch images:debian/13 test01

Oder eine Virtuelle Maschine mit

1incus launch images:debian/13 test02

Unabhängig ob man einen Container oder eine VM hat kann man mit folgenden Befehl einfach eine root Shell öffnen

1incus exec test01 

Verfügbare Images lassen sich mit folgendem Befehl abfragen.

1incus image list images: | more

Systemd-Resolved

Systemd-Resolved nutzen für lokale Namensauflösung der Incus Instancen. Wenn nicht bereits installiert dann das Paket wie folgt installieren.

1sudo apt install systemd-resolved

Mit dem Befehl sudo incus network show br1 holen wir uns die ipv4 der Bridge um mit dieser einen SystemD service /etc/systemd/system/incus-dns-br1.service anzulegen.

 1[Unit]
 2Description=Incus per-link DNS configuration for br1
 3BindsTo=sys-subsystem-net-devices-br1.device
 4After=sys-subsystem-net-devices-br1.device
 5
 6[Service]
 7Type=oneshot
 8ExecStart=/usr/bin/resolvectl dns br1 10.34.239.1
 9ExecStart=/usr/bin/resolvectl domain br1 ~local.example.net
10ExecStart=/usr/bin/resolvectl dnssec br1 off
11ExecStart=/usr/bin/resolvectl dnsovertls br1 off
12ExecStopPost=/usr/bin/resolvectl revert br1
13RemainAfterExit=yes
14
15[Install]
16WantedBy=sys-subsystem-net-devices-br1.device

Den neuen Service wie folgt aktiviren.

1sudo systemctl daemon-reload
2sudo systemctl enable incus-dns-br1.service
3sudo systemctl start incus-dns-br1.service

Damit sind nun die Container per DNS auflösbar.

1ping test01.local.example.net

VM aus ISO Image installieren

Benötigt man eine ganz spezielles Image oder möchte die Installation von einem ISO Image testen geht man wie folgt vor.

Zuerst das gewünschte Image als Volume in Incus importieren.

1incus storage volume import default debian-13.4.0-amd64-netinst.iso debian-13-netinst --type=iso

Eine leere VM einrichten.

1incus init test03 --empty --vm

ISO Image (CD) einhängen.

1incus config device add test03 iso-volume disk pool=default source=debian-13-netinst boot.priority=10

Neue VM von dem eingehängten Image booten.

1incus start test03

Um die Konsole zu öffnen wird ein SPICE Client benötigt, hierfür z.B. das Paket spice-client-gtk installieren. Mit dem folgenden Befehl öffnet man dann die Konsole. Falls sich die Konsole schließen sollte kann man sie mit diesem Befehl auch wieder öffnen.

1incus console test03 --type=vga

Vor dem Reboot in das neue System das ISO Image wieder aushängen.

1incus config device remove test03 iso-volume

Nach dem Reboot empfiehl es sich den incus-agent zu installieren und zu starten.

1apt install incus-agent
2systemctl start incus-agent

Wenn man das ISO Image nicht mehr benötigt, wie folgt löschen.

1incus storage volume delete default debian-13-netinst

Ansible

Ein einfaches Ansible Playbook (playbook.yml) um einen Container einzurichten.

 1- name: Incus Container with Apache2
 2  hosts: test04
 3  gather_facts: false
 4  vars:
 5    ansible_connection: community.general.incus
 6    ansible_incus_remote: local
 7    ansible_incus_project: user-1000
 8  tasks:
 9    - name: Create Incus container
10      community.general.lxd_container:
11        name: "{{ inventory_hostname_short }}"
12        url: "unix:/var/lib/incus/unix.socket"
13        ignore_volatile_options: true
14        state: started
15        source:
16          type: image
17          mode: pull
18          server: "https://images.linuxcontainers.org"
19          protocol: simplestreams
20          alias: "debian/13"
21        profiles:
22          - default
23        project: "{{ ansible_incus_project }}"
24        wait_for_ipv4_addresses: true
25        timeout: 600
26      vars:
27        ansible_connection: local
28      become: true
29      delegate_to: localhost
30    - name: Check python3 is installed in container
31      ansible.builtin.raw: dpkg -s python3
32      register: incus_container_install_python3
33      failed_when: incus_container_install_python3.rc not in [0, 1]
34      changed_when: false
35      check_mode: false
36    - name: Check python3-apt is installed in container
37      ansible.builtin.raw: dpkg -s python3-apt
38      register: incus_container_install_python3_apt
39      failed_when: incus_container_install_python3_apt.rc not in [0, 1]
40      changed_when: false
41      check_mode: false
42    - name: Install python in container
43      ansible.builtin.raw: apt-get update && apt-get install -y python3 python3-apt
44      when: incus_container_install_python3.rc == 1 or
45        incus_container_install_python3_apt.rc == 1
46    - name: Install packages
47      ansible.builtin.apt:
48        pkg:
49          - apache2

Zum Aufrufen des Playbooks.

1ansible-playbook playbook.yml -i "test04,localhost" -D