# Proxmox · Debian-VM-Strategie (Cloud-Init)

## Proxmox · Debian-VM-Strategie (Cloud-Init)

> **abstract:** Zweck
> Debian-13-VMs auf Proxmox reproduzierbar aus einem Cloud-Init-Template bereitstellen. Ausführbarer Source of Truth ist das zentrale interne Git-Repo; dieses Dokument beschreibt den Standard und die Betriebsregeln.

**Gültig für:** Debian 13 (trixie), Proxmox VE, UEFI/OVMF, qcow2-Images

### 1 · Standard und Entscheidung

| Modus | Image | Einsatz |
|---|---|---|
| `cloudinit` | `debian-13-generic-amd64.qcow2` | Standard; User, Key, Hostname und IP pro VM per Cloud-Init |
| `bake` | `debian-13-nocloud-amd64.qcow2` | Sonderfall für bewusst fest gebackene Images |

> **tip:** Empfehlung
> Für neue Staging- und Infrastruktur-VMs immer `cloudinit` mit `--img genericcloud` verwenden.

> **warning:** Image-Falle
> `nocloud` enthält kein Cloud-Init. Der Skriptparameter `--img genericcloud` verwendet die Datei `debian-13-generic-amd64.qcow2`.

### 2 · Skripte installieren

Auf jedem neuen Proxmox-Host als `root`:

```bash
curl -fsSL https://git.corestream.ch/corestream/proxmox-debian-cloudinit-scripts/~raw/master/install-on-proxmox.sh | bash
```

- Installationspfad: `/opt/corestream/proxmox-debian-cloudinit/` (`build-debian-template.sh`, `clone-vm.sh`)
- Kommandos über Symlinks: `/usr/local/sbin/build-debian-template`, `/usr/local/sbin/clone-vm`
- Der OneDev-Raw-Zugriff ist anonym als `Code Reader` freigegeben; der Installer braucht kein Token.

### 3 · Voraussetzungen

#### 3.1 Pakete auf Proxmox

```bash
apt update
apt install -y libguestfs-tools wget curl
```

`qemu-guest-agent` wird nicht für den Proxmox-Host benötigt — das Build-Skript installiert und verifiziert es im Debian-Image.

#### 3.2 Storage und Debian-Image

```bash
pvesm status --enabled
mkdir -p /mnt/pve/<STORE>/import
cd /mnt/pve/<STORE>/import
wget -O debian-13-generic-amd64.qcow2 https://cloud.debian.org/images/cloud/trixie/latest/debian-13-generic-amd64.qcow2
wget -O SHA512SUMS https://cloud.debian.org/images/cloud/trixie/latest/SHA512SUMS
sha512sum -c --ignore-missing SHA512SUMS
```

Rollen im Build-Skript:

- **Quellstorage:** NFS mit unverändertem qcow2 unter `/mnt/pve/<SOURCE_STORE>/import/`; bei mehreren NFS-Storages erscheint ein Auswahlmenü, alternativ `--source-store <STORE>`.
- **Zielstorage:** lokaler, aktivierter Proxmox-Storage mit Content-Typ `images`; Auswahlmenü bzw. `--target-store <STORE>`.

VM-Disk, EFI-Disk und Cloud-Init-Disk liegen immer auf dem Zielstorage; NFS wird nie als VM-Ziel angeboten.

#### 3.3 Admin-Public-Key

Standardpfad prüfen:

```bash
test -s /root/.ssh/id_csgadmin.pub
```

Fehlt die Datei, explizit einen vorhandenen Public-Key übergeben:

```bash
build-debian-template -t 9000 -n debian13-init -m cloudinit --img genericcloud --user-key /pfad/admin.pub
```

> **warning:** > `--user-key /root/.ssh/authorized_keys` übernimmt **alle** dort enthaltenen Keys. Für genau einen Admin-Key eine dedizierte Public-Key-Datei verwenden.

### 4 · Template bauen

```bash
build-debian-template -t 9000 -n debian13-init -m cloudinit --img genericcloud
## optional: --user-key /pfad/admin.pub
## optional (opt-in): --hermes --hermes-key /pfad/hermes.pub
```

Das Skript:

- kopiert das qcow2 pro Build nach `/var/tmp` und verändert **niemals** das zentrale NFS-Basisimage
- installiert und verifiziert `qemu-guest-agent`, `sudo` und `openssh-server` in der Arbeitskopie
- aktiviert QEMU Guest Agent und serielle Konsole
- deaktiviert Root-SSH und Passwort-SSH
- erzwingt die NoCloud-Datasource
- deaktiviert IPv6 per Sysctl und Kernelparameter `ipv6.disable=1`
- importiert VM-, EFI- und Cloud-Init-Disk auf den lokalen Zielstorage
- erstellt eine OVMF/Q35-VM mit SCSI-Disk und Cloud-Init-Drive
- setzt `ciuser=csgadmin`, SSH-Key und DHCP als Ausgangswert
- wandelt die VM in ein Template um

