Initial DevMatrix deployment scripts
This commit is contained in:
commit
1b5269136a
|
|
@ -0,0 +1,379 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# DevMatrix Setup Script for Proxmox
|
||||||
|
# Tailored for: Roberth's Proxmox Environment
|
||||||
|
# Network: vmbr1 | VM IDs: 300+ | Windows: LTSC IoT
|
||||||
|
# Run this script ON THE PROXMOX HOST as root
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# CONFIGURATION (User Specified)
|
||||||
|
# ============================================
|
||||||
|
NETWORK_BRIDGE="vmbr1"
|
||||||
|
VM_ID_START=300
|
||||||
|
PROXMOX_NODE="pve" # Change if your node has a different name
|
||||||
|
|
||||||
|
# VM IDs
|
||||||
|
MAIN_VMID=300 # OpenClaw DevMatrix (Ubuntu)
|
||||||
|
WIN_VMID=301 # Windows LTSC IoT Test VM
|
||||||
|
ANDROID_VMID=302 # Android Emulator VM
|
||||||
|
|
||||||
|
# Resource Allocation
|
||||||
|
MAIN_RAM=32768 # 32GB RAM for main dev VM
|
||||||
|
MAIN_CORES=16 # 16 CPU cores
|
||||||
|
MAIN_DISK=500 # 500GB primary disk
|
||||||
|
MAIN_SECONDARY=200 # 200GB secondary disk
|
||||||
|
|
||||||
|
WIN_RAM=16384 # 16GB RAM for Windows
|
||||||
|
WIN_CORES=8 # 8 CPU cores
|
||||||
|
WIN_DISK=150 # 150GB disk
|
||||||
|
|
||||||
|
ANDROID_RAM=8192 # 8GB RAM for Android
|
||||||
|
ANDROID_CORES=4 # 4 CPU cores
|
||||||
|
ANDROID_DISK=100 # 100GB disk
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# COLORS FOR OUTPUT
|
||||||
|
# ============================================
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
CYAN='\033[0;36m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
log() {
|
||||||
|
echo -e "${GREEN}[DevMatrix]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
warn() {
|
||||||
|
echo -e "${YELLOW}[Warning]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
error() {
|
||||||
|
echo -e "${RED}[Error]${NC} $1"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
info() {
|
||||||
|
echo -e "${CYAN}[Info]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# PRE-FLIGHT CHECKS
|
||||||
|
# ============================================
|
||||||
|
log "🔍 Running pre-flight checks..."
|
||||||
|
|
||||||
|
# Check if running as root
|
||||||
|
if [ "$EUID" -ne 0 ]; then
|
||||||
|
error "Please run as root (use: sudo bash $0)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if vmbr1 exists
|
||||||
|
if ! ip link show "$NETWORK_BRIDGE" &> /dev/null; then
|
||||||
|
error "Network bridge '$NETWORK_BRIDGE' not found!"
|
||||||
|
fi
|
||||||
|
log "✓ Network bridge '$NETWORK_BRIDGE' found"
|
||||||
|
|
||||||
|
# Check available storage
|
||||||
|
log "📦 Checking available storage..."
|
||||||
|
pvesm status
|
||||||
|
|
||||||
|
# Let user select storage
|
||||||
|
info "Available storage locations (select one for VM disks):"
|
||||||
|
pvesm status | grep -v "Name" | nl
|
||||||
|
echo ""
|
||||||
|
read -p "Enter the storage name to use (e.g., local-lvm, vm-storage): " STORAGE_NAME
|
||||||
|
|
||||||
|
if [ -z "$STORAGE_NAME" ]; then
|
||||||
|
error "Storage name cannot be empty"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Verify storage exists
|
||||||
|
if ! pvesm status | grep -q "^$STORAGE_NAME"; then
|
||||||
|
error "Storage '$STORAGE_NAME' not found"
|
||||||
|
fi
|
||||||
|
log "✓ Using storage: $STORAGE_NAME"
|
||||||
|
|
||||||
|
# Check if VM IDs are available
|
||||||
|
log "🔍 Checking VM ID availability..."
|
||||||
|
for vmid in $MAIN_VMID $WIN_VMID $ANDROID_VMID; do
|
||||||
|
if qm status "$vmid" &> /dev/null; then
|
||||||
|
error "VM ID $vmid already exists!"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
log "✓ VM IDs $MAIN_VMID, $WIN_VMID, $ANDROID_VMID are available"
|
||||||
|
|
||||||
|
# Check available resources
|
||||||
|
log "📊 Checking available resources..."
|
||||||
|
AVAILABLE_RAM=$(free -m | awk '/^Mem:/{print $7}')
|
||||||
|
AVAILABLE_DISK=$(pvesm status | grep "^$STORAGE_NAME" | awk '{print $4}' | sed 's/G//')
|
||||||
|
|
||||||
|
info "Available RAM: ${AVAILABLE_RAM}MB"
|
||||||
|
info "Available Disk: ${AVAILABLE_DISK}GB"
|
||||||
|
|
||||||
|
TOTAL_RAM_NEEDED=$((MAIN_RAM + WIN_RAM + ANDROID_RAM))
|
||||||
|
TOTAL_DISK_NEEDED=$((MAIN_DISK + MAIN_SECONDARY + WIN_DISK + ANDROID_DISK))
|
||||||
|
|
||||||
|
info "RAM needed: ${TOTAL_RAM_NEEDED}MB"
|
||||||
|
info "Disk needed: ${TOTAL_DISK_NEEDED}GB"
|
||||||
|
|
||||||
|
if [ "$AVAILABLE_RAM" -lt "$TOTAL_RAM_NEEDED" ]; then
|
||||||
|
warn "Low RAM! You may need to adjust VM memory"
|
||||||
|
read -p "Continue anyway? (y/N): " confirm
|
||||||
|
if [ "$confirm" != "y" ]; then exit 1; fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
log "✅ Pre-flight checks complete!"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# DOWNLOAD ISO IMAGES
|
||||||
|
# ============================================
|
||||||
|
log "⬇️ Checking for required ISO images..."
|
||||||
|
|
||||||
|
ISO_DIR="/var/lib/vz/template/iso"
|
||||||
|
mkdir -p "$ISO_DIR"
|
||||||
|
|
||||||
|
# Ubuntu 22.04 Server ISO
|
||||||
|
UBUNTU_ISO="$ISO_DIR/ubuntu-22.04.5-live-server-amd64.iso"
|
||||||
|
if [ -f "$UBUNTU_ISO" ]; then
|
||||||
|
log "✓ Ubuntu ISO already exists"
|
||||||
|
else
|
||||||
|
log "⬇️ Downloading Ubuntu 22.04 Server ISO..."
|
||||||
|
wget -O "$UBUNTU_ISO" \
|
||||||
|
"https://releases.ubuntu.com/22.04/ubuntu-22.04.5-live-server-amd64.iso" \
|
||||||
|
--progress=bar:force 2>&1 | tail -f -n +6
|
||||||
|
log "✓ Ubuntu ISO downloaded"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Windows 11 LTSC IoT ISO
|
||||||
|
WIN_ISO="$ISO_DIR/Win11_Ent_LTSC_IoT.iso"
|
||||||
|
if [ -f "$WIN_ISO" ]; then
|
||||||
|
log "✓ Windows LTSC IoT ISO already exists"
|
||||||
|
else
|
||||||
|
warn "⚠️ Windows 11 LTSC IoT ISO not found"
|
||||||
|
info "Please download the ISO manually from Microsoft VLSC or your volume licensing portal"
|
||||||
|
info "Expected location: $WIN_ISO"
|
||||||
|
info ""
|
||||||
|
info "Alternative: Use Windows 11 standard ISO for now"
|
||||||
|
read -p "Download Windows 11 standard ISO instead? (y/N): " download_win
|
||||||
|
if [ "$download_win" == "y" ]; then
|
||||||
|
log "⬇️ Downloading Windows 11 standard ISO..."
|
||||||
|
warn "This is a large download (~6GB) and may take a while"
|
||||||
|
# Note: Microsoft doesn't provide direct ISO links, user needs to download manually
|
||||||
|
info "Please download Windows 11 ISO from: https://www.microsoft.com/software-download/windows11"
|
||||||
|
info "Save it to: $ISO_DIR/Win11.iso"
|
||||||
|
read -p "Press Enter when Windows ISO is ready..."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# CREATE VM 300: OpenClaw DevMatrix (Ubuntu)
|
||||||
|
# ============================================
|
||||||
|
log "🚀 Creating VM $MAIN_VMID: OpenClaw DevMatrix"
|
||||||
|
|
||||||
|
# Create VM
|
||||||
|
qm create $MAIN_VMID \
|
||||||
|
--name "OpenClaw-DevMatrix" \
|
||||||
|
--memory $MAIN_RAM \
|
||||||
|
--cores $MAIN_CORES \
|
||||||
|
--cpu host \
|
||||||
|
--net0 virtio,bridge=$NETWORK_BRIDGE \
|
||||||
|
--scsihw virtio-scsi-single \
|
||||||
|
--bios ovmf \
|
||||||
|
--machine q35
|
||||||
|
|
||||||
|
# Add EFI disk
|
||||||
|
qm set $MAIN_VMID --efidisk0 ${STORAGE_NAME}:1,format=qcow2,efitype=4m,pre-enrolled-keys=1
|
||||||
|
|
||||||
|
# Add primary disk
|
||||||
|
qm set $MAIN_VMID --scsi0 ${STORAGE_NAME}:${MAIN_DISK},format=qcow2,discard=on,iothread=1,ssd=1
|
||||||
|
|
||||||
|
# Add secondary disk for projects
|
||||||
|
qm set $MAIN_VMID --scsi1 ${STORAGE_NAME}:${MAIN_SECONDARY},format=qcow2,discard=on,iothread=1,ssd=1
|
||||||
|
|
||||||
|
# Add cloud-init drive
|
||||||
|
qm set $MAIN_VMID --ide2 ${STORAGE_NAME}:cloudinit,media=cdrom
|
||||||
|
|
||||||
|
# Attach Ubuntu ISO
|
||||||
|
qm set $MAIN_VMID --ide0 local:iso/ubuntu-22.04.5-live-server-amd64.iso,media=cdrom
|
||||||
|
|
||||||
|
# Set boot order
|
||||||
|
qm set $MAIN_VMID --boot order=scsi0;ide0
|
||||||
|
|
||||||
|
# Enable QEMU Guest Agent
|
||||||
|
qm set $MAIN_VMID --agent enabled=1,fstrim_cloned_disks=1
|
||||||
|
|
||||||
|
# Configure cloud-init
|
||||||
|
qm set $MAIN_VMID --ciuser devmatrix
|
||||||
|
qm set $MAIN_VMID --cipassword $(openssl rand -base64 32)
|
||||||
|
qm set $MAIN_VMID --ipconfig0 ip=dhcp
|
||||||
|
|
||||||
|
# Generate SSH key pair
|
||||||
|
if [ ! -f ~/.ssh/devmatrix_id_rsa ]; then
|
||||||
|
ssh-keygen -t rsa -b 4096 -f ~/.ssh/devmatrix_id_rsa -N "" -C "devmatrix@proxmox"
|
||||||
|
fi
|
||||||
|
qm set $MAIN_VMID --sshkeys ~/.ssh/devmatrix_id_rsa.pub
|
||||||
|
|
||||||
|
log "✓ VM $MAIN_VMID created successfully"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# CREATE VM 301: Windows LTSC IoT Test VM
|
||||||
|
# ============================================
|
||||||
|
log "🚀 Creating VM $WIN_VMID: Windows-LTSC-Test"
|
||||||
|
|
||||||
|
qm create $WIN_VMID \
|
||||||
|
--name "Windows-LTSC-Test" \
|
||||||
|
--memory $WIN_RAM \
|
||||||
|
--cores $WIN_CORES \
|
||||||
|
--cpu host \
|
||||||
|
--net0 virtio,bridge=$NETWORK_BRIDGE \
|
||||||
|
--scsihw virtio-scsi-single \
|
||||||
|
--bios ovmf \
|
||||||
|
--machine q35
|
||||||
|
|
||||||
|
# Add EFI disk
|
||||||
|
qm set $WIN_VMID --efidisk0 ${STORAGE_NAME}:1,format=qcow2,efitype=4m,pre-enrolled-keys=1
|
||||||
|
|
||||||
|
# Add disk
|
||||||
|
qm set $WIN_VMID --scsi0 ${STORAGE_NAME}:${WIN_DISK},format=qcow2,discard=on,iothread=1,ssd=1
|
||||||
|
|
||||||
|
# Attach Windows ISO (try both names)
|
||||||
|
if [ -f "$ISO_DIR/Win11_Ent_LTSC_IoT.iso" ]; then
|
||||||
|
qm set $WIN_VMID --ide0 local:iso/Win11_Ent_LTSC_IoT.iso,media=cdrom
|
||||||
|
elif [ -f "$ISO_DIR/Win11.iso" ]; then
|
||||||
|
qm set $WIN_VMID --ide0 local:iso/Win11.iso,media=cdrom
|
||||||
|
else
|
||||||
|
warn "⚠️ No Windows ISO attached. Please attach manually after download."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Set boot order
|
||||||
|
qm set $WIN_VMID --boot order=scsi0;ide0
|
||||||
|
|
||||||
|
# Enable QEMU Guest Agent
|
||||||
|
qm set $WIN_VMID --agent enabled=1
|
||||||
|
|
||||||
|
log "✓ VM $WIN_VMID created successfully"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# CREATE VM 302: Android Emulator VM
|
||||||
|
# ============================================
|
||||||
|
log "🚀 Creating VM $ANDROID_VMID: Android-Emulator"
|
||||||
|
|
||||||
|
qm create $ANDROID_VMID \
|
||||||
|
--name "Android-Emulator" \
|
||||||
|
--memory $ANDROID_RAM \
|
||||||
|
--cores $ANDROID_CORES \
|
||||||
|
--cpu host \
|
||||||
|
--net0 virtio,bridge=$NETWORK_BRIDGE \
|
||||||
|
--scsihw virtio-scsi-single \
|
||||||
|
--bios ovmf \
|
||||||
|
--machine q35
|
||||||
|
|
||||||
|
# Add EFI disk
|
||||||
|
qm set $ANDROID_VMID --efidisk0 ${STORAGE_NAME}:1,format=qcow2,efitype=4m,pre-enrolled-keys=1
|
||||||
|
|
||||||
|
# Add disk
|
||||||
|
qm set $ANDROID_VMID --scsi0 ${STORAGE_NAME}:${ANDROID_DISK},format=qcow2,discard=on,iothread=1,ssd=1
|
||||||
|
|
||||||
|
# Attach Ubuntu ISO (for Android development environment)
|
||||||
|
qm set $ANDROID_VMID --ide0 local:iso/ubuntu-22.04.5-live-server-amd64.iso,media=cdrom
|
||||||
|
|
||||||
|
# Set boot order
|
||||||
|
qm set $ANDROID_VMID --boot order=scsi0;ide0
|
||||||
|
|
||||||
|
# Enable QEMU Guest Agent
|
||||||
|
qm set $ANDROID_VMID --agent enabled=1
|
||||||
|
|
||||||
|
log "✓ VM $ANDROID_VMID created successfully"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# SUMMARY
|
||||||
|
# ============================================
|
||||||
|
log "🎉 DevMatrix VMs Created Successfully!"
|
||||||
|
echo ""
|
||||||
|
echo "╔════════════════════════════════════════════════════════════╗"
|
||||||
|
echo "║ VM INVENTORY ║"
|
||||||
|
echo "╠════════════════════════════════════════════════════════════╣"
|
||||||
|
echo "║ ID │ Name │ RAM │ Disk │ Status ║"
|
||||||
|
echo "╠═══════╪═════════════════════════╪════════╪═══════╪════════╣"
|
||||||
|
printf "║ %d │ %-23s │ %dGB │ %dGB │ Ready ║\n" $MAIN_VMID "OpenClaw-DevMatrix" $((MAIN_RAM/1024)) $((MAIN_DISK+MAIN_SECONDARY))
|
||||||
|
printf "║ %d │ %-23s │ %dGB │ %dGB │ Ready ║\n" $WIN_VMID "Windows-LTSC-Test" $((WIN_RAM/1024)) $WIN_DISK
|
||||||
|
printf "║ %d │ %-23s │ %dGB │ %dGB │ Ready ║\n" $ANDROID_VMID "Android-Emulator" $((ANDROID_RAM/1024)) $ANDROID_DISK
|
||||||
|
echo "╚════════════════════════════════════════════════════════════╝"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# NEXT STEPS
|
||||||
|
# ============================================
|
||||||
|
log "📋 Next Steps:"
|
||||||
|
echo ""
|
||||||
|
echo "1. INSTALL UBUNTU ON VM $MAIN_VMID:"
|
||||||
|
echo " qm start $MAIN_VMID"
|
||||||
|
echo " # Connect via console: qm console $MAIN_VMID"
|
||||||
|
echo " # Or use Proxmox web UI console"
|
||||||
|
echo ""
|
||||||
|
echo "2. AFTER UBUNTU INSTALL, RUN SETUP:"
|
||||||
|
echo " # SSH into the VM:"
|
||||||
|
echo " ssh -i ~/.ssh/devmatrix_id_rsa devmatrix@<vm-ip>"
|
||||||
|
echo ""
|
||||||
|
echo " # Download and run the OpenClaw setup script:"
|
||||||
|
echo " curl -fsSL https://raw.githubusercontent.com/yourrepo/devmatrix/main/setup_openclaw_dev.sh | bash"
|
||||||
|
echo ""
|
||||||
|
echo "3. INSTALL WINDOWS ON VM $WIN_VMID:"
|
||||||
|
echo " qm start $WIN_VMID"
|
||||||
|
echo " # Install Windows LTSC IoT manually"
|
||||||
|
echo " # Then run: setup_windows_vm.ps1 (provided separately)"
|
||||||
|
echo ""
|
||||||
|
echo "4. CONFIGURE API KEYS (YOU DO THIS):"
|
||||||
|
echo " # Inside the Ubuntu VM, run:"
|
||||||
|
echo " ~/scripts/configure_api_keys.sh"
|
||||||
|
echo " # Enter your Kimi and Antigravity API keys"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Save VM info to file
|
||||||
|
cat > ~/devmatrix_vm_info.txt << EOF
|
||||||
|
DevMatrix VM Information
|
||||||
|
========================
|
||||||
|
Created: $(date)
|
||||||
|
Network: $NETWORK_BRIDGE
|
||||||
|
Storage: $STORAGE_NAME
|
||||||
|
|
||||||
|
VM 300: OpenClaw-DevMatrix (Ubuntu 22.04)
|
||||||
|
- RAM: ${MAIN_RAM}MB (32GB)
|
||||||
|
- CPU: ${MAIN_CORES} cores
|
||||||
|
- Disk: ${MAIN_DISK}GB + ${MAIN_SECONDARY}GB
|
||||||
|
- SSH Key: ~/.ssh/devmatrix_id_rsa
|
||||||
|
|
||||||
|
VM 301: Windows-LTSC-Test (Windows 11 LTSC IoT)
|
||||||
|
- RAM: ${WIN_RAM}MB (16GB)
|
||||||
|
- CPU: ${WIN_CORES} cores
|
||||||
|
- Disk: ${WIN_DISK}GB
|
||||||
|
|
||||||
|
VM 302: Android-Emulator (Ubuntu)
|
||||||
|
- RAM: ${ANDROID_RAM}MB (8GB)
|
||||||
|
- CPU: ${ANDROID_CORES} cores
|
||||||
|
- Disk: ${ANDROID_DISK}GB
|
||||||
|
|
||||||
|
SSH Access:
|
||||||
|
ssh -i ~/.ssh/devmatrix_id_rsa devmatrix@<vm-ip>
|
||||||
|
|
||||||
|
Proxmox Commands:
|
||||||
|
Start VM 300: qm start 300
|
||||||
|
Stop VM 300: qm stop 300
|
||||||
|
Console: qm console 300
|
||||||
|
Status: qm status 300
|
||||||
|
EOF
|
||||||
|
|
||||||
|
log "📄 VM information saved to: ~/devmatrix_vm_info.txt"
|
||||||
|
log "🔑 SSH private key: ~/.ssh/devmatrix_id_rsa"
|
||||||
|
log "🔓 SSH public key: ~/.ssh/devmatrix_id_rsa.pub"
|
||||||
|
echo ""
|
||||||
|
log "✅ Setup script complete! Review the steps above to continue."
|
||||||
|
|
@ -0,0 +1,542 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# DevMatrix Setup Script for Proxmox - CUSTOMIZED for Roberth
|
||||||
|
# Storage: pve-main2 (HDD) | Future NVMe: pve-main
|
||||||
|
# TrueNAS: 192.168.5.195 | Dataset: NAS2
|
||||||
|
# VM IDs: 300-320
|
||||||
|
# Run this ON THE PROXMOX HOST as root
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# CONFIGURATION (Your Specific Setup)
|
||||||
|
# ============================================
|
||||||
|
NETWORK_BRIDGE="vmbr1"
|
||||||
|
STORAGE_HDD="pve-main2" # Current HDD storage
|
||||||
|
STORAGE_NVME="pve-main" # Future NVMe storage (when installed)
|
||||||
|
TRUENAS_IP="192.168.5.195"
|
||||||
|
TRUENAS_DATASET="NAS2"
|
||||||
|
|
||||||
|
# VM IDs
|
||||||
|
MAIN_VMID=300 # OpenClaw DevMatrix (Ubuntu)
|
||||||
|
WIN_VMID=301 # Windows LTSC IoT Test VM
|
||||||
|
ANDROID_VMID=302 # Android Emulator VM
|
||||||
|
|
||||||
|
# Static IPs (safe range - verified from network scan)
|
||||||
|
MAIN_IP="192.168.5.210"
|
||||||
|
WIN_IP="192.168.5.211"
|
||||||
|
ANDROID_IP="192.168.5.212"
|
||||||
|
GATEWAY="192.168.5.1"
|
||||||
|
|
||||||
|
# Resource Allocation (Optimized for HDD)
|
||||||
|
MAIN_RAM=32768 # 32GB RAM
|
||||||
|
MAIN_CORES=16
|
||||||
|
MAIN_OS_DISK=200 # 200GB OS disk (HDD now, NVMe later)
|
||||||
|
MAIN_DATA_DISK=200 # 200GB data disk (stays on HDD)
|
||||||
|
|
||||||
|
WIN_RAM=16384 # 16GB RAM
|
||||||
|
WIN_CORES=8
|
||||||
|
WIN_DISK=100 # 100GB disk
|
||||||
|
|
||||||
|
ANDROID_RAM=8192 # 8GB RAM
|
||||||
|
ANDROID_CORES=4
|
||||||
|
ANDROID_DISK=50 # 50GB disk
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# COLORS
|
||||||
|
# ============================================
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
CYAN='\033[0;36m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
log() { echo -e "${GREEN}[DevMatrix]${NC} $1"; }
|
||||||
|
warn() { echo -e "${YELLOW}[Warning]${NC} $1"; }
|
||||||
|
error() { echo -e "${RED}[Error]${NC} $1"; exit 1; }
|
||||||
|
info() { echo -e "${CYAN}[Info]${NC} $1"; }
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# PRE-FLIGHT CHECKS
|
||||||
|
# ============================================
|
||||||
|
log "🔍 Running pre-flight checks..."
|
||||||
|
|
||||||
|
if [ "$EUID" -ne 0 ]; then
|
||||||
|
error "Please run as root"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check vmbr1
|
||||||
|
if ! ip link show "$NETWORK_BRIDGE" &> /dev/null; then
|
||||||
|
error "Network bridge '$NETWORK_BRIDGE' not found!"
|
||||||
|
fi
|
||||||
|
log "✓ Network bridge '$NETWORK_BRIDGE' found"
|
||||||
|
|
||||||
|
# Check storage
|
||||||
|
if ! pvesm status | grep -q "^$STORAGE_HDD"; then
|
||||||
|
error "Storage '$STORAGE_HDD' not found!"
|
||||||
|
fi
|
||||||
|
log "✓ HDD storage '$STORAGE_HDD' found"
|
||||||
|
|
||||||
|
# Check available space on HDD
|
||||||
|
HDD_AVAIL=$(pvesm status | grep "^$STORAGE_HDD" | awk '{print $4}' | sed 's/G//')
|
||||||
|
info "HDD available: ${HDD_AVAIL}GB"
|
||||||
|
|
||||||
|
NEEDED_HDD=$((MAIN_OS_DISK + MAIN_DATA_DISK + WIN_DISK + ANDROID_DISK + 100)) # +100GB buffer
|
||||||
|
if [ "${HDD_AVAIL%.*}" -lt "$NEEDED_HDD" ]; then
|
||||||
|
error "Not enough space on $STORAGE_HDD. Need ${NEEDED_HDD}GB, have ${HDD_AVAIL}GB"
|
||||||
|
fi
|
||||||
|
log "✓ Sufficient HDD space (${NEEDED_HDD}GB needed)"
|
||||||
|
|
||||||
|
# Check VM IDs
|
||||||
|
for vmid in $MAIN_VMID $WIN_VMID $ANDROID_VMID; do
|
||||||
|
if qm status "$vmid" &> /dev/null; then
|
||||||
|
error "VM ID $vmid already exists!"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
log "✓ VM IDs available (300-302)"
|
||||||
|
|
||||||
|
# Check RAM
|
||||||
|
AVAILABLE_RAM=$(free -m | awk '/^Mem:/{print $7}')
|
||||||
|
TOTAL_RAM=$((MAIN_RAM + WIN_RAM + ANDROID_RAM))
|
||||||
|
info "Available RAM: ${AVAILABLE_RAM}MB"
|
||||||
|
info "Required RAM: ${TOTAL_RAM}MB"
|
||||||
|
|
||||||
|
if [ "$AVAILABLE_RAM" -lt "$TOTAL_RAM" ]; then
|
||||||
|
warn "Low RAM! Consider reducing VM memory"
|
||||||
|
read -p "Continue anyway? (y/N): " confirm
|
||||||
|
[ "$confirm" != "y" ] && exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check TrueNAS connectivity
|
||||||
|
if ping -c 1 "$TRUENAS_IP" &> /dev/null; then
|
||||||
|
log "✓ TrueNAS ($TRUENAS_IP) reachable"
|
||||||
|
else
|
||||||
|
warn "TrueNAS ($TRUENAS_IP) not reachable - will configure later"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
log "✅ Pre-flight checks complete!"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# DOWNLOAD ISO IMAGES
|
||||||
|
# ============================================
|
||||||
|
log "⬇️ Checking for ISO images..."
|
||||||
|
|
||||||
|
ISO_DIR="/var/lib/vz/template/iso"
|
||||||
|
mkdir -p "$ISO_DIR"
|
||||||
|
|
||||||
|
# Ubuntu 22.04 Server ISO
|
||||||
|
UBUNTU_ISO="$ISO_DIR/ubuntu-22.04.5-live-server-amd64.iso"
|
||||||
|
if [ -f "$UBUNTU_ISO" ]; then
|
||||||
|
log "✓ Ubuntu ISO found"
|
||||||
|
else
|
||||||
|
log "⬇️ Downloading Ubuntu 22.04 Server ISO..."
|
||||||
|
wget -O "$UBUNTU_ISO" \
|
||||||
|
"https://releases.ubuntu.com/22.04/ubuntu-22.04.5-live-server-amd64.iso" \
|
||||||
|
--progress=bar:force 2>&1 | tail -f -n +6
|
||||||
|
log "✓ Ubuntu ISO downloaded"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check for Windows ISO
|
||||||
|
WIN_ISO="$ISO_DIR/Win11_Ent_LTSC_IoT.iso"
|
||||||
|
WIN_ISO_ALT="$ISO_DIR/Win11.iso"
|
||||||
|
|
||||||
|
if [ -f "$WIN_ISO" ]; then
|
||||||
|
log "✓ Windows LTSC IoT ISO found"
|
||||||
|
WIN_ISO_FILE="Win11_Ent_LTSC_IoT.iso"
|
||||||
|
elif [ -f "$WIN_ISO_ALT" ]; then
|
||||||
|
log "✓ Windows 11 ISO found"
|
||||||
|
WIN_ISO_FILE="Win11.iso"
|
||||||
|
else
|
||||||
|
warn "⚠️ Windows ISO not found"
|
||||||
|
info "Please download Windows 11 ISO and place it in:"
|
||||||
|
info " $ISO_DIR/Win11.iso"
|
||||||
|
info "Download from: https://www.microsoft.com/software-download/windows11"
|
||||||
|
read -p "Press Enter when Windows ISO is ready (or 'skip' to continue without): " response
|
||||||
|
if [ "$response" == "skip" ]; then
|
||||||
|
WIN_ISO_FILE=""
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# CREATE VM 300: OpenClaw DevMatrix (Ubuntu)
|
||||||
|
# ============================================
|
||||||
|
log "🚀 Creating VM $MAIN_VMID: OpenClaw-DevMatrix"
|
||||||
|
log " IP: $MAIN_IP | Storage: $STORAGE_HDD (migrates to $STORAGE_NVME later)"
|
||||||
|
|
||||||
|
qm create $MAIN_VMID \
|
||||||
|
--name "OpenClaw-DevMatrix" \
|
||||||
|
--memory $MAIN_RAM \
|
||||||
|
--cores $MAIN_CORES \
|
||||||
|
--cpu host \
|
||||||
|
--net0 virtio,bridge=$NETWORK_BRIDGE,tag=1 \
|
||||||
|
--scsihw virtio-scsi-single \
|
||||||
|
--bios ovmf \
|
||||||
|
--machine q35
|
||||||
|
|
||||||
|
# EFI disk (small, fast)
|
||||||
|
qm set $MAIN_VMID --efidisk0 ${STORAGE_HDD}:1,format=qcow2,efitype=4m,pre-enrolled-keys=1
|
||||||
|
|
||||||
|
# OS Disk - HDD optimized (will migrate to NVMe)
|
||||||
|
# Using writeback cache for better HDD performance
|
||||||
|
qm set $MAIN_VMID \
|
||||||
|
--scsi0 ${STORAGE_HDD}:${MAIN_OS_DISK},format=qcow2,cache=writeback,discard=on,iothread=1,ssd=1
|
||||||
|
|
||||||
|
# Data Disk - stays on HDD even after migration
|
||||||
|
qm set $MAIN_VMID \
|
||||||
|
--scsi1 ${STORAGE_HDD}:${MAIN_DATA_DISK},format=qcow2,cache=none,discard=on,iothread=1
|
||||||
|
|
||||||
|
# Cloud-init drive
|
||||||
|
qm set $MAIN_VMID --ide2 ${STORAGE_HDD}:cloudinit,media=cdrom
|
||||||
|
|
||||||
|
# Attach Ubuntu ISO
|
||||||
|
qm set $MAIN_VMID --ide0 local:iso/ubuntu-22.04.5-live-server-amd64.iso,media=cdrom
|
||||||
|
|
||||||
|
# Boot order
|
||||||
|
qm set $MAIN_VMID --boot order=scsi0;ide0
|
||||||
|
|
||||||
|
# Enable QEMU Guest Agent
|
||||||
|
qm set $MAIN_VMID --agent enabled=1,fstrim_cloned_disks=1
|
||||||
|
|
||||||
|
# CPU optimization for compilation workloads
|
||||||
|
qm set $MAIN_VMID --cpu cputype=host,flags=+aes
|
||||||
|
|
||||||
|
# Configure cloud-init with static IP
|
||||||
|
qm set $MAIN_VMID --ciuser devmatrix
|
||||||
|
qm set $MAIN_VMID --cipassword $(openssl rand -base64 32)
|
||||||
|
qm set $MAIN_VMID --ipconfig0 ip=${MAIN_IP}/24,gw=${GATEWAY}
|
||||||
|
|
||||||
|
# Generate SSH key pair
|
||||||
|
if [ ! -f ~/.ssh/devmatrix_id_rsa ]; then
|
||||||
|
ssh-keygen -t rsa -b 4096 -f ~/.ssh/devmatrix_id_rsa -N "" -C "devmatrix@proxmox"
|
||||||
|
chmod 600 ~/.ssh/devmatrix_id_rsa
|
||||||
|
fi
|
||||||
|
qm set $MAIN_VMID --sshkeys ~/.ssh/devmatrix_id_rsa.pub
|
||||||
|
|
||||||
|
# Description
|
||||||
|
qm set $MAIN_VMID --description "OpenClaw DevMatrix - Ubuntu Dev Environment
|
||||||
|
IP: ${MAIN_IP}
|
||||||
|
Storage: ${STORAGE_HDD} (OS migrates to ${STORAGE_NVME} later)
|
||||||
|
Data: ${STORAGE_HDD} (permanent)
|
||||||
|
TrueNAS: ${TRUENAS_IP}"
|
||||||
|
|
||||||
|
log "✓ VM $MAIN_VMID created"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# CREATE VM 301: Windows LTSC IoT Test VM
|
||||||
|
# ============================================
|
||||||
|
log "🚀 Creating VM $WIN_VMID: Windows-LTSC-Test"
|
||||||
|
log " IP: $WIN_IP | Storage: $STORAGE_HDD"
|
||||||
|
|
||||||
|
qm create $WIN_VMID \
|
||||||
|
--name "Windows-LTSC-Test" \
|
||||||
|
--memory $WIN_RAM \
|
||||||
|
--cores $WIN_CORES \
|
||||||
|
--cpu host \
|
||||||
|
--net0 virtio,bridge=$NETWORK_BRIDGE,tag=1 \
|
||||||
|
--scsihw virtio-scsi-single \
|
||||||
|
--bios ovmf \
|
||||||
|
--machine q35
|
||||||
|
|
||||||
|
# EFI disk
|
||||||
|
qm set $WIN_VMID --efidisk0 ${STORAGE_HDD}:1,format=qcow2,efitype=4m,pre-enrolled-keys=1
|
||||||
|
|
||||||
|
# OS Disk - HDD optimized
|
||||||
|
qm set $WIN_VMID \
|
||||||
|
--scsi0 ${STORAGE_HDD}:${WIN_DISK},format=qcow2,cache=writeback,discard=on,iothread=1,ssd=1
|
||||||
|
|
||||||
|
# Attach Windows ISO if available
|
||||||
|
if [ -n "$WIN_ISO_FILE" ]; then
|
||||||
|
qm set $WIN_VMID --ide0 local:iso/${WIN_ISO_FILE},media=cdrom
|
||||||
|
else
|
||||||
|
warn "No Windows ISO attached. Attach manually later."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Boot order
|
||||||
|
qm set $WIN_VMID --boot order=scsi0;ide0
|
||||||
|
|
||||||
|
# Enable QEMU Guest Agent
|
||||||
|
qm set $WIN_VMID --agent enabled=1
|
||||||
|
|
||||||
|
# Windows benefits from more video memory
|
||||||
|
qm set $WIN_VMID --vga virtio,memory=64
|
||||||
|
|
||||||
|
# Description
|
||||||
|
qm set $WIN_VMID --description "Windows 11 LTSC IoT Test VM
|
||||||
|
IP: ${WIN_IP}
|
||||||
|
Storage: ${STORAGE_HDD}
|
||||||
|
User: testuser / DevMatrix2024!"
|
||||||
|
|
||||||
|
log "✓ VM $WIN_VMID created"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# CREATE VM 302: Android Emulator VM
|
||||||
|
# ============================================
|
||||||
|
log "🚀 Creating VM $ANDROID_VMID: Android-Emulator"
|
||||||
|
log " IP: $ANDROID_IP | Storage: $STORAGE_HDD"
|
||||||
|
|
||||||
|
qm create $ANDROID_VMID \
|
||||||
|
--name "Android-Emulator" \
|
||||||
|
--memory $ANDROID_RAM \
|
||||||
|
--cores $ANDROID_CORES \
|
||||||
|
--cpu host \
|
||||||
|
--net0 virtio,bridge=$NETWORK_BRIDGE,tag=1 \
|
||||||
|
--scsihw virtio-scsi-single \
|
||||||
|
--bios ovmf \
|
||||||
|
--machine q35
|
||||||
|
|
||||||
|
# EFI disk
|
||||||
|
qm set $ANDROID_VMID --efidisk0 ${STORAGE_HDD}:1,format=qcow2,efitype=4m,pre-enrolled-keys=1
|
||||||
|
|
||||||
|
# OS Disk
|
||||||
|
qm set $ANDROID_VMID \
|
||||||
|
--scsi0 ${STORAGE_HDD}:${ANDROID_DISK},format=qcow2,cache=writeback,discard=on,iothread=1,ssd=1
|
||||||
|
|
||||||
|
# Attach Ubuntu ISO (for Android dev environment setup)
|
||||||
|
qm set $ANDROID_VMID --ide0 local:iso/ubuntu-22.04.5-live-server-amd64.iso,media=cdrom
|
||||||
|
|
||||||
|
# Boot order
|
||||||
|
qm set $ANDROID_VMID --boot order=scsi0;ide0
|
||||||
|
|
||||||
|
# Enable QEMU Guest Agent
|
||||||
|
qm set $ANDROID_VMID --agent enabled=1
|
||||||
|
|
||||||
|
# Description
|
||||||
|
qm set $ANDROID_VMID --description "Android Emulator VM
|
||||||
|
IP: ${ANDROID_IP}
|
||||||
|
Storage: ${STORAGE_HDD}
|
||||||
|
Note: Install Android SDK and Emulator after Ubuntu setup"
|
||||||
|
|
||||||
|
log "✓ VM $ANDROID_VMID created"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# CREATE MIGRATION SCRIPT
|
||||||
|
# ============================================
|
||||||
|
log "📝 Creating NVMe migration script..."
|
||||||
|
|
||||||
|
mkdir -p /root/devmatrix-scripts
|
||||||
|
|
||||||
|
cat > /root/devmatrix-scripts/migrate_to_nvme.sh << 'EOF'
|
||||||
|
#!/bin/bash
|
||||||
|
# Migrate DevMatrix VMs from HDD (pve-main2) to NVMe (pve-main)
|
||||||
|
# Run this after installing NVMe drive and adding it as 'pve-main' storage
|
||||||
|
|
||||||
|
STORAGE_NVME="pve-main"
|
||||||
|
STORAGE_HDD="pve-main2"
|
||||||
|
|
||||||
|
MIGRATE_VMS="300 301 302"
|
||||||
|
|
||||||
|
echo "🚀 DevMatrix NVMe Migration Tool"
|
||||||
|
echo "================================"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check NVMe storage exists
|
||||||
|
if ! pvesm status | grep -q "^$STORAGE_NVME"; then
|
||||||
|
echo "❌ NVMe storage '$STORAGE_NVME' not found!"
|
||||||
|
echo ""
|
||||||
|
echo "To add NVMe storage:"
|
||||||
|
echo "1. Install NVMe drive"
|
||||||
|
echo "2. In Proxmox: Datacenter -> Storage -> Add -> Directory"
|
||||||
|
echo "3. Set ID to 'pve-main' and point to your NVMe mount point"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "✓ NVMe storage '$STORAGE_NVME' found"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
migrate_vm() {
|
||||||
|
local vmid=$1
|
||||||
|
local vmname=$(qm config $vmid | grep name | cut -d' ' -f2)
|
||||||
|
|
||||||
|
echo "🔄 Migrating VM $vmid ($vmname)..."
|
||||||
|
|
||||||
|
# Check if running
|
||||||
|
if qm status $vmid | grep -q running; then
|
||||||
|
echo " Stopping VM..."
|
||||||
|
qm stop $vmid
|
||||||
|
sleep 5
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get current disk size
|
||||||
|
DISK_SIZE=$(qm config $vmid | grep scsi0 | grep -oP '\d+(?=,)' | head -1)
|
||||||
|
|
||||||
|
echo " Moving disk (${DISK_SIZE}GB)..."
|
||||||
|
qm move-disk $vmid scsi0 $STORAGE_NVME
|
||||||
|
|
||||||
|
# Update cache settings for SSD (writethrough is safer for SSD)
|
||||||
|
qm set $vmid --scsi0 ${STORAGE_NVME}:${DISK_SIZE},cache=writethrough,discard=on,ssd=1,iothread=1
|
||||||
|
|
||||||
|
# Update description
|
||||||
|
qm set $vmid --description "$(qm config $vmid | grep description | cut -d' ' -f2-) | Migrated to NVMe $(date +%Y-%m-%d)"
|
||||||
|
|
||||||
|
echo " ✓ Migrated successfully"
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# Confirm
|
||||||
|
read -p "Migrate VMs $MIGRATE_VMS to NVMe? (y/N): " confirm
|
||||||
|
if [ "$confirm" != "y" ]; then
|
||||||
|
echo "Cancelled."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Migrate
|
||||||
|
for vmid in $MIGRATE_VMS; do
|
||||||
|
migrate_vm $vmid
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "🎉 All VMs migrated to NVMe!"
|
||||||
|
echo ""
|
||||||
|
echo "Next steps:"
|
||||||
|
echo "1. Start VMs and verify they boot correctly"
|
||||||
|
echo "2. Update any hardcoded paths in VM configs"
|
||||||
|
echo "3. Consider moving data disks (scsi1) to NVMe for better performance"
|
||||||
|
echo ""
|
||||||
|
echo "Old HDD storage can now be used for backups and less critical VMs"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod +x /root/devmatrix-scripts/migrate_to_nvme.sh
|
||||||
|
|
||||||
|
log "✓ Migration script created: /root/devmatrix-scripts/migrate_to_nvme.sh"
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# CREATE VM INFO FILE
|
||||||
|
# ============================================
|
||||||
|
cat > ~/devmatrix_vm_info.txt << EOF
|
||||||
|
DevMatrix VM Configuration
|
||||||
|
==========================
|
||||||
|
Created: $(date)
|
||||||
|
Network: $NETWORK_BRIDGE
|
||||||
|
Storage HDD: $STORAGE_HDD
|
||||||
|
Future NVMe: $STORAGE_NVME
|
||||||
|
TrueNAS: $TRUENAS_IP ($TRUENAS_DATASET)
|
||||||
|
|
||||||
|
VM INVENTORY
|
||||||
|
============
|
||||||
|
|
||||||
|
ID 300: OpenClaw-DevMatrix (Ubuntu 22.04)
|
||||||
|
-----------------------------------------
|
||||||
|
Name: OpenClaw-DevMatrix
|
||||||
|
IP: ${MAIN_IP}/24 (Gateway: ${GATEWAY})
|
||||||
|
RAM: ${MAIN_RAM}MB (32GB)
|
||||||
|
CPU: ${MAIN_CORES} cores
|
||||||
|
OS Disk: ${MAIN_OS_DISK}GB on ${STORAGE_HDD} (migrates to ${STORAGE_NVME})
|
||||||
|
Data Disk: ${MAIN_DATA_DISK}GB on ${STORAGE_HDD} (permanent)
|
||||||
|
SSH: ssh -i ~/.ssh/devmatrix_id_rsa devmatrix@${MAIN_IP}
|
||||||
|
VS Code: http://${MAIN_IP}:8080
|
||||||
|
|
||||||
|
ID 301: Windows-LTSC-Test (Windows 11)
|
||||||
|
--------------------------------------
|
||||||
|
Name: Windows-LTSC-Test
|
||||||
|
IP: ${WIN_IP}/24
|
||||||
|
RAM: ${WIN_RAM}MB (16GB)
|
||||||
|
CPU: ${WIN_CORES} cores
|
||||||
|
Disk: ${WIN_DISK}GB on ${STORAGE_HDD}
|
||||||
|
RDP: mstsc /v:${WIN_IP}
|
||||||
|
User: testuser / DevMatrix2024!
|
||||||
|
|
||||||
|
ID 302: Android-Emulator (Ubuntu 22.04)
|
||||||
|
---------------------------------------
|
||||||
|
Name: Android-Emulator
|
||||||
|
IP: ${ANDROID_IP}/24
|
||||||
|
RAM: ${ANDROID_RAM}MB (8GB)
|
||||||
|
CPU: ${ANDROID_CORES} cores
|
||||||
|
Disk: ${ANDROID_DISK}GB on ${STORAGE_HDD}
|
||||||
|
|
||||||
|
SSH ACCESS
|
||||||
|
==========
|
||||||
|
Private Key: ~/.ssh/devmatrix_id_rsa
|
||||||
|
Public Key: ~/.ssh/devmatrix_id_rsa.pub
|
||||||
|
|
||||||
|
Add this public key to VMs during cloud-init or after install:
|
||||||
|
$(cat ~/.ssh/devmatrix_id_rsa.pub)
|
||||||
|
|
||||||
|
PROXMOX COMMANDS
|
||||||
|
================
|
||||||
|
Start VM 300: qm start 300
|
||||||
|
Stop VM 300: qm stop 300
|
||||||
|
Console: qm console 300
|
||||||
|
Status: qm status 300
|
||||||
|
|
||||||
|
SNAPSHOTS
|
||||||
|
=========
|
||||||
|
Create: qm snapshot 300 before-update
|
||||||
|
List: qm listsnapshot 300
|
||||||
|
Restore: qm rollback 300 before-update
|
||||||
|
|
||||||
|
MIGRATION
|
||||||
|
=========
|
||||||
|
When NVMe (pve-main) is installed, run:
|
||||||
|
/root/devmatrix-scripts/migrate_to_nvme.sh
|
||||||
|
|
||||||
|
This will move VM 300-302 OS disks from HDD to NVMe
|
||||||
|
|
||||||
|
TRUENAS INTEGRATION
|
||||||
|
===================
|
||||||
|
TrueNAS IP: ${TRUENAS_IP}
|
||||||
|
Dataset: ${TRUENAS_DATASET}
|
||||||
|
|
||||||
|
Setup shares on TrueNAS:
|
||||||
|
1. Create dataset: ${TRUENAS_DATASET}/devmatrix
|
||||||
|
2. Create sub-datasets:
|
||||||
|
- ${TRUENAS_DATASET}/devmatrix/projects
|
||||||
|
- ${TRUENAS_DATASET}/devmatrix/backups
|
||||||
|
- ${TRUENAS_DATASET}/devmatrix/iso-archive
|
||||||
|
3. Create NFS shares for each
|
||||||
|
4. Mount in VM 300 using ~/scripts/setup_truenas.sh
|
||||||
|
|
||||||
|
NEXT STEPS
|
||||||
|
==========
|
||||||
|
1. Install Ubuntu on VM 300:
|
||||||
|
qm start 300
|
||||||
|
# Connect via console, complete installation
|
||||||
|
|
||||||
|
2. Install Windows on VM 301:
|
||||||
|
qm start 301
|
||||||
|
# Install Windows LTSC IoT
|
||||||
|
|
||||||
|
3. Setup Dev Environment (inside VM 300):
|
||||||
|
ssh devmatrix@${MAIN_IP}
|
||||||
|
# Run setup_openclaw_dev.sh
|
||||||
|
|
||||||
|
4. Configure TrueNAS shares (optional):
|
||||||
|
# Setup on TrueNAS first, then run setup_truenas.sh in VM
|
||||||
|
|
||||||
|
For detailed instructions, see: DEVMATRIX_SETUP_GUIDE.md
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# SUMMARY
|
||||||
|
# ============================================
|
||||||
|
log "🎉 DevMatrix VMs Created Successfully!"
|
||||||
|
echo ""
|
||||||
|
echo "╔════════════════════════════════════════════════════════════╗"
|
||||||
|
echo "║ VM INVENTORY ║"
|
||||||
|
echo "╠════════════════════════════════════════════════════════════╣"
|
||||||
|
echo "║ ║"
|
||||||
|
printf "║ ID 300: %-15s IP: %-15s ║\n" "OpenClaw-DevMatrix" "$MAIN_IP"
|
||||||
|
printf "║ Ubuntu 22.04 RAM: 32GB Disk: 400GB ║\n"
|
||||||
|
echo "║ ║"
|
||||||
|
printf "║ ID 301: %-15s IP: %-15s ║\n" "Windows-LTSC-Test" "$WIN_IP"
|
||||||
|
printf "║ Windows 11 LTSC RAM: 16GB Disk: 100GB ║\n"
|
||||||
|
echo "║ ║"
|
||||||
|
printf "║ ID 302: %-15s IP: %-15s ║\n" "Android-Emulator" "$ANDROID_IP"
|
||||||
|
printf "║ Ubuntu 22.04 RAM: 8GB Disk: 50GB ║\n"
|
||||||
|
echo "║ ║"
|
||||||
|
echo "╠════════════════════════════════════════════════════════════╣"
|
||||||
|
echo "║ Storage: HDD ($STORAGE_HDD) → NVMe ($STORAGE_NVME) later ║"
|
||||||
|
echo "║ TrueNAS: $TRUENAS_IP ║"
|
||||||
|
echo "╚════════════════════════════════════════════════════════════╝"
|
||||||
|
echo ""
|
||||||
|
log "📄 Configuration saved to: ~/devmatrix_vm_info.txt"
|
||||||
|
log "🔑 SSH key: ~/.ssh/devmatrix_id_rsa"
|
||||||
|
log "🚀 Migration tool: /root/devmatrix-scripts/migrate_to_nvme.sh"
|
||||||
|
echo ""
|
||||||
|
echo "Next: Install Ubuntu on VM 300, then run setup_openclaw_dev.sh"
|
||||||
|
echo ""
|
||||||
|
|
@ -0,0 +1,478 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# OpenClaw DevMatrix Environment Setup
|
||||||
|
# Run this INSIDE the Ubuntu VM (ID: 300) after OS installation
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Colors
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
CYAN='\033[0;36m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
log() { echo -e "${GREEN}[DevMatrix]${NC} $1"; }
|
||||||
|
warn() { echo -e "${YELLOW}[Warning]${NC} $1"; }
|
||||||
|
error() { echo -e "${RED}[Error]${NC} $1"; exit 1; }
|
||||||
|
info() { echo -e "${CYAN}[Info]${NC} $1"; }
|
||||||
|
|
||||||
|
log "🚀 Starting DevMatrix Environment Setup..."
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# SYSTEM UPDATE
|
||||||
|
# ============================================
|
||||||
|
log "📦 Updating system..."
|
||||||
|
sudo apt update && sudo apt upgrade -y
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# BASE PACKAGES
|
||||||
|
# ============================================
|
||||||
|
log "📦 Installing base packages..."
|
||||||
|
sudo apt install -y \
|
||||||
|
curl wget git git-lfs \
|
||||||
|
build-essential software-properties-common \
|
||||||
|
apt-transport-https ca-certificates gnupg lsb-release \
|
||||||
|
unzip zip jq htop tree vim nano tmux \
|
||||||
|
sshpass
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# INSTALL OPENCLAW
|
||||||
|
# ============================================
|
||||||
|
log "🦞 Installing OpenClaw..."
|
||||||
|
curl -fsSL https://openclaw.dev/install.sh | bash
|
||||||
|
|
||||||
|
# Add to PATH
|
||||||
|
echo 'export PATH="$HOME/.openclaw/bin:$PATH"' >> ~/.bashrc
|
||||||
|
export PATH="$HOME/.openclaw/bin:$PATH"
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# NODE.JS
|
||||||
|
# ============================================
|
||||||
|
log "📦 Installing Node.js 20..."
|
||||||
|
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
|
||||||
|
sudo apt install -y nodejs
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# PYTHON
|
||||||
|
# ============================================
|
||||||
|
log "📦 Installing Python development tools..."
|
||||||
|
sudo apt install -y python3 python3-pip python3-venv python3-dev python-is-python3
|
||||||
|
|
||||||
|
pip3 install --user \
|
||||||
|
pipenv poetry pytest black flake8 mypy bandit pylint \
|
||||||
|
jupyter notebook requests
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# DOCKER
|
||||||
|
# ============================================
|
||||||
|
log "🐳 Installing Docker..."
|
||||||
|
sudo apt install -y docker.io docker-compose-plugin
|
||||||
|
sudo usermod -aG docker $USER
|
||||||
|
sudo systemctl enable --now docker
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# FLUTTER (Mobile Development)
|
||||||
|
# ============================================
|
||||||
|
log "📱 Installing Flutter..."
|
||||||
|
sudo snap install flutter --classic
|
||||||
|
flutter config --enable-linux-desktop
|
||||||
|
flutter config --enable-web
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# .NET (Cross-Platform)
|
||||||
|
# ============================================
|
||||||
|
log "🔷 Installing .NET 8..."
|
||||||
|
wget https://packages.microsoft.com/config/ubuntu/22.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
|
||||||
|
sudo dpkg -i packages-microsoft-prod.deb
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install -y dotnet-sdk-8.0 aspnetcore-runtime-8.0
|
||||||
|
rm packages-microsoft-prod.deb
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# RUST
|
||||||
|
# ============================================
|
||||||
|
log "🦀 Installing Rust..."
|
||||||
|
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
|
||||||
|
source $HOME/.cargo/env
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# GO
|
||||||
|
# ============================================
|
||||||
|
log "🐹 Installing Go..."
|
||||||
|
sudo apt install -y golang-go
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# WINE (Windows App Testing)
|
||||||
|
# ============================================
|
||||||
|
log "🍷 Installing Wine..."
|
||||||
|
sudo dpkg --add-architecture i386
|
||||||
|
sudo mkdir -pm755 /etc/apt/keyrings
|
||||||
|
sudo wget -O /etc/apt/keyrings/winehq-archive.key https://dl.winehq.org/wine-builds/winehq.key
|
||||||
|
sudo wget -NP /etc/apt/sources.list.d/ https://dl.winehq.org/wine-builds/ubuntu/dists/jammy/winehq-jammy.sources
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install -y --install-recommends winehq-stable
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# PLAYWRIGHT (UI Testing)
|
||||||
|
# ============================================
|
||||||
|
log "🎭 Installing Playwright..."
|
||||||
|
npm install -g @playwright/test
|
||||||
|
npx playwright install-deps chromium
|
||||||
|
npx playwright install chromium
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# POSTGRESQL & REDIS
|
||||||
|
# ============================================
|
||||||
|
log "🗄️ Installing databases..."
|
||||||
|
sudo apt install -y postgresql postgresql-contrib redis-server
|
||||||
|
sudo systemctl enable --now postgresql
|
||||||
|
sudo systemctl enable --now redis-server
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# CLOUD TOOLS
|
||||||
|
# ============================================
|
||||||
|
log "☁️ Installing cloud tools..."
|
||||||
|
|
||||||
|
# AWS CLI
|
||||||
|
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
|
||||||
|
unzip -q awscliv2.zip
|
||||||
|
sudo ./aws/install
|
||||||
|
rm -rf aws awscliv2.zip
|
||||||
|
|
||||||
|
# Google Cloud SDK
|
||||||
|
echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" | sudo tee /etc/apt/sources.list.d/google-cloud-sdk.list
|
||||||
|
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key --keyring /usr/share/keyrings/cloud.google.gpg add -
|
||||||
|
sudo apt update && sudo apt install -y google-cloud-cli
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# KUBERNETES TOOLS
|
||||||
|
# ============================================
|
||||||
|
log "☸️ Installing Kubernetes tools..."
|
||||||
|
sudo snap install kubectl --classic
|
||||||
|
sudo snap install helm --classic
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# TERRAFORM
|
||||||
|
# ============================================
|
||||||
|
log "🏗️ Installing Terraform..."
|
||||||
|
wget -O- https://apt.releases.hashicorp.com/gpg | gpg --dearmor | sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg > /dev/null
|
||||||
|
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
|
||||||
|
sudo apt update && sudo apt install -y terraform
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# VS CODE SERVER
|
||||||
|
# ============================================
|
||||||
|
log "📝 Installing VS Code Server..."
|
||||||
|
curl -fsSL https://code-server.dev/install.sh | sh
|
||||||
|
|
||||||
|
# Configure code-server
|
||||||
|
mkdir -p ~/.config/code-server
|
||||||
|
cat > ~/.config/code-server/config.yaml << 'EOF'
|
||||||
|
bind-addr: 0.0.0.0:8080
|
||||||
|
auth: password
|
||||||
|
password: devmatrix-setup-2024
|
||||||
|
cert: false
|
||||||
|
EOF
|
||||||
|
|
||||||
|
sudo systemctl enable --now code-server@$USER
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# WORKSPACE STRUCTURE
|
||||||
|
# ============================================
|
||||||
|
log "📁 Creating workspace structure..."
|
||||||
|
mkdir -p ~/{projects,scripts,docs,backups,logs}
|
||||||
|
cd ~/projects
|
||||||
|
mkdir -p {mobile,web,desktop,backend,infrastructure,experiments}
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# VM CONTROL SCRIPTS
|
||||||
|
# ============================================
|
||||||
|
log "🤖 Creating VM control scripts..."
|
||||||
|
|
||||||
|
mkdir -p ~/scripts
|
||||||
|
|
||||||
|
# VM Control Script
|
||||||
|
cat > ~/scripts/vm_control.sh << 'EOF'
|
||||||
|
#!/bin/bash
|
||||||
|
PROXMOX_HOST="192.168.5.200"
|
||||||
|
WIN_VMID=301
|
||||||
|
ANDROID_VMID=302
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
win-start)
|
||||||
|
ssh root@$PROXMOX_HOST "qm start $WIN_VMID"
|
||||||
|
echo "Windows VM starting..."
|
||||||
|
;;
|
||||||
|
win-stop)
|
||||||
|
ssh root@$PROXMOX_HOST "qm stop $WIN_VMID"
|
||||||
|
echo "Windows VM stopping..."
|
||||||
|
;;
|
||||||
|
win-status)
|
||||||
|
ssh root@$PROXMOX_HOST "qm status $WIN_VMID"
|
||||||
|
;;
|
||||||
|
android-start)
|
||||||
|
ssh root@$PROXMOX_HOST "qm start $ANDROID_VMID"
|
||||||
|
echo "Android VM starting..."
|
||||||
|
;;
|
||||||
|
android-stop)
|
||||||
|
ssh root@$PROXMOX_HOST "qm stop $ANDROID_VMID"
|
||||||
|
echo "Android VM stopping..."
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Usage: $0 {win-start|win-stop|win-status|android-start|android-stop}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
EOF
|
||||||
|
chmod +x ~/scripts/vm_control.sh
|
||||||
|
|
||||||
|
# Windows Test Script
|
||||||
|
cat > ~/scripts/test_on_windows.sh << 'EOF'
|
||||||
|
#!/bin/bash
|
||||||
|
# Build and test .NET app on Windows VM
|
||||||
|
|
||||||
|
PROJECT_PATH="$1"
|
||||||
|
WIN_IP="192.168.5.201" # Adjust based on your DHCP
|
||||||
|
WIN_USER="testuser"
|
||||||
|
|
||||||
|
if [ -z "$PROJECT_PATH" ]; then
|
||||||
|
echo "Usage: $0 <project-path>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "🪟 Starting Windows test sequence..."
|
||||||
|
|
||||||
|
# 1. Start Windows VM
|
||||||
|
~/scripts/vm_control.sh win-start
|
||||||
|
sleep 60
|
||||||
|
|
||||||
|
# 2. Build for Windows
|
||||||
|
echo "🔨 Building for Windows..."
|
||||||
|
dotnet publish "$PROJECT_PATH" -c Release -r win-x64 --self-contained
|
||||||
|
|
||||||
|
# 3. Copy to Windows
|
||||||
|
echo "📤 Deploying to Windows VM..."
|
||||||
|
scp -r "$PROJECT_PATH/bin/Release/net8.0/win-x64/publish/" "$WIN_USER@$WIN_IP:/C:/Apps/TestApp/"
|
||||||
|
|
||||||
|
# 4. Run test
|
||||||
|
ssh "$WIN_USER@$WIN_IP" "C:\\Apps\\TestApp\\TestApp.exe --version"
|
||||||
|
|
||||||
|
# 5. Stop VM
|
||||||
|
~/scripts/vm_control.sh win-stop
|
||||||
|
|
||||||
|
echo "✅ Windows test complete!"
|
||||||
|
EOF
|
||||||
|
chmod +x ~/scripts/test_on_windows.sh
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# OPENCLAW CONFIGURATION FRAMEWORK
|
||||||
|
# ============================================
|
||||||
|
log "⚙️ Creating OpenClaw configuration framework..."
|
||||||
|
|
||||||
|
mkdir -p ~/.openclaw/workspaces/devmatrix
|
||||||
|
|
||||||
|
# Routing configuration
|
||||||
|
cat > ~/.openclaw/workspaces/devmatrix/routing.yaml << 'EOF'
|
||||||
|
routing:
|
||||||
|
strategy: "smart_fallback"
|
||||||
|
|
||||||
|
rules:
|
||||||
|
- name: "complex_tasks"
|
||||||
|
pattern: ".*(architecture|design|refactor|implement|create).*"
|
||||||
|
model: "kimi/k2p5"
|
||||||
|
priority: 1
|
||||||
|
|
||||||
|
- name: "quick_fixes"
|
||||||
|
pattern: ".*(fix|bug|error|typo|simple).*"
|
||||||
|
model: "antigravity/mixtral-8x7b"
|
||||||
|
priority: 2
|
||||||
|
|
||||||
|
- name: "documentation"
|
||||||
|
pattern: ".*(doc|comment|readme|explain).*"
|
||||||
|
model: "antigravity/qwen2.5-coder"
|
||||||
|
priority: 2
|
||||||
|
|
||||||
|
- name: "default"
|
||||||
|
pattern: ".*"
|
||||||
|
model: "kimi/k2p5"
|
||||||
|
priority: 99
|
||||||
|
|
||||||
|
cost_optimization:
|
||||||
|
monthly_budget: 100
|
||||||
|
alert_threshold: 80
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Swarm configuration
|
||||||
|
cat > ~/.openclaw/workspaces/devmatrix/swarm.yaml << 'EOF'
|
||||||
|
swarm:
|
||||||
|
name: "DevMatrix Swarm"
|
||||||
|
max_concurrent: 8
|
||||||
|
default_timeout: 300
|
||||||
|
|
||||||
|
agents:
|
||||||
|
- id: "architect"
|
||||||
|
name: "System Architect"
|
||||||
|
model: "kimi/k2p5"
|
||||||
|
|
||||||
|
- id: "frontend"
|
||||||
|
name: "Frontend Lead"
|
||||||
|
model: "kimi/k2p5"
|
||||||
|
|
||||||
|
- id: "backend"
|
||||||
|
name: "Backend Lead"
|
||||||
|
model: "kimi/k2p5"
|
||||||
|
|
||||||
|
- id: "devops"
|
||||||
|
name: "DevOps Engineer"
|
||||||
|
model: "antigravity/mixtral-8x7b"
|
||||||
|
|
||||||
|
- id: "qa"
|
||||||
|
name: "QA Engineer"
|
||||||
|
model: "antigravity/qwen2.5-coder"
|
||||||
|
|
||||||
|
- id: "windows_tester"
|
||||||
|
name: "Windows Test Agent"
|
||||||
|
model: "antigravity/mixtral-8x7b"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# API KEY CONFIGURATION SCRIPT
|
||||||
|
# ============================================
|
||||||
|
log "🔑 Creating API key configuration script..."
|
||||||
|
|
||||||
|
cat > ~/scripts/configure_api_keys.sh << 'EOFSCRIPT'
|
||||||
|
#!/bin/bash
|
||||||
|
# Configure API Keys for OpenClaw
|
||||||
|
# Run this after setup to add your API keys
|
||||||
|
|
||||||
|
echo "🔐 DevMatrix API Key Configuration"
|
||||||
|
echo "==================================="
|
||||||
|
echo ""
|
||||||
|
echo "You will need:"
|
||||||
|
echo " 1. Kimi API Key (from https://kimi.moonshot.cn/)"
|
||||||
|
echo " 2. Antigravity API Key (from your provider)"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Kimi API Key
|
||||||
|
read -sp "Enter your Kimi API Key: " KIMI_KEY
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Antigravity API Key
|
||||||
|
read -sp "Enter your Antigravity API Key: " ANTIGRAVITY_KEY
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Create config directory
|
||||||
|
mkdir -p ~/.openclaw/config
|
||||||
|
|
||||||
|
# Save Kimi config
|
||||||
|
cat > ~/.openclaw/config/kimi.yaml << EOF
|
||||||
|
provider: kimi
|
||||||
|
name: "Kimi K2.5"
|
||||||
|
auth:
|
||||||
|
type: api_key
|
||||||
|
key: "$KIMI_KEY"
|
||||||
|
models:
|
||||||
|
primary:
|
||||||
|
id: "k2p5"
|
||||||
|
max_tokens: 128000
|
||||||
|
fallback:
|
||||||
|
id: "k1.5"
|
||||||
|
max_tokens: 64000
|
||||||
|
routing:
|
||||||
|
priority: 1
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Save Antigravity config
|
||||||
|
cat > ~/.openclaw/config/antigravity.yaml << EOF
|
||||||
|
provider: antigravity
|
||||||
|
name: "Antigravity"
|
||||||
|
auth:
|
||||||
|
type: api_key
|
||||||
|
key: "$ANTIGRAVITY_KEY"
|
||||||
|
models:
|
||||||
|
primary:
|
||||||
|
id: "mixtral-8x7b"
|
||||||
|
max_tokens: 32000
|
||||||
|
secondary:
|
||||||
|
id: "qwen2.5-coder"
|
||||||
|
max_tokens: 32000
|
||||||
|
routing:
|
||||||
|
priority: 2
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Set permissions
|
||||||
|
chmod 600 ~/.openclaw/config/*.yaml
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "✅ API Keys configured!"
|
||||||
|
echo ""
|
||||||
|
echo "Test with: openclaw models list"
|
||||||
|
echo ""
|
||||||
|
EOFSCRIPT
|
||||||
|
chmod +x ~/scripts/configure_api_keys.sh
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# BASH ALIASES
|
||||||
|
# ============================================
|
||||||
|
log "📝 Creating bash aliases..."
|
||||||
|
|
||||||
|
cat >> ~/.bashrc << 'EOF'
|
||||||
|
|
||||||
|
# DevMatrix Aliases
|
||||||
|
alias devmatrix-status='~/scripts/vm_control.sh win-status'
|
||||||
|
alias devmatrix-win-start='~/scripts/vm_control.sh win-start'
|
||||||
|
alias devmatrix-win-stop='~/scripts/vm_control.sh win-stop'
|
||||||
|
alias devmatrix-config='~/scripts/configure_api_keys.sh'
|
||||||
|
alias oc='openclaw'
|
||||||
|
alias ocs='openclaw sessions'
|
||||||
|
alias ocm='openclaw models'
|
||||||
|
|
||||||
|
# Development aliases
|
||||||
|
alias serve='python3 -m http.server'
|
||||||
|
alias myip='curl -s ipinfo.io/ip'
|
||||||
|
alias ports='sudo netstat -tulanp'
|
||||||
|
|
||||||
|
# Add paths
|
||||||
|
export PATH="$HOME/.local/bin:$HOME/.cargo/bin:$HOME/.openclaw/bin:$PATH"
|
||||||
|
export OPENCLAW_WORKSPACE="$HOME/.openclaw/workspaces/devmatrix"
|
||||||
|
|
||||||
|
# Welcome message
|
||||||
|
if command -v figlet &> /dev/null; then
|
||||||
|
echo ""
|
||||||
|
figlet -f slant "DevMatrix" 2>/dev/null || echo "DevMatrix"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
echo "🦞 OpenClaw DevMatrix Environment"
|
||||||
|
echo "================================"
|
||||||
|
echo "📂 Projects: ~/projects"
|
||||||
|
echo "📝 VS Code: http://$(hostname -I | awk '{print $1}'):8080"
|
||||||
|
echo "🐳 Docker: $(docker --version 2>/dev/null | cut -d' ' -f3 | tr -d ',')"
|
||||||
|
echo "🎯 Flutter: $(flutter --version 2>/dev/null | head -1)"
|
||||||
|
echo "🔷 .NET: $(dotnet --version 2>/dev/null)"
|
||||||
|
echo ""
|
||||||
|
echo "Next: Run '~/scripts/configure_api_keys.sh' to add your API keys"
|
||||||
|
echo ""
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# SUMMARY
|
||||||
|
# ============================================
|
||||||
|
log "🎉 DevMatrix Environment Setup Complete!"
|
||||||
|
echo ""
|
||||||
|
echo "╔════════════════════════════════════════════════════════════╗"
|
||||||
|
echo "║ SETUP COMPLETE ║"
|
||||||
|
echo "╠════════════════════════════════════════════════════════════╣"
|
||||||
|
echo "║ ║"
|
||||||
|
echo "║ 🦞 OpenClaw: Installed at ~/.openclaw ║"
|
||||||
|
echo "║ 📱 Flutter: Installed (snap) ║"
|
||||||
|
echo "║ 🔷 .NET 8: Installed ║"
|
||||||
|
echo "║ 🐳 Docker: Installed and running ║"
|
||||||
|
echo "║ 🗄️ PostgreSQL: Installed and running ║"
|
||||||
|
echo "║ 📊 Redis: Installed and running ║"
|
||||||
|
echo "║ 📝 VS Code: http://$(hostname -I | awk '{print $1}'):8080 ║"
|
||||||
|
echo "║ ║"
|
||||||
|
echo "╠════════════════════════════════════════════════════════════╣"
|
||||||
|
echo "║ NEXT STEP: Run '~/scripts/configure_api_keys.sh' ║"
|
||||||
|
echo "║ to add your Kimi and Antigravity API keys ║"
|
||||||
|
echo "╚════════════════════════════════════════════════════════════╝"
|
||||||
|
echo ""
|
||||||
|
|
@ -0,0 +1,309 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# TrueNAS Integration Script for DevMatrix
|
||||||
|
# Run this INSIDE VM 300 (OpenClaw-DevMatrix) after OS setup
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
TRUENAS_IP="192.168.5.195"
|
||||||
|
TRUENAS_DATASET="NAS2"
|
||||||
|
MOUNT_BASE="/mnt/truenas"
|
||||||
|
|
||||||
|
# Colors
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
log() { echo -e "${GREEN}[TrueNAS]${NC} $1"; }
|
||||||
|
warn() { echo -e "${YELLOW}[Warning]${NC} $1"; }
|
||||||
|
error() { echo -e "${RED}[Error]${NC} $1"; exit 1; }
|
||||||
|
|
||||||
|
log "☁️ Setting up TrueNAS integration..."
|
||||||
|
echo " TrueNAS IP: $TRUENAS_IP"
|
||||||
|
echo " Dataset: $TRUENAS_DATASET"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# INSTALL NFS CLIENT
|
||||||
|
# ============================================
|
||||||
|
log "📦 Installing NFS client..."
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install -y nfs-common
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# CREATE MOUNT POINTS
|
||||||
|
# ============================================
|
||||||
|
log "📁 Creating mount points..."
|
||||||
|
|
||||||
|
sudo mkdir -p $MOUNT_BASE/{projects,backups,iso-archive,shared}
|
||||||
|
|
||||||
|
# Set permissions
|
||||||
|
sudo chown -R $(id -u):$(id -g) $MOUNT_BASE
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# CONFIGURE NFS MOUNTS
|
||||||
|
# ============================================
|
||||||
|
log "⚙️ Configuring NFS mounts..."
|
||||||
|
|
||||||
|
# Check if we can reach TrueNAS
|
||||||
|
if ! ping -c 1 $TRUENAS_IP >/dev/null 2>&1; then
|
||||||
|
error "Cannot reach TrueNAS at $TRUENAS_IP"
|
||||||
|
fi
|
||||||
|
log "✓ TrueNAS is reachable"
|
||||||
|
|
||||||
|
# Show available shares
|
||||||
|
echo ""
|
||||||
|
echo "Checking available NFS shares on TrueNAS..."
|
||||||
|
showmount -e $TRUENAS_IP 2>/dev/null || warn "Cannot list exports. Make sure NFS is enabled on TrueNAS."
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Expected shares (create these on TrueNAS if not present):"
|
||||||
|
echo " - /mnt/$TRUENAS_DATASET/devmatrix/projects"
|
||||||
|
echo " - /mnt/$TRUENAS_DATASET/devmatrix/backups"
|
||||||
|
echo " - /mnt/$TRUENAS_DATASET/devmatrix/iso-archive"
|
||||||
|
echo " - /mnt/$TRUENAS_DATASET/devmatrix/shared"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# CREATE FSTAB ENTRIES
|
||||||
|
# ============================================
|
||||||
|
log "📝 Adding mount entries to /etc/fstab..."
|
||||||
|
|
||||||
|
# Backup original fstab
|
||||||
|
sudo cp /etc/fstab /etc/fstab.backup.$(date +%Y%m%d)
|
||||||
|
|
||||||
|
# Add entries
|
||||||
|
cat << EOF | sudo tee -a /etc/fstab
|
||||||
|
|
||||||
|
# TrueNAS mounts for DevMatrix
|
||||||
|
# Format: server:path mountpoint type options dump pass
|
||||||
|
$TRUENAS_IP:/mnt/$TRUENAS_DATASET/devmatrix/projects $MOUNT_BASE/projects nfs defaults,_netdev,rw,sync,hard,intr 0 0
|
||||||
|
$TRUENAS_IP:/mnt/$TRUENAS_DATASET/devmatrix/backups $MOUNT_BASE/backups nfs defaults,_netdev,rw,sync,hard,intr 0 0
|
||||||
|
$TRUENAS_IP:/mnt/$TRUENAS_DATASET/devmatrix/iso-archive $MOUNT_BASE/iso-archive nfs defaults,_netdev,ro,sync,hard,intr 0 0
|
||||||
|
$TRUENAS_IP:/mnt/$TRUENAS_DATASET/devmatrix/shared $MOUNT_BASE/shared nfs defaults,_netdev,rw,sync,hard,intr 0 0
|
||||||
|
EOF
|
||||||
|
|
||||||
|
log "✓ fstab entries added"
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# MOUNT SHARES
|
||||||
|
# ============================================
|
||||||
|
log "🔗 Mounting shares..."
|
||||||
|
|
||||||
|
# Try to mount all
|
||||||
|
sudo mount -a 2>&1 || {
|
||||||
|
warn "Some mounts failed. This is expected if shares don't exist yet."
|
||||||
|
warn "Set up shares on TrueNAS first, then run: sudo mount -a"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check what's mounted
|
||||||
|
echo ""
|
||||||
|
echo "Currently mounted TrueNAS shares:"
|
||||||
|
df -h | grep $TRUENAS_IP || echo " (none mounted yet)"
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# CREATE SYMLINKS
|
||||||
|
# ============================================
|
||||||
|
log "🔗 Creating convenience symlinks..."
|
||||||
|
|
||||||
|
# In home directory
|
||||||
|
ln -sf $MOUNT_BASE/projects ~/projects-nas
|
||||||
|
ln -sf $MOUNT_BASE/backups ~/backups-nas
|
||||||
|
ln -sf $MOUNT_BASE/shared ~/shared-nas
|
||||||
|
|
||||||
|
# In standard locations
|
||||||
|
sudo mkdir -p /opt/truenas
|
||||||
|
sudo ln -sf $MOUNT_BASE/shared /opt/truenas/shared
|
||||||
|
|
||||||
|
log "✓ Symlinks created:"
|
||||||
|
echo " ~/projects-nas → TrueNAS projects"
|
||||||
|
echo " ~/backups-nas → TrueNAS backups"
|
||||||
|
echo " ~/shared-nas → TrueNAS shared"
|
||||||
|
echo " /opt/truenas → TrueNAS shared (system-wide)"
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# SETUP AUTO-MOUNT
|
||||||
|
# ============================================
|
||||||
|
log "⚙️ Configuring auto-mount..."
|
||||||
|
|
||||||
|
# Enable rpcbind for NFS
|
||||||
|
sudo systemctl enable rpcbind
|
||||||
|
sudo systemctl start rpcbind
|
||||||
|
|
||||||
|
# Create systemd mount units for reliability
|
||||||
|
cat > /tmp/truenas-projects.mount << EOF
|
||||||
|
[Unit]
|
||||||
|
Description=TrueNAS Projects Mount
|
||||||
|
After=network-online.target
|
||||||
|
Wants=network-online.target
|
||||||
|
|
||||||
|
[Mount]
|
||||||
|
What=$TRUENAS_IP:/mnt/$TRUENAS_DATASET/devmatrix/projects
|
||||||
|
Where=$MOUNT_BASE/projects
|
||||||
|
Type=nfs
|
||||||
|
Options=defaults,_netdev,rw,sync,hard,intr
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
|
||||||
|
sudo mv /tmp/truenas-projects.mount /etc/systemd/system/
|
||||||
|
sudo systemctl daemon-reload
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# BACKUP SCRIPT
|
||||||
|
# ============================================
|
||||||
|
log "📝 Creating backup helper script..."
|
||||||
|
|
||||||
|
mkdir -p ~/scripts
|
||||||
|
|
||||||
|
cat > ~/scripts/backup_to_truenas.sh << 'EOFSCRIPT'
|
||||||
|
#!/bin/bash
|
||||||
|
# Backup important data to TrueNAS
|
||||||
|
|
||||||
|
BACKUP_DIR="/mnt/truenas/backups/$(hostname)/$(date +%Y-%m-%d)"
|
||||||
|
LOG_FILE="/tmp/backup_$(date +%Y%m%d_%H%M%S).log"
|
||||||
|
|
||||||
|
echo "Starting backup to TrueNAS..."
|
||||||
|
echo "Destination: $BACKUP_DIR"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Create backup directory
|
||||||
|
mkdir -p "$BACKUP_DIR"
|
||||||
|
|
||||||
|
# Backup projects
|
||||||
|
if [ -d ~/projects ]; then
|
||||||
|
echo "Backing up projects..."
|
||||||
|
rsync -avz --progress ~/projects/ "$BACKUP_DIR/projects/" 2>&1 | tee -a $LOG_FILE
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Backup OpenClaw config
|
||||||
|
if [ -d ~/.openclaw ]; then
|
||||||
|
echo "Backing up OpenClaw config..."
|
||||||
|
rsync -avz --progress ~/.openclaw/ "$BACKUP_DIR/openclaw/" 2>&1 | tee -a $LOG_FILE
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Backup scripts
|
||||||
|
if [ -d ~/scripts ]; then
|
||||||
|
echo "Backing up scripts..."
|
||||||
|
rsync -avz --progress ~/scripts/ "$BACKUP_DIR/scripts/" 2>&1 | tee -a $LOG_FILE
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create backup manifest
|
||||||
|
cat > "$BACKUP_DIR/backup-manifest.txt" << EOF
|
||||||
|
Backup Date: $(date)
|
||||||
|
Hostname: $(hostname)
|
||||||
|
User: $(whoami)
|
||||||
|
Source: ~/projects, ~/.openclaw, ~/scripts
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Backup complete!"
|
||||||
|
echo "Log: $LOG_FILE"
|
||||||
|
echo "Location: $BACKUP_DIR"
|
||||||
|
EOFSCRIPT
|
||||||
|
|
||||||
|
chmod +x ~/scripts/backup_to_truenas.sh
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# RESTORE SCRIPT
|
||||||
|
# ============================================
|
||||||
|
cat > ~/scripts/restore_from_truenas.sh << 'EOFSCRIPT'
|
||||||
|
#!/bin/bash
|
||||||
|
# Restore from TrueNAS backup
|
||||||
|
|
||||||
|
if [ -z "$1" ]; then
|
||||||
|
echo "Usage: $0 <backup-date>"
|
||||||
|
echo "Example: $0 2024-02-16"
|
||||||
|
echo ""
|
||||||
|
echo "Available backups:"
|
||||||
|
ls /mnt/truenas/backups/$(hostname)/ 2>/dev/null || echo " (no backups found)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
BACKUP_DATE="$1"
|
||||||
|
BACKUP_DIR="/mnt/truenas/backups/$(hostname)/$BACKUP_DATE"
|
||||||
|
|
||||||
|
if [ ! -d "$BACKUP_DIR" ]; then
|
||||||
|
echo "Error: Backup not found: $BACKUP_DIR"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Restoring from backup: $BACKUP_DATE"
|
||||||
|
echo "Source: $BACKUP_DIR"
|
||||||
|
echo ""
|
||||||
|
read -p "Are you sure? This will overwrite existing files! (y/N): " confirm
|
||||||
|
|
||||||
|
if [ "$confirm" != "y" ]; then
|
||||||
|
echo "Cancelled."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Restore projects
|
||||||
|
if [ -d "$BACKUP_DIR/projects" ]; then
|
||||||
|
echo "Restoring projects..."
|
||||||
|
rsync -avz "$BACKUP_DIR/projects/" ~/projects/
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Restore OpenClaw config
|
||||||
|
if [ -d "$BACKUP_DIR/openclaw" ]; then
|
||||||
|
echo "Restoring OpenClaw config..."
|
||||||
|
rsync -avz "$BACKUP_DIR/openclaw/" ~/.openclaw/
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Restore scripts
|
||||||
|
if [ -d "$BACKUP_DIR/scripts" ]; then
|
||||||
|
echo "Restoring scripts..."
|
||||||
|
rsync -avz "$BACKUP_DIR/scripts/" ~/scripts/
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Restore complete!"
|
||||||
|
EOFSCRIPT
|
||||||
|
|
||||||
|
chmod +x ~/scripts/restore_from_truenas.sh
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# SUMMARY
|
||||||
|
# ============================================
|
||||||
|
log "☁️ TrueNAS integration complete!"
|
||||||
|
echo ""
|
||||||
|
echo "╔════════════════════════════════════════════════════════╗"
|
||||||
|
echo "║ TRUENAS CONFIGURATION ║"
|
||||||
|
echo "╠════════════════════════════════════════════════════════╣"
|
||||||
|
echo "║ ║"
|
||||||
|
echo "║ Mount Points: ║"
|
||||||
|
echo "║ /mnt/truenas/projects - Project storage ║"
|
||||||
|
echo "║ /mnt/truenas/backups - Backup storage ║"
|
||||||
|
echo "║ /mnt/truenas/iso-archive - ISO storage ║"
|
||||||
|
echo "║ /mnt/truenas/shared - Shared files ║"
|
||||||
|
echo "║ ║"
|
||||||
|
echo "║ Symlinks: ║"
|
||||||
|
echo "║ ~/projects-nas → /mnt/truenas/projects ║"
|
||||||
|
echo "║ ~/backups-nas → /mnt/truenas/backups ║"
|
||||||
|
echo "║ ~/shared-nas → /mnt/truenas/shared ║"
|
||||||
|
echo "║ ║"
|
||||||
|
echo "║ Helper Scripts: ║"
|
||||||
|
echo "║ ~/scripts/backup_to_truenas.sh - Backup data ║"
|
||||||
|
echo "║ ~/scripts/restore_from_truenas.sh - Restore data ║"
|
||||||
|
echo "║ ║"
|
||||||
|
echo "╚════════════════════════════════════════════════════════╝"
|
||||||
|
echo ""
|
||||||
|
echo "⚠️ IMPORTANT: Create shares on TrueNAS first!"
|
||||||
|
echo ""
|
||||||
|
echo "On TrueNAS ($TRUENAS_IP):"
|
||||||
|
echo "1. Go to Storage → Pools → $TRUENAS_DATASET"
|
||||||
|
echo "2. Create dataset: devmatrix"
|
||||||
|
echo "3. Create sub-datasets:"
|
||||||
|
echo " - devmatrix/projects"
|
||||||
|
echo " - devmatrix/backups"
|
||||||
|
echo " - devmatrix/iso-archive"
|
||||||
|
echo " - devmatrix/shared"
|
||||||
|
echo "4. Go to Sharing → Unix (NFS) Shares"
|
||||||
|
echo "5. Add NFS shares for each dataset"
|
||||||
|
echo "6. Set permissions to allow this VM's IP ($(hostname -I | awk '{print $1}'))"
|
||||||
|
echo ""
|
||||||
|
echo "Then run: sudo mount -a"
|
||||||
|
echo ""
|
||||||
|
|
@ -0,0 +1,177 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# TrueNAS Share Setup Script for DevMatrix
|
||||||
|
# Run this on TrueNAS (192.168.5.195) as root
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
DATASET_NAME="NAS2"
|
||||||
|
SHARE_PREFIX="devmatrix"
|
||||||
|
NETWORK_ALLOW="192.168.5.0/24"
|
||||||
|
|
||||||
|
echo "☁️ Setting up TrueNAS shares for DevMatrix..."
|
||||||
|
echo " Dataset: $DATASET_NAME"
|
||||||
|
echo " Network: $NETWORK_ALLOW"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# CREATE DATASET STRUCTURE
|
||||||
|
# ============================================
|
||||||
|
echo "📁 Creating dataset structure..."
|
||||||
|
|
||||||
|
# Main dataset (if not exists)
|
||||||
|
if ! zfs list "$DATASET_NAME/$SHARE_PREFIX" >/devdev/null 2>&1; then
|
||||||
|
zfs create "$DATASET_NAME/$SHARE_PREFIX"
|
||||||
|
echo "✓ Created: $DATASET_NAME/$SHARE_PREFIX"
|
||||||
|
else
|
||||||
|
echo "✓ Exists: $DATASET_NAME/$SHARE_PREFIX"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Sub-datasets
|
||||||
|
for subdir in projects backups iso-archive shared; do
|
||||||
|
dataset_path="$DATASET_NAME/$SHARE_PREFIX/$subdir"
|
||||||
|
if ! zfs list "$dataset_path" >/dev/null 2>&1; then
|
||||||
|
zfs create "$dataset_path"
|
||||||
|
echo "✓ Created: $dataset_path"
|
||||||
|
else
|
||||||
|
echo "✓ Exists: $dataset_path"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# SET PERMISSIONS
|
||||||
|
# ============================================
|
||||||
|
echo ""
|
||||||
|
echo "🔐 Setting permissions..."
|
||||||
|
|
||||||
|
# Set ownership (nobody:nogroup for NFS)
|
||||||
|
for subdir in projects backups iso-archive shared; do
|
||||||
|
mountpoint=$(zfs get -H -o value mountpoint "$DATASET_NAME/$SHARE_PREFIX/$subdir")
|
||||||
|
chown -R nobody:nogroup "$mountpoint"
|
||||||
|
chmod -R 777 "$mountpoint"
|
||||||
|
echo "✓ Permissions set for: $subdir"
|
||||||
|
done
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# CREATE NFS SHARES
|
||||||
|
# ============================================
|
||||||
|
echo ""
|
||||||
|
echo "🔗 Creating NFS shares..."
|
||||||
|
|
||||||
|
# Function to create NFS share
|
||||||
|
create_nfs_share() {
|
||||||
|
local name=$1
|
||||||
|
local path=$2
|
||||||
|
local options=$3
|
||||||
|
|
||||||
|
# Check if share already exists
|
||||||
|
if midclt call sharing.nfs.query "[[\"path\",\"=\",\"$path\"]]" | grep -q "$path"; then
|
||||||
|
echo "✓ NFS share exists: $name"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create share using midclt (TrueNAS API)
|
||||||
|
midclt call sharing.nfs.create "{
|
||||||
|
\"path\": \"$path\",
|
||||||
|
\"comment\": \"DevMatrix $name\",
|
||||||
|
\"hosts\": [\"$NETWORK_ALLOW\"],
|
||||||
|
\"ro\": $options,
|
||||||
|
\"maproot_user\": \"root\",
|
||||||
|
\"maproot_group\": \"root\",
|
||||||
|
\"mapall_user\": \"\",
|
||||||
|
\"mapall_group\": \"\",
|
||||||
|
\"security\": [\"sys\"]
|
||||||
|
}" > /dev/null
|
||||||
|
|
||||||
|
echo "✓ Created NFS share: $name ($path)"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create shares
|
||||||
|
mountpoint_base=$(zfs get -H -o value mountpoint "$DATASET_NAME")
|
||||||
|
|
||||||
|
create_nfs_share "projects" "$mountpoint_base/$SHARE_PREFIX/projects" "false"
|
||||||
|
create_nfs_share "backups" "$mountpoint_base/$SHARE_PREFIX/backups" "false"
|
||||||
|
create_nfs_share "iso-archive" "$mountpoint_base/$SHARE_PREFIX/iso-archive" "false"
|
||||||
|
create_nfs_share "shared" "$mountpoint_base/$SHARE_PREFIX/shared" "false"
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# ENABLE NFS SERVICE
|
||||||
|
# ============================================
|
||||||
|
echo ""
|
||||||
|
echo "🚀 Enabling NFS service..."
|
||||||
|
|
||||||
|
# Check if NFS is running
|
||||||
|
if ! midclt call service.query "[[\"service\",\"=\",\"nfs\"]]" | grep -q '"state": "RUNNING"'; then
|
||||||
|
midclt call service.start "nfs" > /dev/null
|
||||||
|
midclt call service.update "nfs" '{"enable": true}' > /dev/null
|
||||||
|
echo "✓ NFS service started and enabled"
|
||||||
|
else
|
||||||
|
echo "✓ NFS service already running"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# CREATE SMB SHARES (Optional - for Windows access)
|
||||||
|
# ============================================
|
||||||
|
echo ""
|
||||||
|
echo "🖥️ Creating SMB shares (for Windows access)..."
|
||||||
|
|
||||||
|
# Enable SMB if not already
|
||||||
|
if ! midclt call service.query "[[\"service\",\"=\",\"cifs\"]]" | grep -q '"state": "RUNNING"'; then
|
||||||
|
midclt call service.start "cifs" > /dev/null
|
||||||
|
midclt call service.update "cifs" '{"enable": true}' > /dev/null
|
||||||
|
echo "✓ SMB service started and enabled"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Function to create SMB share
|
||||||
|
create_smb_share() {
|
||||||
|
local name=$1
|
||||||
|
local path=$2
|
||||||
|
|
||||||
|
# Check if exists
|
||||||
|
if midclt call sharing.smb.query "[[\"path\",\"=\",\"$path\"]]" | grep -q "$path"; then
|
||||||
|
echo "✓ SMB share exists: $name"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
midclt call sharing.smb.create "{
|
||||||
|
\"path\": \"$path\",
|
||||||
|
\"name\": \"devmatrix-$name\",
|
||||||
|
\"comment\": \"DevMatrix $name\",
|
||||||
|
\"browseable\": true,
|
||||||
|
\"readonly\": false,
|
||||||
|
\"guestok\": true,
|
||||||
|
\"afp\": false
|
||||||
|
}" > /dev/null
|
||||||
|
|
||||||
|
echo "✓ Created SMB share: devmatrix-$name"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create SMB shares
|
||||||
|
create_smb_share "projects" "$mountpoint_base/$SHARE_PREFIX/projects"
|
||||||
|
create_smb_share "backups" "$mountpoint_base/$SHARE_PREFIX/backups"
|
||||||
|
create_smb_share "shared" "$mountpoint_base/$SHARE_PREFIX/shared"
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# SUMMARY
|
||||||
|
# ============================================
|
||||||
|
echo ""
|
||||||
|
echo "╔════════════════════════════════════════════════════════╗"
|
||||||
|
echo "║ TRUENAS SETUP COMPLETE ║"
|
||||||
|
echo "╠════════════════════════════════════════════════════════╣"
|
||||||
|
echo "║ ║"
|
||||||
|
echo "║ NFS Shares (for Linux VMs): ║"
|
||||||
|
echo "║ $mountpoint_base/$SHARE_PREFIX/projects ║"
|
||||||
|
echo "║ $mountpoint_base/$SHARE_PREFIX/backups ║"
|
||||||
|
echo "║ $mountpoint_base/$SHARE_PREFIX/iso-archive ║"
|
||||||
|
echo "║ $mountpoint_base/$SHARE_PREFIX/shared ║"
|
||||||
|
echo "║ ║"
|
||||||
|
echo "║ SMB Shares (for Windows): ║"
|
||||||
|
echo "║ \\$(hostname)\\devmatrix-projects ║"
|
||||||
|
echo "║ \\$(hostname)\\devmatrix-backups ║"
|
||||||
|
echo "║ \\$(hostname)\\devmatrix-shared ║"
|
||||||
|
echo "║ ║"
|
||||||
|
echo "║ Access from: $NETWORK_ALLOW ║"
|
||||||
|
echo "║ ║"
|
||||||
|
echo "╚════════════════════════════════════════════════════════╝"
|
||||||
|
echo ""
|
||||||
|
echo "Next: Run 'setup_truenas.sh' inside VM 300 to mount these shares"
|
||||||
|
|
@ -0,0 +1,339 @@
|
||||||
|
# Windows 11 LTSC IoT VM Setup Script
|
||||||
|
# Run this INSIDE the Windows VM after installation
|
||||||
|
# Run as Administrator in PowerShell
|
||||||
|
|
||||||
|
#Requires -RunAsAdministrator
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# CONFIGURATION
|
||||||
|
# ============================================
|
||||||
|
$VM_IP = "192.168.5.211" # Static IP for Windows VM
|
||||||
|
$MAIN_DEV_IP = "192.168.5.210" # IP of your Ubuntu Dev VM
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
function Write-Info { param($Message) Write-Host "[INFO] $Message" -ForegroundColor Cyan }
|
||||||
|
function Write-Success { param($Message) Write-Host "[SUCCESS] $Message" -ForegroundColor Green }
|
||||||
|
function Write-Warning { param($Message) Write-Host "[WARNING] $Message" -ForegroundColor Yellow }
|
||||||
|
function Write-Error { param($Message) Write-Host "[ERROR] $Message" -ForegroundColor Red }
|
||||||
|
|
||||||
|
Write-Info "Starting Windows LTSC IoT VM Setup..."
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# ENABLE SSH SERVER
|
||||||
|
# ============================================
|
||||||
|
Write-Info "Enabling OpenSSH Server..."
|
||||||
|
|
||||||
|
# Install OpenSSH Server
|
||||||
|
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
|
||||||
|
|
||||||
|
# Start and enable service
|
||||||
|
Start-Service sshd
|
||||||
|
Set-Service -Name sshd -StartupType 'Automatic'
|
||||||
|
|
||||||
|
# Configure firewall
|
||||||
|
if (!(Get-NetFirewallRule -Name "OpenSSH-Server-In-TCP" -ErrorAction SilentlyContinue)) {
|
||||||
|
New-NetFirewallRule -Name "OpenSSH-Server-In-TCP" -DisplayName "OpenSSH Server (sshd)" `
|
||||||
|
-Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Success "SSH Server enabled"
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# ENABLE RDP
|
||||||
|
# ============================================
|
||||||
|
Write-Info "Enabling Remote Desktop..."
|
||||||
|
|
||||||
|
Set-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Terminal Server' `
|
||||||
|
-Name "fDenyTSConnections" -Value 0
|
||||||
|
|
||||||
|
Enable-NetFirewallRule -DisplayGroup "Remote Desktop"
|
||||||
|
|
||||||
|
# Enhanced RDP security
|
||||||
|
Set-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' `
|
||||||
|
-Name "UserAuthentication" -Value 1
|
||||||
|
|
||||||
|
Write-Success "RDP enabled"
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# CREATE TEST USER
|
||||||
|
# ============================================
|
||||||
|
Write-Info "Creating test user account..."
|
||||||
|
|
||||||
|
$TestUser = "testuser"
|
||||||
|
$TestPassword = ConvertTo-SecureString "DevMatrix2024!" -AsPlainText -Force
|
||||||
|
|
||||||
|
# Check if user exists
|
||||||
|
if (!(Get-LocalUser -Name $TestUser -ErrorAction SilentlyContinue)) {
|
||||||
|
New-LocalUser -Name $TestUser -Password $TestPassword `
|
||||||
|
-FullName "Test User" -Description "DevMatrix Test Account"
|
||||||
|
Add-LocalGroupMember -Group "Administrators" -Member $TestUser
|
||||||
|
Add-LocalGroupMember -Group "Remote Desktop Users" -Member $TestUser
|
||||||
|
Write-Success "Test user '$TestUser' created"
|
||||||
|
} else {
|
||||||
|
Write-Warning "Test user already exists"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# INSTALL CHOCOLATEY
|
||||||
|
# ============================================
|
||||||
|
Write-Info "Installing Chocolatey package manager..."
|
||||||
|
|
||||||
|
if (!(Get-Command choco -ErrorAction SilentlyContinue)) {
|
||||||
|
Set-ExecutionPolicy Bypass -Scope Process -Force
|
||||||
|
[System.Net.ServicePointManager]::SecurityProtocol = `
|
||||||
|
[System.Net.ServicePointManager]::SecurityProtocol -bor 3072
|
||||||
|
Invoke-Expression ((New-Object System.Net.WebClient). `
|
||||||
|
DownloadString('https://community.chocolatey.org/install.ps1'))
|
||||||
|
|
||||||
|
# Refresh environment
|
||||||
|
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + `
|
||||||
|
[System.Environment]::GetEnvironmentVariable("Path","User")
|
||||||
|
|
||||||
|
Write-Success "Chocolatey installed"
|
||||||
|
} else {
|
||||||
|
Write-Warning "Chocolatey already installed"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# INSTALL DEVELOPMENT TOOLS
|
||||||
|
# ============================================
|
||||||
|
Write-Info "Installing development tools..."
|
||||||
|
|
||||||
|
$packages = @(
|
||||||
|
"git"
|
||||||
|
"python"
|
||||||
|
"nodejs"
|
||||||
|
"dotnet-sdk"
|
||||||
|
"vscode"
|
||||||
|
"firefox"
|
||||||
|
"googlechrome"
|
||||||
|
"7zip"
|
||||||
|
"powertoys"
|
||||||
|
"sysinternals"
|
||||||
|
"processhacker"
|
||||||
|
)
|
||||||
|
|
||||||
|
foreach ($pkg in $packages) {
|
||||||
|
Write-Info "Installing $pkg..."
|
||||||
|
choco install $pkg -y --no-progress
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Success "Development tools installed"
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# INSTALL PLAYWRIGHT
|
||||||
|
# ============================================
|
||||||
|
Write-Info "Installing Playwright for UI testing..."
|
||||||
|
|
||||||
|
npm install -g @playwright/test
|
||||||
|
npx playwright install chromium firefox webkit
|
||||||
|
npx playwright install-deps
|
||||||
|
|
||||||
|
Write-Success "Playwright installed"
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# CREATE TEST DIRECTORIES
|
||||||
|
# ============================================
|
||||||
|
Write-Info "Creating test directories..."
|
||||||
|
|
||||||
|
$directories = @(
|
||||||
|
"C:\Apps",
|
||||||
|
"C:\Tests",
|
||||||
|
"C:\Projects",
|
||||||
|
"C:\Results",
|
||||||
|
"C:\Scripts"
|
||||||
|
)
|
||||||
|
|
||||||
|
foreach ($dir in $directories) {
|
||||||
|
if (!(Test-Path $dir)) {
|
||||||
|
New-Item -ItemType Directory -Force -Path $dir
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Success "Test directories created"
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# CREATE TEST RUNNER SCRIPTS
|
||||||
|
# ============================================
|
||||||
|
Write-Info "Creating test automation scripts..."
|
||||||
|
|
||||||
|
# Simple test runner
|
||||||
|
$TestRunner = @'
|
||||||
|
@echo off
|
||||||
|
echo ========================================
|
||||||
|
echo DevMatrix Windows Test Runner
|
||||||
|
echo Started: %date% %time%
|
||||||
|
echo ========================================
|
||||||
|
echo.
|
||||||
|
|
||||||
|
if "%~1"=="" (
|
||||||
|
echo Usage: run_tests.bat ^<test-directory^>
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
set TEST_DIR=%~1
|
||||||
|
echo Running tests from: %TEST_DIR%
|
||||||
|
echo.
|
||||||
|
|
||||||
|
cd /d %TEST_DIR%
|
||||||
|
if errorlevel 1 (
|
||||||
|
echo ERROR: Cannot access directory %TEST_DIR%
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
echo Test Start > C:\Results\test_session.log
|
||||||
|
echo %date% %time% >> C:\Results\test_session.log
|
||||||
|
echo. >> C:\Results\test_session.log
|
||||||
|
|
||||||
|
REM Run Playwright tests if playwright.config.js exists
|
||||||
|
if exist "playwright.config.js" (
|
||||||
|
echo Running Playwright tests...
|
||||||
|
npx playwright test --reporter=html --output=C:\Results
|
||||||
|
set TEST_EXIT=%errorlevel%
|
||||||
|
) else (
|
||||||
|
echo No Playwright config found. Looking for other tests...
|
||||||
|
dir /s /b *.test.js *.spec.js > nul 2>&1
|
||||||
|
if !errorlevel!==0 (
|
||||||
|
echo Found JavaScript tests. Running with Node...
|
||||||
|
for /r %%i in (*.test.js *.spec.js) do (
|
||||||
|
echo Running: %%i
|
||||||
|
node "%%i" >> C:\Results\test_session.log 2>&1
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
echo. >> C:\Results\test_session.log
|
||||||
|
echo Test End: %date% %time% >> C:\Results\test_session.log
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ========================================
|
||||||
|
echo Tests complete. Results in C:\Results\
|
||||||
|
echo ========================================
|
||||||
|
|
||||||
|
exit /b %TEST_EXIT%
|
||||||
|
'@
|
||||||
|
|
||||||
|
$TestRunner | Out-File -FilePath "C:\Scripts\run_tests.bat" -Encoding ASCII
|
||||||
|
|
||||||
|
# App installer script
|
||||||
|
$AppInstaller = @'
|
||||||
|
@echo off
|
||||||
|
echo DevMatrix App Installer
|
||||||
|
echo =======================
|
||||||
|
|
||||||
|
if "%~1"=="" (
|
||||||
|
echo Usage: install_app.bat ^<path-to-app-files^>
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
set APP_PATH=%~1
|
||||||
|
set APP_NAME=%~n1
|
||||||
|
|
||||||
|
echo Installing: %APP_NAME%
|
||||||
|
echo From: %APP_PATH%
|
||||||
|
|
||||||
|
REM Create app directory
|
||||||
|
if not exist "C:\Apps\%APP_NAME%" mkdir "C:\Apps\%APP_NAME%"
|
||||||
|
|
||||||
|
REM Copy files
|
||||||
|
xcopy /E /I /Y "%APP_PATH%\*" "C:\Apps\%APP_NAME%\"
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo Installation complete: C:\Apps\%APP_NAME%\
|
||||||
|
echo.
|
||||||
|
echo To run: C:\Apps\%APP_NAME%\%APP_NAME%.exe
|
||||||
|
'@
|
||||||
|
|
||||||
|
$AppInstaller | Out-File -FilePath "C:\Scripts\install_app.bat" -Encoding ASCII
|
||||||
|
|
||||||
|
Write-Success "Automation scripts created"
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# CONFIGURE WINRM (FOR AUTOMATION)
|
||||||
|
# ============================================
|
||||||
|
Write-Info "Configuring WinRM for remote automation..."
|
||||||
|
|
||||||
|
# Enable WinRM
|
||||||
|
Enable-PSRemoting -Force -SkipNetworkProfileCheck
|
||||||
|
|
||||||
|
# Configure WinRM to allow unencrypted (local network only)
|
||||||
|
Set-Item WSMan:\localhost\Service\AllowUnencrypted -Value $true
|
||||||
|
Set-Item WSMan:\localhost\Service\Auth\Basic -Value $true
|
||||||
|
|
||||||
|
# Configure firewall
|
||||||
|
Set-NetFirewallRule -Name "WINRM-HTTP-In-TCP" -RemoteAddress LocalSubnet
|
||||||
|
Set-NetFirewallRule -Name "WINRM-HTTP-In-TCP-PUBLIC" -RemoteAddress LocalSubnet
|
||||||
|
|
||||||
|
Write-Success "WinRM configured"
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# INSTALL WSL2 (OPTIONAL)
|
||||||
|
# ============================================
|
||||||
|
Write-Info "Installing WSL2 for Linux compatibility..."
|
||||||
|
|
||||||
|
# Enable WSL
|
||||||
|
wsl --install --no-distribution
|
||||||
|
|
||||||
|
Write-Success "WSL2 installed (reboot required to complete)"
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# PERFORMANCE OPTIMIZATIONS
|
||||||
|
# ============================================
|
||||||
|
Write-Info "Applying performance optimizations..."
|
||||||
|
|
||||||
|
# Disable unnecessary visual effects
|
||||||
|
$regPath = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\VisualEffects"
|
||||||
|
Set-ItemProperty -Path $regPath -Name "VisualFXSetting" -Value 2
|
||||||
|
|
||||||
|
# Set high performance power plan
|
||||||
|
powercfg /setactive 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c
|
||||||
|
|
||||||
|
# Disable Windows Search indexing for test directories
|
||||||
|
Add-Content -Path "C:\Windows\System32\WindowsPowerShell\v1.0\Profile.ps1" -Value @"
|
||||||
|
# DevMatrix Performance Settings
|
||||||
|
`$env:DOTNET_CLI_TELEMETRY_OPTOUT = 1
|
||||||
|
`$env:POWERSHELL_TELEMETRY_OPTOUT = 1
|
||||||
|
"@
|
||||||
|
|
||||||
|
Write-Success "Performance optimizations applied"
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# CREATE FIREWALL RULES FOR DEVMATRIX
|
||||||
|
# ============================================
|
||||||
|
Write-Info "Creating DevMatrix firewall rules..."
|
||||||
|
|
||||||
|
# Allow traffic from main dev VM
|
||||||
|
New-NetFirewallRule -DisplayName "DevMatrix-DevVM" `
|
||||||
|
-Direction Inbound -Action Allow `
|
||||||
|
-RemoteAddress $MAIN_DEV_IP `
|
||||||
|
-Profile Private
|
||||||
|
|
||||||
|
# Allow file sharing
|
||||||
|
Set-NetFirewallRule -DisplayGroup "File and Printer Sharing" -Enabled True -Profile Private
|
||||||
|
|
||||||
|
Write-Success "Firewall rules created"
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# SUMMARY
|
||||||
|
# ============================================
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "╔════════════════════════════════════════════════════════════╗" -ForegroundColor Green
|
||||||
|
Write-Host "║ WINDOWS VM SETUP COMPLETE ║" -ForegroundColor Green
|
||||||
|
Write-Host "╠════════════════════════════════════════════════════════════╣" -ForegroundColor Green
|
||||||
|
Write-Host "║ ║" -ForegroundColor Green
|
||||||
|
Write-Host "║ ✅ SSH Server: Enabled on port 22 ║" -ForegroundColor Green
|
||||||
|
Write-Host "║ ✅ RDP: Enabled ║" -ForegroundColor Green
|
||||||
|
Write-Host "║ ✅ Test User: testuser / DevMatrix2024! ║" -ForegroundColor Green
|
||||||
|
Write-Host "║ ✅ Dev Tools: Git, Python, Node, .NET, VS Code ║" -ForegroundColor Green
|
||||||
|
Write-Host "║ ✅ Testing: Playwright installed ║" -ForegroundColor Green
|
||||||
|
Write-Host "║ ✅ Directories: C:\Apps, C:\Tests, C:\Results ║" -ForegroundColor Green
|
||||||
|
Write-Host "║ ║" -ForegroundColor Green
|
||||||
|
Write-Host "╠════════════════════════════════════════════════════════════╣" -ForegroundColor Green
|
||||||
|
Write-Host "║ Connect from Dev VM: ║" -ForegroundColor Green
|
||||||
|
Write-Host "║ ssh testuser@$VM_IP ║" -ForegroundColor Green
|
||||||
|
Write-Host "║ scp -r ./app testuser@${VM_IP}:/C:/Apps/ ║" -ForegroundColor Green
|
||||||
|
Write-Host "╚════════════════════════════════════════════════════════════╝" -ForegroundColor Green
|
||||||
|
Write-Host ""
|
||||||
|
Write-Warning "REBOOT REQUIRED for WSL2 to complete installation"
|
||||||
|
Write-Host ""
|
||||||
|
Write-Info "After reboot, this VM is ready for automated testing!"
|
||||||
Loading…
Reference in New Issue