最終更新 3 weeks ago

Working version of my proxmox template creation script. It'll be used to provision Packer with necessary templates in order to build it's image.

修正履歴 cefd88f70257701ca3d61c4b526e602fca0a9017

create-pve-template.sh Raw
1#!/bin/bash
2set -e
3
4TEMPLATE_URL="https://cloud-images.ubuntu.com/plucky/current/plucky-server-cloudimg-amd64.img"
5VMID=9001
6TEMPLATE_NAME="ubuntu-25.04-cloudimg-temp"
7STORAGE="local-lvm"
8SKIP_DISK_SETUP=false
9VMID_CUSTOM=false # Track if VMID was explicitly set
10
11# Parser avec getopt
12OPTS=$(getopt -o "" --long vmid:,template:,storage:,skip-disk -n 'script' -- "$@")
13eval set -- "$OPTS"
14
15while true; do
16 case "$1" in
17 --vmid) VMID="$2"; VMID_CUSTOM=true; shift 2 ;;
18 --template) TEMPLATE_NAME="$2"; shift 2 ;;
19 --storage) STORAGE="$2"; shift 2 ;;
20 --skip-disk) SKIP_DISK_SETUP=true; shift ;;
21 --) shift; break ;;
22 *) break ;;
23 esac
24done
25
26# Detect if we need sudo (non-root user)
27if [ "$(id -u)" -ne 0 ]; then
28 echo "Running as non-root user, will use sudo for qm commands"
29 SUDO="sudo"
30else
31 SUDO=""
32fi
33
34# Check if VMID already exists
35ORIGINAL_VMID=$VMID
36echo "Checking if VMID $VMID is available..."
37if $SUDO qm status "$VMID" &>/dev/null; then
38 # VMID exists, check if it's already a template
39 IS_TEMPLATE=$($SUDO qm config "$VMID" | grep -q "^template:" && echo "yes" || echo "no")
40
41 if [ "$IS_TEMPLATE" = "yes" ]; then
42 echo "✓ VMID $VMID already exists and is a template (idempotent)"
43 echo ""
44 echo "========================================="
45 echo "Template already exists!"
46 echo " VMID: $VMID"
47 echo "========================================="
48 echo ""
49 echo "Skipping template creation (already exists)."
50 exit 0
51 else
52 echo "⚠ VMID $VMID already exists but is NOT a template!"
53
54 # If VMID is the default (9001) and was not explicitly set, error out
55 # This ensures Packer can find the expected template
56 if [ "$VMID_CUSTOM" = "false" ]; then
57 echo ""
58 echo "========================================="
59 echo "ERROR: Default VMID $VMID is occupied!"
60 echo "========================================="
61 echo ""
62 echo "VMID $VMID exists but is not a template."
63 echo ""
64 echo "Solutions:"
65 echo " 1. Delete the VM: qm destroy $VMID"
66 echo " 2. Convert it to template: qm template $VMID"
67 echo " 3. Use a different VMID: $0 --vmid XXXX"
68 echo ""
69 exit 1
70 fi
71
72 # If VMID was explicitly set, auto-increment to next available
73 echo "Finding next available VMID..."
74 MAX_VMID=$($SUDO qm list | awk 'NR>1 {print $1}' | sort -n | tail -1)
75
76 if [ -z "$MAX_VMID" ]; then
77 # No VMs exist, use the requested VMID
78 echo "No existing VMs found, using VMID $VMID"
79 else
80 # Use max VMID + 1
81 VMID=$((MAX_VMID + 1))
82 echo "✓ Using next available VMID: $VMID (max existing: $MAX_VMID)"
83 fi
84 fi
85else
86 echo "✓ VMID $VMID is available"
87fi
88
89# Récupérer les clés SSH
90SSH_KEYS=$(curl -s https://gist.vorpax.dev/vorpax/ssh/raw/HEAD/ssh-keys.pub | sed 's/%20/ /g; s/%0A/\n/g; s/%3D/=/g; s/%2F/\//g; s/%40/@/g; s/%3A/:/g')
91
92cd /tmp
93
94if [ "$SKIP_DISK_SETUP" = false ]; then
95 echo "Downloading cloud image..."
96 wget -O "${TEMPLATE_NAME}_disk" "$TEMPLATE_URL"
97
98 # Créer la VM avec une config minimale
99 $SUDO qm create "$VMID" \
100 --name "$TEMPLATE_NAME" \
101 --memory 3072 \
102 --cores 3 \
103 --scsihw virtio-scsi-pci \
104 --serial0 socket \
105 --vga serial0 \
106 --net0 virtio,bridge=vmbr0
107
108 # Importer le disque
109 echo "Importing disk..."
110 $SUDO qm importdisk "$VMID" "${TEMPLATE_NAME}_disk" "$STORAGE"
111
112 # Extraire le chemin complet du disque unused (la partie APRÈS "unused0: ")
113 DISK_PATH=$($SUDO qm config "$VMID" | grep "^unused0:" | awk '{print $2}')
114
115 if [ -z "$DISK_PATH" ]; then
116 echo "ERROR: Could not find unused disk"
117 exit 1
118 fi
119
120 echo "Attaching disk: $DISK_PATH"
121 $SUDO qm set "$VMID" --scsi0 "$DISK_PATH"
122
123 # Cleanup temporary downloaded file
124 rm -f "${TEMPLATE_NAME}_disk"
125else
126 echo "Skipping disk setup (--skip-disk flag)"
127fi
128
129# Créer le dossier des clés SSH
130SSH_KEYS_DIR="ssh_keys_${VMID}"
131mkdir -p "$SSH_KEYS_DIR"
132
133# Écrire toutes les clés dans un seul fichier
134SSH_KEY_FILE="${SSH_KEYS_DIR}/authorized_keys"
135echo "$SSH_KEYS" > "$SSH_KEY_FILE"
136echo "SSH keys written to $SSH_KEY_FILE"
137
138# Configurer cloud-init et le reste
139$SUDO qm set "$VMID" \
140 --sshkey "$SSH_KEY_FILE" \
141 --ide2 "${STORAGE}:cloudinit" \
142 --boot order=scsi0 \
143 --ciuser packer \
144 --searchdomain .lab.internal \
145 --ipconfig0 ip=dhcp
146 --bios ovmf
147
148# Convertir en template
149$SUDO qm template "$VMID"
150
151echo ""
152echo "========================================="
153echo "✓ Template created successfully!"
154echo " VMID: $VMID"
155echo " Name: $TEMPLATE_NAME"
156echo "========================================="
157echo ""
158echo "Template is ready for Packer to clone and provision."