#!/bin/bash source ~/.bashrc # Deploy Service VMs via Proxmox API # Can be executed without SSH access set -e SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" # Load environment variables if [ -f "$PROJECT_ROOT/.env" ]; then set -a source <(grep -v '^#' "$PROJECT_ROOT/.env" | grep -v '^$' | sed 's/#.*$//' | grep '=') set +a fi # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' PVE_USERNAME="${PVE_USERNAME:-root@pam}" PVE_PASSWORD="${PVE_ROOT_PASS:-}" PROXMOX_URL="${PROXMOX_ML110_URL:-https://192.168.1.206:8006}" PROXMOX_NODE="${PROXMOX_NODE:-pve}" TEMPLATE_VMID="${TEMPLATE_VMID:-9000}" log_info() { echo -e "${GREEN}[INFO]${NC} $1" } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" } get_api_token() { local response=$(curl -s -k --connect-timeout 10 --max-time 15 \ -d "username=$PVE_USERNAME&password=$PVE_PASSWORD" \ "$PROXMOX_URL/api2/json/access/ticket" 2>&1) if echo "$response" | grep -q '"data"'; then local ticket=$(echo "$response" | grep -o '"ticket":"[^"]*' | cut -d'"' -f4) local csrf_token=$(echo "$response" | grep -o '"CSRFPreventionToken":"[^"]*' | cut -d'"' -f4) echo "$ticket|$csrf_token" else echo "" fi } create_vm_from_template() { local vmid=$1 local name=$2 local ip=$3 local gateway=$4 local cores=$5 local memory=$6 local disk_size=$7 local bridge="${8:-vmbr0}" log_info "Creating VM $vmid: $name" local tokens=$(get_api_token) if [ -z "$tokens" ]; then log_error "Failed to authenticate with Proxmox" return 1 fi local ticket=$(echo "$tokens" | cut -d'|' -f1) local csrf_token=$(echo "$tokens" | cut -d'|' -f2) # Check if template exists local template_check=$(curl -s -k -H "Cookie: PVEAuthCookie=$ticket" \ -H "CSRFPreventionToken: $csrf_token" \ "$PROXMOX_URL/api2/json/nodes/$PROXMOX_NODE/qemu/$TEMPLATE_VMID/status/current" 2>&1) if ! echo "$template_check" | grep -q '"data"'; then log_error "Template VM $TEMPLATE_VMID not found or not accessible" return 1 fi # Clone VM from template log_info "Cloning from template $TEMPLATE_VMID..." local clone_response=$(curl -s -k -X POST \ -H "Cookie: PVEAuthCookie=$ticket" \ -H "CSRFPreventionToken: $csrf_token" \ -d "newid=$vmid" \ -d "name=$name" \ "$PROXMOX_URL/api2/json/nodes/$PROXMOX_NODE/qemu/$TEMPLATE_VMID/clone" 2>&1) if echo "$clone_response" | grep -q '"data"'; then log_info "VM cloned successfully" else log_error "Failed to clone VM: $clone_response" return 1 fi # Wait for clone to complete sleep 5 # Configure VM log_info "Configuring VM $vmid..." # Set CPU and memory curl -s -k -X PUT \ -H "Cookie: PVEAuthCookie=$ticket" \ -H "CSRFPreventionToken: $csrf_token" \ -d "cores=$cores" \ -d "memory=$memory" \ "$PROXMOX_URL/api2/json/nodes/$PROXMOX_NODE/qemu/$vmid/config" > /dev/null # Set network and IP curl -s -k -X PUT \ -H "Cookie: PVEAuthCookie=$ticket" \ -H "CSRFPreventionToken: $csrf_token" \ -d "net0=virtio,bridge=$bridge" \ -d "ipconfig0=ip=$ip/24,gw=$gateway" \ "$PROXMOX_URL/api2/json/nodes/$PROXMOX_NODE/qemu/$vmid/config" > /dev/null log_info "VM $vmid configured successfully" return 0 } main() { log_info "Deploying Service VMs via Proxmox API" if [ -z "$PVE_PASSWORD" ]; then log_error "PVE_ROOT_PASS not set in .env" exit 1 fi # VM definitions # Format: vmid name ip gateway cores memory_mb disk_gb bridge local vms=( "100 cloudflare-tunnel 192.168.1.60 192.168.1.254 2 4096 40 vmbr0" "101 k3s-master 192.168.1.188 192.168.1.254 4 8192 80 vmbr0" "102 git-server 192.168.1.121 192.168.1.254 4 8192 100 vmbr0" "103 observability 192.168.1.82 192.168.1.254 4 8192 200 vmbr0" ) for vm_spec in "${vms[@]}"; do read -r vmid name ip gateway cores memory disk bridge <<< "$vm_spec" # Check if VM already exists local tokens=$(get_api_token) local ticket=$(echo "$tokens" | cut -d'|' -f1) local csrf_token=$(echo "$tokens" | cut -d'|' -f2) local vm_check=$(curl -s -k -H "Cookie: PVEAuthCookie=$ticket" \ -H "CSRFPreventionToken: $csrf_token" \ "$PROXMOX_URL/api2/json/nodes/$PROXMOX_NODE/qemu/$vmid/status/current" 2>&1) if echo "$vm_check" | grep -q '"data"'; then log_warn "VM $vmid ($name) already exists, skipping" continue fi create_vm_from_template "$vmid" "$name" "$ip" "$gateway" "$cores" "$memory" "$disk" "$bridge" done log_info "VM deployment completed!" log_warn "Next steps:" log_warn " 1. Install Ubuntu 24.04 on each VM via Proxmox console" log_warn " 2. Configure services after OS installation" } main "$@"