Files
proxmox-ha-setup/scripts/create-vm.sh
2025-11-29 18:14:49 +01:00

342 lines
9.9 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# create-vm.sh
# Script per creare singole VM su Proxmox con parametri personalizzabili
# Uso: ./create-vm.sh <vm_id> <vm_name> [cores] [memory_mb] [disk_size]
# Esempio: ./create-vm.sh 203 web-server 4 8192 50G
set -e
# ==================== CONFIGURAZIONE ====================
# Parametri da riga di comando
if [ "$#" -lt 2 ]; then
echo "Uso: $0 <vm_id> <vm_name> [cores] [memory_mb] [disk_size]"
echo ""
echo "Parametri obbligatori:"
echo " vm_id - ID della VM Proxmox (es: 203)"
echo " vm_name - Nome della VM (es: web-server)"
echo ""
echo "Parametri opzionali (valori di default):"
echo " cores - Numero di CPU cores (default: 4)"
echo " memory_mb - RAM in MB (default: 8192)"
echo " disk_size - Dimensione disco con unità (default: 50G)"
echo ""
echo "Esempi:"
echo " $0 203 web-server # VM con valori default"
echo " $0 203 web-server 2 4096 30G # VM con 2 cores, 4GB RAM, 30GB disco"
echo ""
echo "Nota: L'IP sarà automaticamente 192.168.1.<vm_id>"
exit 1
fi
VM_ID=$1
VM_NAME=$2
VM_IP="192.168.1.${VM_ID}"
# Parametri opzionali con valori di default
CORES=${3:-2}
MEMORY=${4:-4096}
DISK_SIZE=${5:-20G}
# Configurazione Proxmox
PVE_NODE="server"
STORAGE="sddmirror" # Storage principale per i dischi VM (supporta Images)
BRIDGE="vmbr0"
# FIX: Due variabili per lo storage
CLOUDINIT_VOL_STORAGE="$STORAGE" # sddmirror: Useremo lo storage principale che supporta i volumi disco Cloud-Init (Images)
SNIPPET_STORAGE="local" # local: Manteniamo 'local' per i file snippet YAML
# Configurazione di rete
GATEWAY="192.168.1.1"
NETMASK="24"
DNS="8.8.8.8"
# Template
TEMPLATE_ID=9000
UBUNTU_IMAGE_URL="https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img"
UBUNTU_IMAGE_NAME="ubuntu-24.04-cloudimg.img"
# Credenziali
SSH_PUBLIC_KEY="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOyva+cul3WOW3ct53a0QMRTkhtKvA2QpJI0p8bv48tH alex@alex-XPS-15-9570"
ROOT_PASSWORD="TempProxmox123!"
# Directory applicazioni
APP_DIR="/opt/myapp"
# Directory per gli snippet
SNIPPETS_DIR="/var/lib/vz/snippets"
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
# ==================== FUNZIONI ====================
print_header() {
echo -e "${BLUE}================================================${NC}"
echo -e "${BLUE}$1${NC}"
echo -e "${BLUE}================================================${NC}"
}
print_success() { echo -e "${GREEN}$1${NC}"; }
print_warning() { echo -e "${YELLOW}$1${NC}"; }
print_error() { echo -e "${RED}$1${NC}"; }
print_info() { echo -e "${BLUE} $1${NC}"; }
check_command() {
if ! command -v $1 &> /dev/null; then
print_error "$1 non trovato. Installalo: apt install $1"
exit 1
fi
}
# Funzione per generare il file user-data YAML personalizzato (come snippet)
create_custom_user_data() {
local vm_name=$1
local output_file="/tmp/${vm_name}-user-data.yaml"
# Crea user-data YAML
cat > "$output_file" << EOF
#cloud-config
hostname: $vm_name
fqdn: ${vm_name}.local
manage_etc_hosts: true
users:
- name: root
ssh_authorized_keys:
- $SSH_PUBLIC_KEY
lock_passwd: false
shell: /bin/bash
chpasswd:
list: |
root:$ROOT_PASSWORD
expire: false
ssh_pwauth: true
disable_root: false
packages:
- curl
- wget
- git
- htop
- net-tools
- qemu-guest-agent
runcmd:
# Install Docker
- mkdir -p /etc/apt/keyrings
- curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
- echo "deb [arch=\$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \$(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
- apt-get update
- apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
- systemctl enable docker
- systemctl start docker
- systemctl enable qemu-guest-agent
- systemctl start qemu-guest-agent
# Configure sysctl
- echo "net.ipv4.ip_nonlocal_bind=1" >> /etc/sysctl.conf
- echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
- sysctl -p
# Create app directory
- mkdir -p $APP_DIR
- chown -R root:root $APP_DIR
# Ensure SSH is properly configured
- sed -i 's/#*PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config
- sed -i 's/#*PubkeyAuthentication.*/PubkeyAuthentication yes/' /etc/ssh/sshd_config
- systemctl restart sshd
power_state:
mode: reboot
timeout: 300
condition: true
EOF
echo "$output_file"
}
# ==================== SCRIPT PRINCIPALE ====================
print_header "CREAZIONE VM SU PROXMOX"
# Check prerequisites
print_info "Verifica prerequisiti..."
check_command "qm"
print_success "Prerequisiti OK"
# Validazione parametri
if ! [[ "$VM_ID" =~ ^[0-9]+$ ]]; then
print_error "VM_ID deve essere un numero valido"
exit 1
fi
if [ "$VM_ID" -eq "$TEMPLATE_ID" ]; then
print_error "VM_ID $VM_ID è riservato per il template"
exit 1
fi
if ! [[ "$CORES" =~ ^[0-9]+$ ]] || [ "$CORES" -lt 1 ]; then
print_error "CORES deve essere un numero positivo (valore fornito: $CORES)"
exit 1
fi
if ! [[ "$MEMORY" =~ ^[0-9]+$ ]] || [ "$MEMORY" -lt 512 ]; then
print_error "MEMORY deve essere almeno 512 MB (valore fornito: $MEMORY)"
exit 1
fi
if ! [[ "$DISK_SIZE" =~ ^[0-9]+[GMK]$ ]]; then
print_error "DISK_SIZE deve essere nel formato numero+unità (es: 50G, 500M) (valore fornito: $DISK_SIZE)"
exit 1
fi
print_info "Configurazione VM:"
print_info " ID: $VM_ID"
print_info " Nome: $VM_NAME"
print_info " IP: $VM_IP"
print_info " CPU Cores: $CORES"
print_info " RAM: ${MEMORY}MB"
print_info " Disco: $DISK_SIZE"
# Crea la directory snippet se non esiste
mkdir -p "$SNIPPETS_DIR"
# Verifica se la VM esiste già
if qm status $VM_ID &>/dev/null; then
print_warning "VM $VM_ID già esistente!"
read -p "Vuoi eliminarlo e ricrearlo? (y/N) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
print_info "Arresto VM $VM_ID..."
qm stop $VM_ID || true
sleep 3
print_info "Eliminazione VM $VM_ID..."
qm destroy $VM_ID
# Pulizia dei file custom
rm -f "${SNIPPETS_DIR}/${VM_ID}-user-data.yaml"
print_success "VM $VM_ID eliminata"
else
print_error "Operazione annullata"
exit 1
fi
fi
# ==================== VERIFICA/CREA TEMPLATE ====================
print_header "STEP 1: Verifica Template Cloud-Init"
if ! qm status $TEMPLATE_ID &>/dev/null; then
print_info "Template non trovato. Creazione in corso..."
cd /tmp
if [ ! -f "$UBUNTU_IMAGE_NAME" ]; then
print_info "Download Ubuntu Cloud Image..."
wget -q --show-progress $UBUNTU_IMAGE_URL -O $UBUNTU_IMAGE_NAME
fi
print_info "Creazione template VM..."
qm create $TEMPLATE_ID --name ubuntu-cloud-template --memory $MEMORY --net0 virtio,bridge=$BRIDGE --cores $CORES
# Importa il disco
qm importdisk $TEMPLATE_ID $UBUNTU_IMAGE_NAME $STORAGE &>/dev/null
qm set $TEMPLATE_ID --scsihw virtio-scsi-single --scsi0 ${STORAGE}:vm-${TEMPLATE_ID}-disk-0
# Configurazione Cloud-Init
qm set $TEMPLATE_ID --delete ide0 2>/dev/null || true
qm set $TEMPLATE_ID --delete ide2 2>/dev/null || true
# Aggiungi il drive per cloud-init
qm set $TEMPLATE_ID --ide2 ${CLOUDINIT_VOL_STORAGE}:cloudinit,format=raw
# Imposta configurazioni essenziali
qm set $TEMPLATE_ID --cpu x86-64-v2-AES
qm set $TEMPLATE_ID --agent enabled=1
qm set $TEMPLATE_ID --boot c --bootdisk scsi0
# Resize del disco del template
qm resize $TEMPLATE_ID scsi0 $DISK_SIZE &>/dev/null || true
qm template $TEMPLATE_ID
print_success "Template creato con successo"
else
print_success "Template già esistente"
fi
# ==================== CREA VM ====================
print_header "STEP 2: Creazione VM $VM_NAME (ID: $VM_ID, IP: $VM_IP)"
print_info "Clonazione template..."
qm clone $TEMPLATE_ID $VM_ID --name $VM_NAME --full
# 1. Crea il file user-data personalizzato
USER_DATA_FILE=$(create_custom_user_data $VM_NAME)
# 2. Crea il file SSH temporaneo
SSH_KEY_FILE="/tmp/${VM_NAME}_id_rsa.pub"
echo "$SSH_PUBLIC_KEY" > "$SSH_KEY_FILE"
print_info "Chiave SSH salvata in $SSH_KEY_FILE per l'iniezione."
# 3. Allega il file user-data personalizzato come snippet (cicustom)
SNIPPET_FILENAME="${VM_ID}-user-data.yaml"
# 4. Configura VM con tutti i dati di Cloud-Init
print_info "Iniezione configurazione Cloud-Init..."
qm set $VM_ID \
--ciuser root \
--sshkeys "$SSH_KEY_FILE" \
--ipconfig0 "ip=${VM_IP}/${NETMASK},gw=${GATEWAY}" \
--nameserver "${DNS}" \
--cicustom "user=${SNIPPET_STORAGE}:snippets/${SNIPPET_FILENAME}"
# 5. Sposta il file user-data nella directory snippets di Proxmox
mv "$USER_DATA_FILE" "${SNIPPETS_DIR}/${SNIPPET_FILENAME}"
# 6. PULIZIA: Rimuovi il file temporaneo della chiave SSH
rm "$SSH_KEY_FILE"
print_success "VM configurata e dati cloud-init iniettati"
# ==================== AVVIA VM ====================
print_header "STEP 3: Avvio della VM"
print_info "Avvio VM $VM_NAME ($VM_IP)..."
qm start $VM_ID
sleep 5
print_info "Attendo cloud-init (2-3 minuti). Il primo avvio può richiedere tempo per il resize e le installazioni."
sleep 180
# ==================== RIEPILOGO ====================
print_header "CREAZIONE VM COMPLETATA! 🎉"
print_info ""
print_info "Dettagli VM:"
print_info " Nome: $VM_NAME"
print_info " ID: $VM_ID"
print_info " IP: ${GREEN}$VM_IP${NC}"
print_info " Cores: $CORES"
print_info " Memory: ${MEMORY}MB"
print_info " Disk: $DISK_SIZE"
print_info ""
print_info "Credenziali:"
print_info " User: root"
print_info " Password: $ROOT_PASSWORD"
print_info " SSH Key: configurata"
print_info ""
print_info "Test connessione (attendere il riavvio causato da cloud-init se non funziona subito):"
print_info " ssh root@$VM_IP"
print_info ""
print_success "Setup completato! La VM ora ha IP statico $VM_IP, Docker installato e chiave SSH configurata."