Files
kestra-scripts/README.md
T
2026-06-26 18:03:17 +02:00

419 lines
8.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Kestra Scripts
Dieses Repository enthält Kestra-Flows und Hilfsskripte für Homelab-Automatisierung.
Aktuell enthalten:
* `docker_stack_inventory_scan.yaml`
* `build_select_options.py`
* `linux_apt-upgrade.yaml`
* `hetzner-vm-provision.yaml`
* `hetzner-server-type-location-update.yaml`
* `.env.example`
Der erste Flow scannt mehrere Docker-Hosts per SSH, sucht nach Docker-Compose-Stacks und schreibt daraus eine Dropdown-Liste in den Kestra KV-Store.
---
## Zweck
Dieses Repository trennt bewusst:
* **Kestra-Flow**: Ablaufsteuerung und Orchestrierung
* **Python-Script**: Verarbeitung der Scan-Ergebnisse
* **Secrets / Zugangsdaten**: außerhalb des Repositories über `.env` bzw. Kestra Secrets
Damit bleibt der Flow übersichtlich, wartbar und sicherer.
---
## Dateien
### `docker_stack_inventory_scan.yaml`
Kestra-Flow zum Scannen mehrerer Docker-Hosts.
Der Flow:
1. verbindet sich per SSH mit definierten Docker-Hosts
2. durchsucht dort ein Basisverzeichnis nach Compose-Dateien
3. sammelt gefundene Docker-Stacks ein
4. übergibt die Ergebnisse an ein Python-Script
5. schreibt die fertige Dropdown-Liste in den Kestra KV-Store
Gesucht werden unter anderem:
```text
compose.yml
compose.yaml
docker-compose.yml
docker-compose.yaml
```
---
### `build_select_options.py`
Python-Script zum Zusammenführen der Scan-Ergebnisse.
Das Script liest die Umgebungsvariable:
```text
OPTIONS_B64_JSON
```
Darin erwartet es eine JSON-Liste mit Base64-codierten Host-Ergebnissen.
Ausgabe:
```text
select_options.json
```
Diese Datei wird anschließend vom Kestra-Flow in den KV-Store geschrieben.
---
### `linux_apt-upgrade.yaml`
Kestra-Flow zum Ausführen von `apt update && apt upgrade` auf einem Linux-Server per SSH.
Der Flow:
1. verbindet sich per SSH mit dem Zielserver
2. erkennt automatisch ob der Benutzer root ist oder sudo benötigt
3. führt `apt-get update` und `apt-get upgrade` aus
4. meldet ob ein Reboot erforderlich ist
Der Flow wird manuell gestartet und erwartet folgende Eingaben:
| Input | Beschreibung |
|---|---|
| `host` | Server IP oder Hostname |
| `user` | SSH-Benutzer |
| `sudo_password` | Sudo-Passwort (Kestra Secret) |
Benötigtes Kestra Secret:
```text
SSH_PRIVATE_KEY
```
![linux-apt-upgrade Flow](screenshots/linux_apt_upgrade.png)
---
### `hetzner-vm-provision.yaml`
Kestra-Flow zum Provisionieren einer Hetzner Cloud VM via Terraform — mit KI-gestützter Plan-Analyse und manuellem Approval-Gate.
**Namespace:** `hetzner`
Der Flow läuft in vier Phasen:
1. **Terraform Plan** — erstellt einen Plan für die neue VM (Ubuntu 24.04) im Hetzner-Datacenter; Terraform State wird im S3-Backend (Hetzner Object Storage) gespeichert
2. **LLM-Analyse** — GPT-4o-mini fasst den Plan auf Deutsch zusammen und bewertet ob er sicher aussieht
3. **Approval-Gate** — Kestra pausiert und wartet auf manuelle Freigabe
4. **Terraform Apply / Abbruch** — bei Freigabe wird die VM erstellt und die IPv4-Adresse ausgegeben; bei Ablehnung wird die Execution abgebrochen
Der Flow erwartet folgende Eingaben:
| Input | Typ | Beschreibung |
|---|---|---|
| `vm_name` | STRING | Eindeutiger VM-Name, z.B. `dev-server-01` |
| `server_type` | SELECT | `cx23` (2 vCPU / 4 GB) · `cx33` · `cx43` · `cx53` |
| `location` | SELECT | `nbg1` · `fsn1` · `hel1` |
| `team` | STRING | Label für die VM |
Benötigte Kestra Secrets:
```text
HCLOUD_TOKEN
SSH_KEY_NAME
AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
TF_BACKEND_BUCKET
TF_BACKEND_ENDPOINT
OPENAI_API_KEY
```
---
### `hetzner-server-type-location-update.yaml`
Kestra-Flow zum automatischen Aktualisieren der verfügbaren Hetzner Server-Typen und Standorte.
**Namespace:** `hetzner`
**Trigger:** Alle 15 Minuten, täglich 07:0021:00 Uhr (Europe/Berlin)
Der Flow:
1. **Hetzner API abfragen** — ruft die aktuellen Server-Typen (`cx23`, `cx33`, `cpx42`) und deren verfügbare Standorte (`nbg1`, `fsn1`, `hel1`) ab
2. **Dropdown-Matrix bauen** — erzeugt eine kombinierte Server-Type/Location-Liste im Format `cx23|nbg1`
3. **MinIO/S3 Upload** — schreibt beide JSON-Dateien ins S3-Backend unter `inventory/`
4. **KV-Store setzen** — speichert die Dropdown-Optionen unter dem Key `hetzner_server_type_location_options`
Ausgaben:
| Ziel | Pfad / Key |
|---|---|
| S3 | `inventory/hetzner-server-types.json` |
| S3 | `inventory/hetzner-server-type-location-options.json` |
| KV-Store | `hetzner_server_type_location_options` |
Benötigte Kestra Secrets:
```text
HCLOUD_TOKEN
AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
TF_BACKEND_BUCKET
TF_BACKEND_ENDPOINT
```
---
### `.env.example`
Beispiel-Datei für benötigte Umgebungsvariablen und Secrets.
Die Datei enthält bewusst nur Platzhalter.
Die echte `.env` darf nicht ins Git-Repository committed werden.
---
## Installation
Repository klonen:
```bash
git clone https://git.unixweb.net/joachim/kestra-scripts.git
cd kestra-scripts
```
Beispiel-Umgebung kopieren:
```bash
cp .env.example .env
```
Danach die Werte in `.env` anpassen.
---
## Kestra Secrets
Der Flow verwendet Kestra Secrets, zum Beispiel:
```yaml
privateKey: "{{ secret('SSH_PRIVATE_KEY') }}"
```
Bei Kestra OSS müssen `SECRET_*` Werte in der `.env` base64-codiert hinterlegt werden.
Beispiel Linux:
```bash
echo -n "mein-geheimer-wert" | base64 -w 0
```
Beispiel macOS:
```bash
echo -n "mein-geheimer-wert" | base64
```
Beispiel für einen SSH Private Key:
```bash
base64 -w 0 ~/.ssh/id_ed25519
```
Dann in `.env` eintragen:
```env
SECRET_SSH_PRIVATE_KEY=base64_encoded_private_ssh_key
```
---
## Docker Stack Inventory Scan
Der Flow befindet sich in:
```text
docker_stack_inventory_scan.yaml
```
Wichtige Variablen im Flow:
```yaml
variables:
ssh_user: meinuser
base_dir: /home/meinuser/docker
kv_select_options_key: docker_stack_select_options
```
Die Docker-Hosts werden im Flow als Liste definiert:
```yaml
docker_hosts:
- docker1;192.168.100.10
- docker2;192.168.100.11
```
Format:
```text
hostname;ip-adresse
```
Beispiel:
```text
docker1;192.168.100.10
```
---
## KV-Store Ergebnis
Der Flow schreibt die Dropdown-Liste in diesen Kestra KV-Key:
```text
docker_stack_select_options
```
Die Werte haben dieses Format:
```text
hostname;ip-adresse;ssh-user;compose-verzeichnis
```
Beispiel:
```text
docker1;192.168.100.10;meinuser;/home/meinuser/docker/nextcloud
```
---
## Sicherheit
Dieses Repository darf keine echten Zugangsdaten enthalten.
Nicht committen:
```text
.env
SSH Private Keys
API Tokens
Passwörter
Terraform State Dateien
S3 Zugangsdaten
OpenAI API Keys
SMTP Passwörter
```
Empfohlene `.gitignore`:
```gitignore
.env
.env.*
!.env.example
*.tfstate
*.tfstate.*
.terraform/
*.pem
*.key
id_rsa
id_ed25519
__pycache__/
*.pyc
```
Wichtig: Wenn ein Secret einmal versehentlich committed oder öffentlich geteilt wurde, sollte es ausgetauscht werden.
---
## Test des Python-Scripts
Das Python-Script kann lokal getestet werden.
Beispiel:
```bash
export OPTIONS_B64_JSON='["WyJkb2NrZXIxOzE5Mi4xNjguMTAwLjEwO21laW51c2VyOy9ob21lL21laW51c2VyL2RvY2tlci9uZXh0Y2xvdWQiXQ=="]'
python3 build_select_options.py
cat select_options.json
```
Erwartete Ausgabe:
```json
[
"docker1;192.168.100.10;meinuser;/home/meinuser/docker/nextcloud"
]
```
---
## Typische Fehler
### Python-Script wird nicht gefunden
Fehler:
```text
python3: can't open file ... build_select_options.py
```
Ursache:
Das Script liegt nicht an der erwarteten Stelle im geklonten Repository.
Lösung:
Im Kestra-Log prüfen, welche Dateien nach dem Git-Clone vorhanden sind. Der aktuelle Flow sucht `build_select_options.py` automatisch.
---
### SSH-Verbindung schlägt fehl
Mögliche Ursachen:
* falscher SSH-Benutzer
* falscher Host
* SSH-Key fehlt in Kestra
* Public Key ist auf dem Zielhost nicht in `authorized_keys`
* Firewall blockiert Port 22
---
### Keine Stacks gefunden
Mögliche Ursachen:
* falsches `base_dir`
* Compose-Dateien liegen tiefer als `maxdepth 2`
* Compose-Dateien heißen anders
* Benutzer hat keine Leserechte
---
## Grundsatz
Die klassische Aufteilung bleibt:
```text
Kestra = Ablaufsteuerung
Git = versionierte Logik
Secrets = außerhalb des Repositories
KV-Store = Laufzeitdaten für Dropdowns und Auswahlfelder
```