diff --git a/scripts/create-vm.sh b/scripts/create-vm.sh new file mode 100755 index 0000000..96011aa --- /dev/null +++ b/scripts/create-vm.sh @@ -0,0 +1,341 @@ +#!/bin/bash +# create-vm.sh +# Script per creare singole VM su Proxmox con parametri personalizzabili +# Uso: ./create-vm.sh [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 [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." + 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."