Proxmox Cloud-Init konfigurieren

Eine Anleitung zur Einrichtung von Cloud-Init in Proxmox für automatische VM-Konfiguration.

Cloud-Init ist der De-facto-Standard für die automatische Konfiguration von virtuellen Maschinen in Cloud-Umgebungen. In diesem Artikel zeige ich dir, wie du ein Cloud-Init Template in Proxmox erstellst und automatisch VMs damit bereitstellen kannst.

Was ist Cloud-Init?

Cloud-Init ist ein Werkzeug, das beim ersten Start einer virtuellen Maschine ausgeführt wird, um das System automatisch zu konfigurieren. Dazu gehören:

  • Einrichten von Benutzerkonten und SSH-Keys
  • Netzwerk-Konfiguration
  • Konfiguration von Paketquellen
  • System-Anpassungen

Voraussetzungen

Bevor wir beginnen, stelle sicher, dass folgende Pakete installiert sind:

1
apt install libguestfs-tools wget

Schritt-für-Schritt Anleitung

1. Image herunterladen

Zuerst laden wir das Cloud-Image herunter:

1
2
3
mkdir -p /opt/cloud_init
cd /opt/cloud_init
wget https://cloud.debian.org/images/cloud/trixie/latest/debian-13-generic-amd64.qcow2

2. qemu-guest-agent installieren

Der qemu-guest-agent ermöglicht die Kommunikation zwischen Proxmox und der VM:

1
virt-customize -a debian-13-generic-amd64.qcow2 --install qemu-guest-agent

3. Root-Passwort setzen

1
virt-customize -a debian-13-generic-amd64.qcow2 --root-password password:dein-passwort

4. /etc/machine-id leeren

Dies ist wichtig für Cloud-Init:

1
virt-customize -a debian-13-generic-amd64.qcow2 --run-command "echo -n > /etc/machine-id"

5. SSH-Keys hinzufügen

1
2
3
4
5
6
7
8
virt-customize -a debian-13-generic-amd64.qcow2 \
  --run-command "mkdir -p /root/.ssh && chmod 700 /root/.ssh" \
  --run-command "cat >> /root/.ssh/authorized_keys << 'SSHEOF'
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAAAAxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx user@host-1
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAAAAyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy user@host-2
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAAAAzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz user@host-3
SSHEOF" \
  --run-command "chmod 600 /root/.ssh/authorized_keys"

6. SSH Root-Login aktivieren (optional)

1
2
virt-customize -a debian-13-generic-amd64.qcow2 \
  --run-command "sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config"

7. VM erstellen

Jetzt erstellen wir die VM in Proxmox:

1
2
3
4
5
qm create 9999 \
  --name debian-13 \
  --memory 2048 \
  --cores 4 \
  --net0 virtio,bridge=vmbr1

8. Disk importieren

1
qm importdisk 9999 debian-13-generic-amd64.qcow2 local-zfs

9. VM konfigurieren

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
qm set 9999 --scsihw virtio-scsi-single --scsi0 "local-zfs:vm-9999-disk-0,cache=writeback,discard=on,ssd=1"
qm set 9999 --boot c --bootdisk scsi0
qm set 9999 --scsi2 local-zfs:cloudinit
qm set 9999 --agent enabled=1
qm set 9999 --serial0 socket
qm set 9999 --vga serial0
qm set 9999 --cpu cputype=host
qm set 9999 --ostype l26
qm set 9999 --balloon 2048
qm set 9999 --ciupgrade 1
qm set 9999 --ipconfig0 ip=dhcp
qm set 9999 --nameserver 192.168.1.1
qm set 9999 --searchdomain localdomain

Erklärung der qm set Befehle

BefehlBeschreibung
--scsihw virtio-scsi-singleSCSI-Controller konfigurieren
--boot c --bootdisk scsi0Boot-Reihenfolge festlegen
--scsi2 ...:cloudinitCloud-Init Disk hinzufügen
--agent enabled=1qemu-guest-agent aktivieren
--serial0 socketSerielle Konsole
--vga serial0VGA-Ausgabe auf serial0
--cpu cputype=hostCPU-Typ
--ostype l26Linux 2.6+ Kernel
--balloonMemory-Ballooning
--ciupgrade 1Cloud-Init Upgrade
--ipconfig0 ip=dhcpDHCP für Netzwerk
--nameserverDNS-Server
--searchdomainSearch-Domain

10. Als Template markieren

Zum Schluss markieren wir die VM als Template:

1
qm template 9999

Cloud-Init Konfiguration anpassen

Um eine VM aus dem Template zu starten, kannst du die Cloud-Init Konfiguration anpassen:

1
2
qm set 9999 --ipconfig0 ip=192.168.1.100/24,gw=192.168.1.1
qm set 9999 --nameserver 8.8.8.8

Statische IP-Adresse

