# Backup-Konzept — kube-bot + diskstation-bot
Stand: 2026-06-23

## Architektur

```
K3s DMZ (192.168.20.40/.45)  ──┐
Raspi / nginx PM (20.20)     ──┤  push/scp  →  dmz-backup (192.168.20.90)
IT15 / ArgoCD (192.168.1.121)──┘                    │
                                                     │ pull 06:00 UTC
                                              DiskStation (192.168.1.40)
                                         KI_Agenten/backups/k3s-dmz/
```

## Prinzipien

1. Clientseitige Verschlüsselung mit `age` — Klartext verlässt nie den Quellhost
2. Credentials ausschließlich via Infisical (Backup_Restore/prod) — nie im Script-Text
3. SHA256-Verifikation nach jedem Transfer
4. Einheitlicher Pfad dmz-backup: `k3s-dmz/tenants/<mandant>/<env>/<app>/<backup-id>/`
5. Artefakte: `<backup-id>__<cluster>__<mandant>__<app>__<typ>.tar.gz.age` + `.sha256`

## Zeitplan (täglich, UTC)

| Zeit  | Job                  | Runner              | dmz-backup Pfad                                    |
|-------|----------------------|---------------------|----------------------------------------------------|
| 02:00 | K3s Controlplane DMZ | DMZ Crontab         | tenants/platform/prod/k3s-controlplane/            |
| 02:10 | DMZ-Infisical        | DMZ Crontab         | tenants/platform/prod/infisical/                   |
| 02:20 | ArgoCD IT15 + K3s DB | kube-bot HEARTBEAT  | tenants/platform/prod/argocd-it15/                 |
| 02:30 | nginx Proxy Manager  | kube-bot HEARTBEAT  | tenants/platform/prod/nginx-proxy-manager/         |
| 03:00 | Zammad               | DMZ Crontab         | tenants/pidoka/prod/zammad/                        |
| 03:20 | Matomo               | DMZ Crontab         | tenants/pidoka/prod/matomo/                        |
| 03:40 | n8n                  | DMZ Crontab         | tenants/pidoka/prod/n8n/                           |
| 03:50 | Mautic               | DMZ Crontab         | tenants/pidoka/prod/mautic/                        |
| 04:00 | SuiteCRM             | DMZ Crontab         | tenants/pidoka/prod/suitecrm/                      |
| 04:10 | Homarr               | DMZ Crontab         | tenants/pidoka/prod/homarr/                        |
| 04:30 | NextcloudPi          | DiskStation Task 5  | /volume1/Backup_Nextcloud/ (direkt)                |
| 05:30 | Longhorn NFS Pull    | DiskStation Task 7  | KI_Agenten/backups/k3s-dmz/longhorn-staging/       |
| 06:00 | dmz-backup Pull      | DiskStation Task 9  | KI_Agenten/backups/k3s-dmz/tenants/ (alle .age)    |

## Scripts — kube-bot

Ablage Runtime: `/home/node/.openclaw/workspace/scripts/`
Ablage DMZ Control-Plane: `/home/kube-bot/scripts/`

| Script                    | Sprache     | Zweck                                      |
|---------------------------|-------------|--------------------------------------------|
| backup-app.sh             | Bash        | Generisches K3s App-Backup (DMZ-Apps)      |
| backup-argocd-it15.sh     | Bash        | ArgoCD Apps/Projects + K3s State DB IT15   |
| backup-nginx.sh           | Bash        | nginx Proxy Manager vom Raspi              |
| backup-all.sh             | Bash        | Manueller Wrapper (Referenz)               |
| restore-staging-fetch.sh  | Bash        | Restore-Staging Hilfsskript                |

Credential-Handling: Python 3 inline (stdlib: urllib, json, os) — kein externer Code
Verschlüsselung: age Binary `/home/node/shared/tools/age` (x86_64) / apt-Paket auf aarch64

DMZ Crontab-User: `kube-bot` auf `192.168.20.40`
Logs: `/home/kube-bot/logs/backup-<app>.log`

## Scripts — diskstation-bot

Ablage: `/volume1/KI_Agenten/backups/k3s-dmz/scripts/`

