#!/bin/bash source ~/.bashrc # Create VMs from Cloud-Init Template with Automated Setup Scripts # This script creates VMs from a Cloud-Init template and applies service-specific install scripts set -e # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' log_info() { echo -e "${GREEN}[INFO]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" } log_step() { echo -e "${BLUE}[STEP]${NC} $1" } # Load environment variables if [ -f .env ]; then set -a source <(grep -v '^#' .env | grep -v '^$' | sed 's/#.*$//' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' | grep '=') set +a fi PVE_USERNAME="${PVE_USERNAME:-root@pam}" PVE_PASSWORD="${PVE_ROOT_PASS:-}" PROXMOX_URL="https://192.168.1.206:8006" PROXMOX_NODE="pve" STORAGE="${STORAGE:-local-lvm}" TEMPLATE_NAME="${TEMPLATE_NAME:-ubuntu-24.04-cloudinit}" # VM Configuration declare -A VMS=( [100]="cloudflare-tunnel:2:4096:40G:192.168.1.60:192.168.1.1:setup-cloudflare-tunnel.sh" [101]="k3s-master:4:8192:80G:192.168.1.188:192.168.1.1:setup-k3s.sh" [102]="git-server:2:4096:100G:192.168.1.121:192.168.1.1:setup-git-server.sh" [103]="observability:4:8192:200G:192.168.1.82:192.168.1.1:setup-observability.sh" ) # Get authentication ticket get_ticket() { local response=$(curl -k -s -d "username=$PVE_USERNAME&password=$PVE_PASSWORD" \ "$PROXMOX_URL/api2/json/access/ticket") local ticket=$(echo "$response" | grep -o '"ticket":"[^"]*' | cut -d'"' -f4) local csrf=$(echo "$response" | grep -o '"CSRFPreventionToken":"[^"]*' | cut -d'"' -f4) if [ -z "$ticket" ] || [ -z "$csrf" ]; then log_error "Failed to authenticate with Proxmox" return 1 fi echo "$ticket|$csrf" } # Read install script and create Cloud-Init user-data create_cloud_init_user_data() { local script_path=$1 local vm_name=$2 local ip_address=$3 local gateway=$4 if [ ! -f "$script_path" ]; then log_error "Install script not found: $script_path" return 1 fi local script_content=$(cat "$script_path" | base64 -w 0) cat < "$user_data_file" log_info "Cloud-Init user-data created: $user_data_file" # Upload user-data to Proxmox (requires manual step or SCP) log_warn "Note: Cloud-Init user-data needs to be uploaded to Proxmox storage" log_info "You can:" log_info " 1. Upload $user_data_file to Proxmox storage manually" log_info " 2. Or use cicustom parameter in API call" # Clone template to create VM log_info "Cloning template $TEMPLATE_NAME to VM $vmid..." local clone_response=$(curl -k -s -X POST \ -H "Cookie: PVEAuthCookie=$ticket" \ -H "CSRFPreventionToken: $csrf" \ -d "newid=$vmid" \ -d "name=$name" \ "$PROXMOX_URL/api2/json/nodes/$PROXMOX_NODE/qemu/$TEMPLATE_NAME/clone") if echo "$clone_response" | grep -q '"errors"'; then log_error "Failed to clone template: $clone_response" return 1 fi log_info "Template cloned successfully" # Wait for clone to complete sleep 5 # Configure VM log_info "Configuring VM..." # Set CPU, memory, disk curl -k -s -X PUT \ -H "Cookie: PVEAuthCookie=$ticket" \ -H "CSRFPreventionToken: $csrf" \ -d "cores=$cores" \ -d "memory=$memory" \ -d "net0=virtio,bridge=vmbr0" \ "$PROXMOX_URL/api2/json/nodes/$PROXMOX_NODE/qemu/$vmid/config" > /dev/null # Configure Cloud-Init curl -k -s -X PUT \ -H "Cookie: PVEAuthCookie=$ticket" \ -H "CSRFPreventionToken: $csrf" \ -d "ipconfig0=ip=${ip_address}/24,gw=${gateway}" \ -d "ciuser=ubuntu" \ "$PROXMOX_URL/api2/json/nodes/$PROXMOX_NODE/qemu/$vmid/config" > /dev/null log_info "✓ VM $vmid configured" # Cleanup rm -f "$user_data_file" } main() { echo "=========================================" echo "Create VMs from Cloud-Init Template" echo "=========================================" echo "" if [ -z "$PVE_PASSWORD" ]; then log_error "PVE_ROOT_PASS not set in .env" exit 1 fi if [ -z "$TEMPLATE_NAME" ]; then log_error "TEMPLATE_NAME not set. Create template first." log_info "See: scripts/create-proxmox-template.sh" exit 1 fi # Authenticate auth=$(get_ticket) if [ $? -ne 0 ]; then exit 1 fi log_step "Creating VMs from template: $TEMPLATE_NAME" echo "" # Create each VM for vmid in 100 101 102 103; do IFS=':' read -r name cores memory disk_size ip_address gateway install_script <<< "${VMS[$vmid]}" if create_vm_from_template "$auth" "$vmid" "$name" "$cores" "$memory" "$disk_size" "$ip_address" "$gateway" "$install_script"; then log_info "✓ VM $vmid ($name) created successfully" else log_error "✗ Failed to create VM $vmid" fi echo "" done log_info "=========================================" log_info "VM Creation Complete" log_info "=========================================" echo "" log_warn "Next steps:" echo " 1. Start each VM" echo " 2. VM will boot and run install script automatically" echo " 3. Check VM console for installation progress" echo " 4. SSH to VM after installation completes" } main "$@"