Mit Cloud-Init kannst du auch statische IP-Adressen konfigurieren:

1
qm set 9999 --ipconfig0 ip=192.168.1.100/24,gw=192.168.1.1

Cloud-Init Konfigurationsdateien

Cloud-Init verwendet zwei Hauptkonfigurationsdateien, die auf einem separaten Datenträger (CIDATA) gespeichert werden:

user-data

Die user-data Datei enthält die Benutzerkonfiguration. Erstelle eine ISO-Datei mit beiden Dateien:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
mkdir -p /tmp/cloud-init-iso
cd /tmp/cloud-init-iso

# user-data erstellen
cat > user-data << 'EOF'
#cloud-config
users:
  - name: admin
    sudo: ALL=(ALL) NOPASSWD:ALL
    groups: sudo
    shell: /bin/bash
    ssh-authorized-keys:
      - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAAAAxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx user@host-1
      - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAAAAyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy user@host-2
      - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAAAAzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz user@host-3

package_update: true
packages:
  - vim
  - curl
  - wget
  - git

runcmd:
  - systemctl enable sshd
  - timedatectl set-timezone Europe/Berlin
EOF

# meta-data erstellen
cat > meta-data << 'EOF'
instance-id: debian-13-vm
local-hostname: debian-13-vm
EOF

# ISO erstellen
genisoimage -output cloud-init.iso -volid cidata -rock -joliet meta-data user-data

Cloud-Init Module erklärt

Cloud-Init unterstützt viele Module. Die wichtigsten sind:

ModulBeschreibung
usersBenutzerkonten erstellen
packagesPakete installieren
package_updatePaketliste aktualisieren
package_upgradePakete aktualisieren
runcmdBefehle beim ersten Start ausführen
write_filesDateien schreiben
timezoneZeitzone setzen
localeLocale setzen
ssh_authorized_keysSSH-Keys für Benutzer
ssh_pwauthSSH-Passwort-Authentifizierung

Benutzer mit sudo-Rechten erstellen

Standardmäßig kann derDefault-Benutzer (admin) bereits sudo verwenden. Für zusätzliche Benutzer:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
users:
  - name: admin
    sudo: ALL=(ALL) NOPASSWD:ALL
    groups: sudo,adm
    shell: /bin/bash
    ssh-authorized-keys:
      - ssh-ed25519 AAAAC3N...
  - name:onitoring
    sudo: ALL=(ALL) NOPASSWD:ALL
    groups: sudo
    shell: /bin/bash

Pakete installieren

Um Pakete beim ersten Start zu installieren:

1
2
3
4
5
6
7
packages:
  - vim
  - curl
  - wget
  - git
  - htop
  - net-tools

Paketquellen (Repositories) konfigurieren

Um eigene Paketquellen hinzuzufügen:

1
2
3
4
5
write_files:
  - path: /etc/apt/sources.list.d/custom.list
    content: |
      deb https://repo.example.com/debian stable main
    permissions: "0644"

Oder für einen lokalen Mirror:

1
2
3
4
5
6
write_files:
  - path: /etc/apt/sources.list
    content: |
      deb http://192.168.1.10/debian bookworm main contrib
      deb http://192.168.1.10/debian bookworm-updates main contrib
    permissions: "0644"

Cloud-Init ISO in Proxmox einhängen

Nachdem du die ISO erstellt hast, kannst du sie als Cloud-Init Datenträger verwenden:

1
2
3
4
5
# ISO auf den Proxmox-Server kopieren
scp cloud-init.iso root@proxmox:/tmp/

# ISO als Cloud-Init Datenträger konfigurieren
qm set 9999 --ide2 local:iso/cloud-init.iso,media=cdrom

Automatische Konfiguration beim Klonen

Wenn du eine VM von einem Template klonst, kannst du die Cloud-Init Konfiguration direkt anpassen:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# VM klonen
qm clone 9999 100 --name debian-13-neu

# Cloud-Init Konfiguration setzen
qm set 100 --ipconfig0 ip=192.168.1.200/24,gw=192.168.1.1
qm set 100 --nameserver 192.168.1.1
qm set 100 --searchdomain localdomain

# SSH-Keys für neuen Benutzer
qm set 100 --sshkeys "ssh-ed25519 AAAAC3N..."

Netzwerk-Konfiguration

Für komplexere Netzwerk-Konfigurationen kannst du network-config verwenden:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
cat > network-config << 'EOF'
version: 2
ethernets:
  ens18:
    addresses:
      - 192.168.1.100/24
    gateway4: 192.168.1.1
    nameservers:
      addresses:
        - 192.168.1.1
        - 8.8.8.8
      search:
        - localdomain
EOF

Fazit

Mit Cloud-Init kannst du VMs in Proxmox schnell und automatisiert bereitstellen. Das Template muss nur einmal erstellt werden, und anschließend kannst du beliebig viele VMs davon klonen und mit individueller Konfiguration starten.

