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.
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 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
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
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