| Script                        | DSM Task | Zeit       | Zweck                          |
|-------------------------------|----------|------------|--------------------------------|
| dmz-backup-pull.sh            | Task 9   | 06:00 UTC  | Pull alle .age von dmz-backup  |
| longhorn-nfs-pull.sh          | Task 7   | 05:30 UTC  | Longhorn NFS Backupstore Pull  |
| homarr-pull-from-dmz.sh       | —        | manuell    | Homarr-spezifisch              |
| homarr-stage-restore-to-dmz.sh| —        | manuell    | Homarr Restore-Staging         |

Ablage: `/volume1/Backup_Nextcloud/scripts/`

| Script    | DSM Task | Zeit       | Zweck              |
|-----------|----------|------------|--------------------|
| ncp-pull.sh | Task 5 | 04:30 UTC  | NextcloudPi Pull   |

Sprache: Shell (`#!/bin/sh`) — POSIX-kompatibel, DSM-Aufgabenplaner unter User `diskstation-bot`
Credential-Handling: Python 3 inline (urllib, json, ssl) — nur in OpenClaw-Runtime, nie auf DiskStation

## Age-Keys (Infisical Backup_Restore/prod)

| Secret-Prefix                  | App                  |
|--------------------------------|----------------------|
| BACKUP_HOMARR_AGE_*            | Homarr               |
| BACKUP_INFISICAL_AGE_*         | DMZ-Infisical        |
| BACKUP_K3S_CONTROLPLANE_AGE_*  | K3s Controlplane     |
| BACKUP_NGINX_AGE_*             | nginx Proxy Manager  |
| BACKUP_ARGOCD_IT15_AGE_*       | ArgoCD IT15          |
| KUBE_BOT_DMZ_BACKUP_SSH_*      | SSH-Zugang dmz-backup|

## DiskStation Zielstruktur

```
/volume1/KI_Agenten/backups/k3s-dmz/
  tenants/
    platform/prod/
      argocd-it15/          ← ArgoCD + K3s IT15
      infisical/            ← DMZ-Infisical
      k3s-controlplane/     ← K3s DMZ Controlplane
      nginx-proxy-manager/  ← nginx PM
    pidoka/prod/
      homarr/
      matomo/
      mautic/
      n8n/
      suitecrm/
      zammad/
    cattaro/prod/           ← reserviert
  longhorn-staging/         ← Longhorn NFS Backupstore
  _restore-staging/         ← Restore-Artefakte
  docs/
  logs/
  scripts/
  status/
```

## Notizen

- `Backup_K3s_Longhorn` Share gelöscht 2026-06-23 (nach vollständiger Migration)
- Longhorn Backup-Target zeigt auf `nfs://192.168.20.40:/srv/longhorn-backup-staging` (DMZ-intern, unabhängig vom Share-Namen)
- IT15 → dmz-backup Entscheid 2026-06-23: gleicher Weg wie alle anderen (entgegen ursprünglicher Abmachung)


## Lagebericht 2026-06-23

### diskstation-bot
- Task 7 (Longhorn NFS Pull 05:30): Lauf inhaltlich OK (337 Dateien, RSYNC_EXIT=0), Status-Datei fehlte wegen altem Pfad → Script gepatcht ✅
- Task 9 (dmz-backup Pull 06:00): STATUS=ok, RSYNC_EXIT=0, 38 Quelldateien, alle Artefakte angekommen ✅
- Task 5 (NextcloudPi Pull 04:30): rsync error code 23 — Permissions auf /var/mail, /var/spool/postfix, /var/tmp. Nextcloud-Daten vollständig. Offen: --exclude für Systempfade (nextcloud-bot)

### kube-bot
- Alle Backup-Scripts erstellt und getestet: backup-argocd-it15.sh ✅, backup-nginx.sh ✅
- Cronjobs auf DMZ Control-Plane (192.168.20.40) eingerichtet: 02:00–04:10 UTC ✅
- HEARTBEAT.md: ArgoCD IT15 02:20, nginx 02:30, Lagebericht 08:00 ✅
- Erster vollständiger automatischer Lauf: morgen Nacht ab 02:00 UTC

### Offene Punkte
- nextcloud-bot: --exclude /var/mail /var/spool/postfix /var/tmp in ncp-pull.sh ergänzen
- NextcloudPi (Task 5 rsync error 23): wird separat nachgeholt — nextcloud-bot koordiniert mit diskstation-bot (Entscheid Mislav 2026-06-23)