Prüfen:

```bash
qm config 9000 | grep -E 'agent|scsi1|cloudinit|ciuser|boot'
```

Erwartet: `agent: 1` (bzw. `enabled=1`), `scsi1` enthält `cloudinit`, `ciuser: csgadmin`, Boot-Reihenfolge enthält `scsi0;scsi1`.

> **important:** > Template **niemals booten** — immer einen Clone zum Testen verwenden. Ein gebootetes Template hat Cloud-Init bereits ausgeführt.

### 5 · VM klonen

```bash
## DHCP, gewünschte Endgrösse
clone-vm 9000 901 test-debian dhcp --disk-size 32G

## statische IPv4, 64-GB-Disk (Werte im Zielnetz geltend setzen)
clone-vm 9000 121 app-staging <IPv4>/<CIDR> <Gateway-IPv4> --disk-size 64G

## zusätzliche NIC (wiederholbar)
clone-vm 9000 130 dualnic dhcp --add-nic vmbr1 dhcp
```

- `--disk-size` ist optional; vergrössert `scsi0` **vor** dem ersten Boot auf die absolute Grösse. Verkleinern nicht möglich; mindestens Template-Grösse. Debian Cloud-Init/`growpart` erweitert Partition und Dateisystem automatisch.
- `--add-nic` erzeugt `net1`/`ipconfig1`, dann `net2`/`ipconfig2` usw. Sekundäre NICs erhalten bewusst kein zweites Default-Gateway.
- Der Clone-Helper erstellt Full Clones, setzt `agent enabled=1`, die IP-Konfiguration, regeneriert den Cloud-Init-Seed nach allen Änderungen und startet die VM.
- Linked Clones nur für Throwaway-Tests; Staging-/Prod-/Infra-VMs bleiben Full Clones.

#### Netzwerkdienst im Debian-Gast

Das Debian-13-`generic-amd64`-Image (laut offiziellem Paketmanifest, Stand 2026-10) enthält **Netplan** (`netplan.io`) und `systemd-resolved`; NetworkManager und klassisches ifupdown sind nicht enthalten. Netplan rendert per Standard-Renderer `systemd-networkd` (Teil von systemd).

```bash
systemctl is-active systemd-networkd
systemctl is-active systemd-resolved
networkctl
ls -l /etc/netplan/
```

#### Bestehende VM manuell um eine NIC erweitern

Auf Proxmox (VM sauber herunterfahren):

```bash
qm shutdown <VMID>
qm set <VMID> --net1 virtio,bridge=vmbr1
qm start <VMID>
```

Im Gast Interfacename ermitteln (`ip -br link`; typisch `net0` → `ens18`, `net1` → `ens19` — immer tatsächlich prüfen). Netplan-Datei ergänzen:

```bash
## DHCP
printf '%s\n' 'network:' '  version: 2' '  ethernets:' '    ens19:' '      dhcp4: true' '      dhcp6: false' \
  | sudo tee /etc/netplan/60-secondary-nic.yaml >/dev/null
## statisch, ohne zweites Default-Gateway
printf '%s\n' 'network:' '  version: 2' '  ethernets:' '    ens19:' '      dhcp4: false' '      dhcp6: false' '      addresses: [<IPv4>/<CIDR>]' \
  | sudo tee /etc/netplan/60-secondary-nic.yaml >/dev/null

sudo netplan generate && sudo netplan apply
```

Prüfen: `ip -br addr`, `networkctl status ens19`.

> **important:** > Bei einer bereits initialisierten VM im Gast über Netplan ändern. Nicht darauf vertrauen, dass nachträglich gesetztes Proxmox-`ipconfig1` Cloud-Init vollständig erneut ausführt.

### 6 · Verifikation

#### 6.1 Im Gast

```bash
cloud-init status --long
id csgadmin && hostname && ip -4 a
ls -l /dev/disk/by-label/cidata
dpkg-query -W qemu-guest-agent && systemctl is-active qemu-guest-agent
sysctl net.ipv6.conf.all.disable_ipv6 && cat /proc/cmdline
```

Erwartet: Cloud-Init `status: done`, `csgadmin` existiert, Hostname/IPv4 stimmen, `cidata` vorhanden, Guest-Agent aktiv, `disable_ipv6 = 1`, `ipv6.disable=1` in der Kernel-Commandline, keine IPv6-Adressen.

#### 6.2 Auf Proxmox

```bash
qm agent <VMID> ping
ssh csgadmin@<IPv4>
```

### 7 · User und SSH-Zugriff

