Entwickeln
Eigene App
Vom leeren Repo zur App mit Container, VM-Image und Update – in sechs Schritten.
Das Prinzip
Eine iac-App beschreibt nur ihren Sollzustand – als Ansible-Rolle: Pakete, Benutzer,
Dateien, Konfiguration. Dazu kommt ein Steckbrief (iac.json) mit Ports, Diensten und
Healthcheck. Alles andere übernimmt iac-core:
- Container und VM anlegen, dazu die Einzeiler
ct.sh,vm.shundadopt.sh - das VM-Image bauen und testen, die CI
- Firewall, Dienste starten, Healthcheck,
update, Module
Deshalb besteht ein App-Repo nur aus wenigen Dateien:
iac-meineapp/
├── iac.json Steckbrief
├── tasks/main.yml der Sollzustand (Ansible) ← das Wesentliche
├── handlers/main.yml Neustarts
├── templates/, files/ Konfigurationsdateien, systemd-Units
├── tests/smoke.sh Prüfungen, die nur diese App braucht
├── README.md, CHANGELOG.md, AGENTS.md (+ Verweise für KI-Werkzeuge)
└── .forgejo/workflows/ lint.yml, image.yml – unverändert aus der Vorlage
Ansible läuft dabei lokal im Gast – kein Controller, kein Inventory, kein SSH von außen.
1. Vorbereiten
mkdir -p ~/repositories/iac && cd ~/repositories/iac
git clone https://git.heyer.systems/iac/iac-core.git
git clone https://git.heyer.systems/iac/iac-example.git
Lokal gebraucht werden shellcheck, jq, ansible-core (Lint) und Docker (Testen ohne
Proxmox). Lies vorher iac-example in der
Reihenfolge aus seinem README: eine kleine App, in der jede Möglichkeit genau einmal vorkommt.
2. Gerüst anlegen
iac-core/tools/new-app.sh meineapp # legt iac-meineapp/ an, überschreibt nie etwas
3. Steckbrief: iac.json
{
"name": "meineapp",
"title": "Meine App",
"description": "Ein Satz für die Website.",
"upstream": { "type": "debian", "repo": "meineapp" },
"supports": ["lxc", "vm"],
"defaults": {
"lxc": { "cpu": 1, "ram": 512, "disk": 4 },
"vm": { "cpu": 1, "ram": 1024, "disk": 8 }
},
"ports": [{ "port": 80, "proto": "tcp", "description": "Web", "access": "public" }],
"services": ["meineapp"],
"health": { "url": "http://127.0.0.1/" },
"access": "Web: http://{ip}/"
}
Aus ports entsteht die Firewall, services startet und prüft iac-core, health muss nach jeder
Installation antworten. Alle Felder: App-Referenz.
4. Sollzustand: tasks/main.yml
Ganz normales Ansible – nur mit den eingebauten Modulen (ansible.builtin.*):
- name: Package meineapp
ansible.builtin.apt:
name: meineapp
install_recommends: false
- name: Configuration
ansible.builtin.template:
src: config.yml.j2 # templates/config.yml.j2
dest: /etc/meineapp/config.yml
owner: root
group: root
mode: "0644"
notify: Restart meineapp # handlers/main.yml
Dazu der Handler in handlers/main.yml:
- name: Restart meineapp
ansible.builtin.systemd_service:
name: meineapp
state: restarted
daemon_reload: true
when: not iac_build # im Image-Build läuft kein systemd
Drei Regeln, dann passt es:
- Idempotent – ein zweiter Lauf ändert nichts. Mit Modulen statt
command/shellbekommst du das geschenkt. - Neustarts nur per
notify– so unterbricht einupdateohne Änderung den Dienst nicht. - Dienste startest du nicht selbst – das macht iac-core für alles in
services.
Software von außerhalb Debians (GitHub-Release, eigene Download-Seite)? Die Rolle iac_version
entscheidet, welche Version installiert wird: Versionen.
5. Testen
iac-core/tools/lint.sh iac-meineapp # Tippfehler, falsche Felder, Ansible-Syntax
iac-core/tools/dev-container.sh iac-meineapp # installieren + Smoke-Test, ohne Proxmox
iac-core/tools/dev-container.sh iac-meineapp # zweiter Lauf: idempotent? (changed=1)
Hineinschauen: docker exec -it iac-dev-meineapp bash, Log in /var/log/iac/iac.log.
6. Veröffentlichen
- Repo
iac-meineappin der Organisation iac anlegen (öffentlich) und pushen. - Die CI prüft jeden Push. Ein Push auf
mainbaut außerdem das VM-Image, startet es in einer Test-VM und veröffentlicht es nur, wenn alle Prüfungen bestehen. - Die Website liest stündlich alle öffentlichen
iac-*-Repos ein. Danach gibt es die App-Seite mit Generator und die Einzeiler/meineapp/ct.shund/meineapp/vm.sh.
Weiter: App-Referenz – alle Felder, Variablen, Hilfsrollen und häufige Fehler.