Die wichtigsten Vorteile sind:

  • Automatisierung der VM-Bereitstellung
  • Zentrale Konfiguration über Cloud-Init
  • Wiederverwendbare Templates
  • Flexible Netzwerk-Konfiguration

Komplettes Script

Hier ist das vollständige Script zur automatischen Erstellung eines Cloud-Init Templates:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#!/bin/bash

WORK_DIR="/opt/cloud_init"
IMAGE_URL="https://cloud.debian.org/images/cloud/trixie/latest/debian-13-generic-amd64.qcow2"
IMAGE_NAME="debian-13-generic-amd64.qcow2"
VM_ID="9999"
VM_NAME="debian-13"
VM_MEMORY="2048"
VM_CORES="4"
VM_BRIDGE="vmbr1"
STORAGE_LOCAL="local-zfs"
ROOT_PASSWORD="xxx"
NAMESERVER="192.168.1.1"
SEARCHDOMAIN="localdomain"
ENABLE_ROOT_SSH="true"

log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
}

error() {
    echo "[ERROR] $1" >&2
    exit 1
}

log "Starte Cloud-Init Template Erstellung..."

mkdir -p "$WORK_DIR" || error "Konnte Verzeichnis nicht erstellen"
cd "$WORK_DIR" || error "Konnte Verzeichnis nicht wechseln"

if [ ! -f "$IMAGE_NAME" ]; then
    log "Lade Cloud-Image herunter: $IMAGE_URL"
    wget "$IMAGE_URL" || error "Download fehlgeschlagen"
else
    log "Image existiert bereits: $IMAGE_NAME"
fi

log "Installiere qemu-guest-agent..."
virt-customize -a "$IMAGE_NAME" --install qemu-guest-agent || error "qemu-guest-agent Installation fehlgeschlagen"

log "Setze root-Passwort..."
virt-customize -a "$IMAGE_NAME" --root-password password:"$ROOT_PASSWORD" || error "Passwort-Setzung fehlgeschlagen"

log "Leere /etc/machine-id..."
virt-customize -a "$IMAGE_NAME" --run-command "echo -n > /etc/machine-id" || error "machine-id Leerung fehlgeschlagen"

log "Füge SSH-Keys zu root hinzu..."
virt-customize -a "$IMAGE_NAME" \
  --run-command "mkdir -p /root/.ssh && chmod 700 /root/.ssh" \
  --run-command "cat >> /root/.ssh/authorized_keys << 'SSHEOF'
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAAAAxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx user@host-1
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAAAAyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy user@host-2
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAAAAzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz user@host-3
SSHEOF" \
  --run-command "chmod 600 /root/.ssh/authorized_keys" || error "SSH-Keys hinzufügen fehlgeschlagen"

if [ "$ENABLE_ROOT_SSH" = "true" ]; then
    log "Aktiviere SSH Root-Login..."
    virt-customize -a "$IMAGE_NAME" \
      --run-command "sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config" || error "SSH-Konfiguration fehlgeschlagen"
fi

log "Erstelle VM mit ID $VM_ID..."
qm create "$VM_ID" \
  --name "$VM_NAME" \
  --memory "$VM_MEMORY" \
  --cores "$VM_CORES" \
  --net0 virtio,bridge="$VM_BRIDGE" || error "VM-Erstellung fehlgeschlagen"

log "Importiere Disk..."
qm importdisk "$VM_ID" "$IMAGE_NAME" "$STORAGE_LOCAL" || error "Disk-Import fehlgeschlagen"

log "Konfiguriere VM..."
qm set "$VM_ID" --scsihw virtio-scsi-single --scsi0 "$STORAGE_LOCAL:vm-$VM_ID-disk-0,cache=writeback,discard=on,ssd=1"
qm set "$VM_ID" --boot c --bootdisk scsi0
qm set "$VM_ID" --scsi2 "$STORAGE_LOCAL:cloudinit"
qm set "$VM_ID" --agent enabled=1
qm set "$VM_ID" --serial0 socket
qm set "$VM_ID" --vga serial0
qm set "$VM_ID" --cpu cputype=host
qm set "$VM_ID" --ostype l26
qm set "$VM_ID" --balloon "$VM_MEMORY"
qm set "$VM_ID" --ciupgrade 1
qm set "$VM_ID" --ipconfig0 ip=dhcp
qm set "$VM_ID" --nameserver "$NAMESERVER"
qm set "$VM_ID" --searchdomain "$SEARCHDOMAIN"

log "Markiere VM als Template..."
qm template "$VM_ID" || error "Template-Markierung fehlgeschlagen"

log "✓ Cloud-Init Template erfolgreich erstellt!"
log "Template ID: $VM_ID"
log "Template Name: $VM_NAME"