id: backup-provision namespace: automation description: "Netbox → Ansible → Borg Backup Provisioning" version: 1 triggers: - id: daily-backup-sync type: schedule cron: "0 2 * * *" # Täglich 02:00 Uhr timezone: "Europe/Berlin" variables: netbox_url: "https://netbox.mbo-tech-it.de" netbox_api_token: "{{ secret('NETBOX_TOKEN') }}" # Basis-TAG für automatische Backups (erforderlich) backup_tag_base: "auto-backup" # Optional: Weitere TAGs können hinzugefügt werden # z.B. env:prod, tenant:kunde1, backup-server:primary ansible_inventory_file: "/tmp/netbox_inventory.ini" git_repo: "https://gitea.mbo-tech-it.de/claude/backup-automation.git" tasks: # Task 1: Netbox Abfrage - Alle Systems mit "auto-backup" TAG - id: fetch-backup-systems type: io.kestra.plugin.core.http.Request uri: "{{ vars.netbox_url }}/api/dcim/devices/?tag={{ vars.backup_tag_base }}&limit=500" headers: Authorization: "Token {{ vars.netbox_api_token }}" method: GET # Task 2: Verarbeite Netbox Response - id: parse-devices type: io.kestra.plugin.core.script.Groovy script: | def response = json(tasks.fetchBackupSystems.body) def devices = [] response.results.each { device -> devices.add([ name: device.name, ip: device.primary_ip4?.address?.split('/')[0] ?: null, os: device.device_type?.manufacturer?.name ?: "unknown", status: device.status?.value ]) } // Filtern: nur active und mit IP def activeDevices = devices.findAll { it.ip && it.status == 'active' } kestra.logger.info("Found ${activeDevices.size()} devices for backup") return activeDevices # Task 3: Git-Repo pullen - id: pull-backup-scripts type: io.kestra.plugin.core.tasks.bash.BashScript script: | #!/bin/bash set -e REPO_DIR="/tmp/backup-automation" if [ -d "$REPO_DIR" ]; then cd "$REPO_DIR" git pull origin main else git clone {{ vars.git_repo }} "$REPO_DIR" cd "$REPO_DIR" fi echo "Repo synced successfully" exit 0 # Task 4: Generiere Ansible Inventory aus Netbox-Daten - id: generate-ansible-inventory type: io.kestra.plugin.core.script.Groovy script: | def devices = tasks.parseDevices.output def inventory = """[all] [backup_clients] """ devices.each { device -> inventory += """${device.name} ansible_host=${device.ip} ansible_user=root """ } inventory += """ [backup_clients:vars] ansible_python_interpreter=/usr/bin/python3 backup_repo_server=backup01.mbotechit.de backup_repo_base=/backup/repos """ // Schreibe zu Datei new File('/tmp/netbox_inventory.ini').text = inventory kestra.logger.info("Ansible inventory generated") return true # Task 5: Führe Ansible Playbook aus (parallel pro Host) - id: run-ansible-playbook type: io.kestra.plugin.core.tasks.bash.BashScript script: | #!/bin/bash set -e cd /tmp/backup-automation # Installiere Ansible + Netbox Module falls nötig pip install -q ansible netaddr jinja2 &>/dev/null || true # Führe Playbook aus ansible-playbook \ -i {{ vars.ansible_inventory_file }} \ ansible/playbooks/install-borg-client.yaml \ -e "backup_repo_server=backup01.mbotechit.de" \ -e "backup_repo_base=/backup/repos" \ --diff echo "Ansible playbook completed" exit 0 # Task 6: Trigger Backup-Server Borg Repo Init (falls neu) - id: initialize-backup-repos type: io.kestra.plugin.core.tasks.bash.BashScript script: | #!/bin/bash cd /tmp/backup-automation # SSH zum Backup-Server ssh -i ~/.ssh/id_ed25519 backup@backup01.mbotechit.de << 'EOF' source /home/backup/.bashrc # Hole Device-Liste aus Netbox (nur Systems mit auto-backup TAG) DEVICES=$(curl -s -H "Authorization: Token {{ vars.netbox_api_token }}" \ "{{ vars.netbox_url }}/api/dcim/devices/?tag={{ vars.backup_tag_base }}&limit=500" \ | jq -r '.results[].name') for device in $DEVICES; do REPO_PATH="/backup/repos/$device" if [ ! -d "$REPO_PATH" ]; then mkdir -p "$REPO_PATH" borg init --encryption=repokey "$REPO_PATH" echo "Initialized $REPO_PATH" fi done EOF exit 0 # Task 7: Trigger Backups auf allen Hosts - id: trigger-backups type: io.kestra.plugin.core.tasks.bash.BashScript script: | #!/bin/bash DEVICES="{{ tasks.parseDevices.output | json }}" echo "$DEVICES" | jq -r '.[] | .name' | while read device; do kestra.logger.info "Triggering backup for $device..." # SSH zum Host und starte systemd service ssh -i ~/.ssh/id_ed25519 root@$device \ "systemctl start mbo-backup.service" 2>/dev/null || true done echo "Backup triggers sent" exit 0 # Task 8: Status Reporting - id: backup-status-report type: io.kestra.plugin.core.script.Groovy script: | def devices = tasks.parseDevices.output def report = """ ╔══════════════════════════════════════════════════╗ ║ BACKUP PROVISION REPORT ║ ╠══════════════════════════════════════════════════╣ """ report += "║ Total Devices Found: ${devices.size()}\n" report += "║ Timestamp: ${new Date()}\n" report += "║ Status: PROVISIONING INITIATED\n" report += "╚══════════════════════════════════════════════════╝\n\n" devices.each { device -> report += "✓ ${device.name} (${device.ip})\n" } kestra.logger.info(report) return report outputs: - id: device_count type: STRING value: "{{ tasks.parseDevices.output.size() }}" - id: backup_report type: STRING value: "{{ tasks.backupStatusReport.output }}"