#!/usr/bin/env bash # Deploy Miracles In Motion Web Platform to pve2 # React + Vite web application for nonprofit organization set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' log_info() { echo -e "${BLUE}[INFO]${NC} $1"; } log_success() { echo -e "${GREEN}[✓]${NC} $1"; } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } log_error() { echo -e "${RED}[ERROR]${NC} $1"; } # Configuration PROXMOX_NODE="pve2" PROXMOX_HOST="192.168.11.12" PROXMOX_STORAGE="${PROXMOX_STORAGE:-thin4}" CONTAINER_OS_TEMPLATE="local:vztmpl/ubuntu-22.04-standard_22.04-1_amd64.tar.zst" # Miracles In Motion Configuration # Using Sankofa service layer VLAN 160 (10.160.0.0/22) MIM_VLAN="160" MIM_SUBNET="10.160.0.0/22" MIM_GATEWAY="10.160.0.1" # VMID Allocation (within Sankofa range: 7800-8999) VMID_MIM_WEB=7810 VMID_MIM_API=7811 # Service IPs (VLAN 160) MIM_WEB_IP="10.160.0.20" MIM_API_IP="10.160.0.21" # Resource allocation MIM_WEB_MEMORY="4096" # 4GB MIM_WEB_CORES="4" MIM_WEB_DISK="50" # 50GB MIM_API_MEMORY="2048" # 2GB MIM_API_CORES="2" MIM_API_DISK="30" # 30GB # Project paths MIM_PROJECT_PATH="/home/intlc/projects/proxmox/miracles_in_motion" MIM_DEPLOY_PATH="/opt/miracles-in-motion" # SSH function ssh_pve2() { ssh -o StrictHostKeyChecking=no -o ConnectTimeout=5 root@"$PROXMOX_HOST" "$@" } # Check if container exists container_exists() { local vmid=$1 ssh_pve2 "pct list 2>/dev/null | grep -q '^\s*$vmid\s'" 2>/dev/null } # Create Miracles In Motion container create_mim_container() { local vmid=$1 local hostname=$2 local ip_address=$3 local memory=$4 local cores=$5 local disk=$6 local service_type=$7 log_info "Creating Miracles In Motion $service_type: $hostname (VMID: $vmid, IP: $ip_address)" if container_exists "$vmid"; then log_warn "Container $vmid ($hostname) already exists, skipping creation" return 0 fi # Network configuration - using DHCP (VLAN tagging configured at bridge level) local network_config="bridge=vmbr0,name=eth0,ip=dhcp,type=veth" log_info "Creating container $vmid on $PROXMOX_NODE..." ssh_pve2 "pct create $vmid \ $CONTAINER_OS_TEMPLATE \ --storage $PROXMOX_STORAGE \ --hostname $hostname \ --memory $memory \ --cores $cores \ --rootfs $PROXMOX_STORAGE:$disk \ --net0 '$network_config' \ --unprivileged 1 \ --swap 512 \ --onboot 1 \ --timezone America/Los_Angeles \ --features nesting=1,keyctl=1" 2>&1 if container_exists "$vmid"; then log_success "Container $vmid created successfully" # Start container log_info "Starting container $vmid..." ssh_pve2 "pct start $vmid" 2>&1 || true # Wait for container to be ready log_info "Waiting for container to be ready..." sleep 5 # Basic setup log_info "Configuring container $vmid..." ssh_pve2 "pct exec $vmid -- bash -c 'export DEBIAN_FRONTEND=noninteractive; apt-get update -qq && apt-get install -y -qq curl wget git build-essential'" 2>&1 | grep -vE "(perl: warning|locale:)" || true log_success "Miracles In Motion $service_type container $vmid ($hostname) deployed successfully" return 0 else log_error "Failed to create container $vmid" return 1 fi } # Setup web service in container setup_web_service() { local vmid=$1 local hostname=$2 log_info "Setting up web service in container $vmid..." # Install Node.js 18+ log_info "Installing Node.js..." ssh_pve2 "pct exec $vmid -- bash -c 'curl -fsSL https://deb.nodesource.com/setup_18.x | bash - && apt-get install -y nodejs'" 2>&1 | grep -vE "(perl: warning|locale:)" || true # Install nginx for serving static files log_info "Installing nginx..." ssh_pve2 "pct exec $vmid -- bash -c 'apt-get install -y nginx'" 2>&1 | grep -vE "(perl: warning|locale:)" || true # Create deployment directory ssh_pve2 "pct exec $vmid -- bash -c 'mkdir -p $MIM_DEPLOY_PATH'" 2>&1 log_success "Web service setup complete for container $vmid" } # Copy project to container copy_project_to_container() { local vmid=$1 log_info "Copying project files to container $vmid..." # Create a tarball of the project (excluding node_modules and dist) log_info "Creating project archive..." cd "$PROJECT_ROOT" tar --exclude='node_modules' \ --exclude='dist' \ --exclude='.git' \ --exclude='*.log' \ -czf /tmp/miracles-in-motion.tar.gz -C miracles_in_motion . # Copy to container log_info "Transferring project to container..." scp -o StrictHostKeyChecking=no /tmp/miracles-in-motion.tar.gz root@"$PROXMOX_HOST":/tmp/ ssh_pve2 "pct push $vmid /tmp/miracles-in-motion.tar.gz /tmp/miracles-in-motion.tar.gz" # Extract in container log_info "Extracting project in container..." ssh_pve2 "pct exec $vmid -- bash -c 'cd $MIM_DEPLOY_PATH && tar -xzf /tmp/miracles-in-motion.tar.gz && rm /tmp/miracles-in-motion.tar.gz'" # Cleanup local tarball rm -f /tmp/miracles-in-motion.tar.gz log_success "Project copied to container $vmid" } # Build and configure web application build_web_application() { local vmid=$1 log_info "Building web application in container $vmid..." # Install dependencies log_info "Installing npm dependencies..." ssh_pve2 "pct exec $vmid -- bash -c 'cd $MIM_DEPLOY_PATH && npm install --legacy-peer-deps'" 2>&1 | tail -20 # Build the application log_info "Building application..." ssh_pve2 "pct exec $vmid -- bash -c 'cd $MIM_DEPLOY_PATH && npm run build'" 2>&1 | tail -20 # Configure nginx to serve the built files log_info "Configuring nginx..." ssh_pve2 "pct exec $vmid -- bash -c 'cat > /etc/nginx/sites-available/miracles-in-motion <&1 log_success "Web application built and configured" } # Main deployment main() { echo "" log_info "=========================================" log_info "Miracles In Motion Deployment to pve2" log_info "=========================================" echo "" log_info "Target Node: $PROXMOX_NODE ($PROXMOX_HOST)" log_info "VLAN: $MIM_VLAN ($MIM_SUBNET)" log_info "VMID Range: 7810-7811 (within Sankofa range 7800-8999)" log_info "Project Path: $MIM_PROJECT_PATH" echo "" # Check if project exists if [[ ! -d "$MIM_PROJECT_PATH" ]]; then log_error "Project not found at $MIM_PROJECT_PATH" exit 1 fi log_success "Project found at $MIM_PROJECT_PATH" echo "" # Check connectivity to pve2 log_info "Checking connectivity to $PROXMOX_NODE..." if ! ssh_pve2 "pvecm status >/dev/null 2>&1"; then log_error "Cannot connect to $PROXMOX_NODE. Please check SSH access." exit 1 fi log_success "Connected to $PROXMOX_NODE" echo "" # Check if containers already exist log_info "Checking existing Miracles In Motion containers..." existing_containers=() if container_exists "$VMID_MIM_WEB"; then existing_containers+=("$VMID_MIM_WEB:mim-web-1") log_warn "Container $VMID_MIM_WEB (mim-web-1) already exists" fi if container_exists "$VMID_MIM_API"; then existing_containers+=("$VMID_MIM_API:mim-api-1") log_warn "Container $VMID_MIM_API (mim-api-1) already exists" fi if [[ ${#existing_containers[@]} -gt 0 ]]; then log_warn "Some Miracles In Motion containers already exist:" for container in "${existing_containers[@]}"; do echo " - $container" done echo "" read -p "Continue with deployment? (y/N): " -n 1 -r echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then log_info "Deployment cancelled" exit 0 fi fi echo "" # Deploy Miracles In Motion Web log_info "Deploying Miracles In Motion Web service..." create_mim_container \ "$VMID_MIM_WEB" \ "mim-web-1" \ "$MIM_WEB_IP" \ "$MIM_WEB_MEMORY" \ "$MIM_WEB_CORES" \ "$MIM_WEB_DISK" \ "Web" echo "" # Setup web service setup_web_service "$VMID_MIM_WEB" "mim-web-1" echo "" # Copy project to container copy_project_to_container "$VMID_MIM_WEB" echo "" # Build and configure build_web_application "$VMID_MIM_WEB" echo "" # Deploy API service (optional, for future use) log_info "Deploying Miracles In Motion API service (optional)..." create_mim_container \ "$VMID_MIM_API" \ "mim-api-1" \ "$MIM_API_IP" \ "$MIM_API_MEMORY" \ "$MIM_API_CORES" \ "$MIM_API_DISK" \ "API" echo "" # Summary log_success "=========================================" log_success "Miracles In Motion Deployment Complete" log_success "=========================================" echo "" log_info "Deployed containers on $PROXMOX_NODE:" echo " - VMID $VMID_MIM_WEB: mim-web-1 ($MIM_WEB_IP) - Web Frontend" echo " - VMID $VMID_MIM_API: mim-api-1 ($MIM_API_IP) - API Service (ready for setup)" echo "" log_info "Next steps:" echo " 1. Configure environment variables in containers" echo " 2. Set up API service if needed" echo " 3. Configure Cloudflare tunnels for external access" echo " 4. Set up SSL certificates" echo " 5. Configure monitoring and logging" echo "" log_info "Web service should be accessible at: http://" echo "" } # Run main function main "$@"