Container aus dem Proxmox-Template (neueste passende Version aus aplinfo), unprivilegiert, nesting automatisch für docker. Weil Proxmox keine Exec-API für Container hat, läuft die Provisionierung per SSH: bevorzugt pct exec über den Node, sonst direkt in den Container mit einem Bereitstellungsschlüssel, der am Ende wieder entfernt wird. Auf pve-demo beide Wege geprüft: Debian 13 mit docker per pct exec (hello-world läuft mit nesting allein) und Ubuntu 24.04 per SSH in den Container. Dabei gefunden: chrony scheitert ohne CAP_SYS_TIME (jetzt if: vm), sshd -t auf Ubuntu 24.04 ohne /run/sshd. Closes #009 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
5.5 KiB
Katalog: Distributionen und Profile
Distributionen und Profile sind Daten, kein Code. Jede liegt als YAML-Datei unter catalog/ und wird
beim Start von ProxDeploy in die Datenbank abgeglichen. Die Datei ist maßgeblich für den Inhalt; in der
Oberfläche (Katalog) lassen sich Einträge nur aktivieren und deaktivieren. Eine fehlerhafte Datei
wird mit Dateiname und Fehlerstelle im Log gemeldet und übersprungen.
Regeln für beide Arten:
- Dateiname =
id+.yaml(catalog/distros/debian-13.yaml→id: debian-13) - unbekannte Schlüssel sind ein Fehler – ein Tippfehler fällt so sofort auf
- nur HTTPS-Quellen
Neue Distribution hinzufügen
Beispiel Debian 13:
id: debian-13
name: Debian 13 „Trixie“
family: debian # wählt den Provisionierungs-Adapter
os:
id: debian # für Platzhalter in Profilen: {{ os.id }}
version_id: "13" # {{ os.version_id }} – in Anführungszeichen, sonst wird 22.04 zur Zahl
codename: trixie # {{ os.codename }}
arch: amd64
vm:
image_url: https://cloud.debian.org/images/cloud/trixie/latest/debian-13-genericcloud-amd64.qcow2
checksum_url: https://cloud.debian.org/images/cloud/trixie/latest/SHA512SUMS
checksum_type: sha512 # sha256 | sha512
format: qcow2 # qcow2 | raw | vmdk
default_user: debian
guest_agent_preinstalled: false # sonst baut ProxDeploy ihn beim Template-Bau ein
bios: ovmf # ovmf (UEFI, Standard) | seabios
min_disk_gb: 4
lxc:
template_pattern: "debian-13-standard_*_amd64.tar.zst" # wie in `pveam available`
ostype: debian
vm oder lxc darf fehlen, wenn die Distribution nur eins davon kann. Bei mehreren passenden
LXC-Templates gewinnt die höchste Version. Die Prüfsummen-Datei darf im GNU-Format (<hash> <datei>
oder <hash> *<datei>) oder im BSD-Format (SHA256 (<datei>) = <hash>) vorliegen.
Gehört die Distribution zu einer Familie, für die es noch keinen Adapter gibt (etwa rhel für Rocky
oder Alma, alpine), braucht es zusätzlich einen Adapter:
src/engine/adapter/<familie>.tsanlegen, das InterfaceFamilienAdapteraussrc/engine/adapter/schnittstelle.tsumsetzen (Pakete, Dienste, Paketquellen, Zeitzone, Locale, Tastatur, Benutzer, SSH-Härtung, Guest-Agent, automatische Updates)- in
src/engine/adapter/index.tseintragen - Tests nach dem Muster von
tests/engine/profile.test.ts, dazu ein Image intests/container/profile-pruefen.sh - in den Profilen unter
families:eine Umsetzung für die neue Familie ergänzen – Profile ohne Umsetzung erscheinen im Assistenten ausgegraut
Eigenes Profil anlegen
Ein Profil ist eine Liste von Schritten je Distributionsfamilie. Der Adapter übersetzt sie in ein Shell-Skript, das bei VMs über den Guest-Agent und bei Containern per SSH läuft.
id: nginx
name: nginx
description: Webserver mit Startseite
requires: [base] # wird automatisch davor ausgeführt
variables:
- { name: titel, label: Seitentitel, default: Willkommen }
- { name: tls, label: Zertifikat per certbot, type: boolean, default: false }
lxc:
features: { nesting: false } # Container-Features, die das Profil braucht
families:
debian:
- packages: [nginx]
- file:
path: /var/www/html/index.html
content: |
<h1>{{ var.titel }}</h1>
<p>{{ guest.name }} · {{ os.id }} {{ os.version_id }}</p>
- service: { name: nginx, enable: true, start: true }
- packages: [certbot, python3-certbot-nginx]
if: tls
Schritte
| Schritt | Wirkung |
|---|---|
update: true |
Paketlisten aktualisieren und alle Pakete aktualisieren |
packages: [a, b] |
Pakete installieren |
service: { name, enable, start, restart } |
Dienst aktivieren, starten oder neu starten |
repo: { name, key_url, uris, suites, components } |
Paketquelle mit Schlüssel einrichten (deb822) |
repo_package: <url> |
ein Paket installieren, das selbst eine Quelle einrichtet (z. B. zabbix-release) |
file: { path, content, mode } |
Datei schreiben (Inhalt wird unverändert übertragen) |
timezone, locale, keyboard |
Zeitzone, Sprache, Tastaturbelegung |
ssh_harden: { password_auth, root_login } |
SSH absichern – läuft immer ganz am Ende |
guest_agent: true |
QEMU-Guest-Agent (in Containern übersprungen) |
unattended_upgrades: true |
automatische Sicherheitsupdates |
run: <befehl> |
freier Shell-Befehl – nicht portabel, nur wenn nichts anderes passt |
Jeder Schritt kann if: <variable> (oder if: "!<variable>") tragen und läuft dann nur, wenn die
Variable wahr bzw. falsch ist. Fest eingebaut sind if: vm und if: lxc – etwa für Zeitsync, die
in einem unprivilegierten Container nicht laufen kann.
Platzhalter
{{ var.<name> }} (Profil-Variable), {{ os.id }}, {{ os.version_id }}, {{ os.codename }},
{{ guest.name }}, {{ guest.user }}. {{ var.a ?? var.b }} nimmt b, wenn a leer ist. Ein
unbekannter Platzhalter ist ein Fehler, kein leerer Text.
In run-Schritten wird jeder eingesetzte Wert für die Shell gequotet – eine Eingabe im Formular kann
so nie zu Code werden. Variablen dürfen keine Zeilenumbrüche enthalten.
Variablentypen
string (Standard), number, boolean, select (mit options: [...]). required: true macht
das Feld im Assistenten zur Pflicht; default füllt es vor; help erscheint darunter.
Prüfen
pnpm exec tsx scripts/profil-rendern.ts debian-13 nginx titel=Hallo # Skript ansehen
pnpm test:container debian-13 # wirklich ausführen