| User | Standard | Key | Rechte |
|---|---|---|---|
| `csgadmin` | immer im Cloud-Init-Modus | `--user-key`, Standard `/root/.ssh/id_csgadmin.pub` | Admin-Zugang gemäss Cloud-Image/Cloud-Init |
| `hermes` | nur mit `--hermes` | `--hermes-key`, Standard `/root/.ssh/id_ed25519.pub` | `NOPASSWD:ALL`, Passwort gesperrt |
| `root` | kein SSH-Login | keiner | `PermitRootLogin no` |

Zusätzlich gilt `PasswordAuthentication no`; SSH-Zugriff nur per Key. Hermes ist opt-in — der User wird nie automatisch angelegt.

### 8 · Goldene Regeln

1. Für Cloud-Init `debian-13-generic-amd64.qcow2` verwenden.
2. Template nie booten.
3. Cloud-Init-Drive muss vorhanden sein; bei OVMF auf `scsi1`.
4. Nach Änderungen an `ci*` immer `qm cloudinit update <VMID>`.
5. Staging-/Prod-/Infra-VMs als Full Clones erstellen.
6. Admin-Key vor dem Build verifizieren; der Build bricht bei fehlender/leerer Key-Datei ab.
7. Nach dem ersten Clone Cloud-Init, Guest Agent, IPv4, SSH und deaktiviertes IPv6 prüfen.
8. Skripte nicht aus der KB kopieren; immer den aktuellen Stand aus dem Repo installieren.

### 9 · Troubleshooting

| Symptom | Ursache | Fix |
|---|---|---|
| `user pubkey missing` | Default-Key-Datei fehlt | dedizierte Datei oder `--user-key <datei>` |
| `storage ... does not support vm images` | Quell-NFS als VM-Ziel oder alter Skriptstand | Installer erneut ausführen; lokalen Zielstorage wählen bzw. `--target-store` |
| VM-ID existiert nach fehlgeschlagenem Import | Teilbau vor Storage-Fehler angelegt | `qm config <VMID>` prüfen, Teilbau löschen oder neue ID |
| Basis-qcow2 stimmt nicht mit SHA512 | alter Skriptstand hat NFS-Image direkt verändert | Original neu laden; aktueller Stand arbeitet mit `/var/tmp`-Kopie |
| Kein SSH-Login | Key nicht im Cloud-Init-Seed | `qm config` (`sshkeys`), Key-Datei, `qm cloudinit update` prüfen |
| `cloud-init: command not found` | `nocloud`-Image verwendet | Template mit `generic-amd64` neu bauen |
| `cidata` fehlt | Cloud-Init-Drive fehlt/falscher Bus | `scsi1` und `qm cloudinit update` prüfen |
| Cloud-Init übersprungen | Template wurde gebootet | Template neu bauen; künftig nur Clones booten |
| `qemu-guest-agent` fehlt | altes/fehlerhaftes Template | aktuelles Build-Skript, Template neu bauen |
| `qm agent <VMID> ping` scheitert | Paket/Dienst/Agent-Flag fehlt | Gastpaket, Dienst, `/dev/virtio-ports/`, `qm config` prüfen |
| IPv6 noch aktiv | alter Template-Stand oder kein Neustart | neues Template; Sysctl, Kernelparameter, Cold Boot prüfen |
| DHCP wartet | kein DHCP im Zielnetz | statische IPv4 beim Clone übergeben |

### 10 · Source of Truth

> **important:** > Ausführbarer Source of Truth ist das interne Git-Repo, nicht ein eingebetteter Skriptblock in der KB.

- **Repo:** `corestream/proxmox-debian-cloudinit-scripts` (internes OneDev)
- **Installer:** `https://git.corestream.ch/corestream/proxmox-debian-cloudinit-scripts/~raw/master/install-on-proxmox.sh`
- **Installationspfad:** `/opt/corestream/proxmox-debian-cloudinit`

Die früher eingebetteten Vollkopien der Skripte wurden bewusst entfernt, damit Doku und Code nicht auseinanderlaufen.

Verwandt: Staging- und Produktionskonzept

### Quellen

- Debian Cloud-Images (trixie, `latest`): <https://cloud.debian.org/images/cloud/trix/latest/>
- Debian Cloud image Paketmanifest (`debian-13-generic-amd64.json`): <https://cloud.debian.org/images/cloud/trix/latest/debian-13-generic-amd64.json>
- Proxmox VE Administration Guide – QEMU/Cloud-Init: <https://pve.proxmox.com/pve-docs/chapter-qm.html>
- Proxmox VE Wiki – Cloud-Init Support: <https://pve.proxmox.com/wiki/Cloud-Init_Support>

---

*Quelle: Obsidian `Knowledge Base/Proxmox/Proxmox Debian Cloud-Init Strategie.md` · Stand: 2026-10-12 · Automatisiert publiziert durch Hermes.*