diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d23687b --- /dev/null +++ b/Makefile @@ -0,0 +1,130 @@ +# ORION Infrastructure - One-Command Deployment +# Usage: make deploy + +.PHONY: help init plan apply destroy clean status verify + +# Default target +.DEFAULT_GOAL := help + +##@ General + +help: ## Display this help + @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) + +##@ Setup + +check-prereqs: ## Check prerequisites + @echo "πŸ” Checking prerequisites..." + @command -v terraform >/dev/null 2>&1 || { echo "❌ Terraform not installed"; exit 1; } + @command -v ansible >/dev/null 2>&1 || { echo "❌ Ansible not installed"; exit 1; } + @command -v kubectl >/dev/null 2>&1 || { echo "⚠️ kubectl not installed (optional)"; } + @test -f terraform/terraform.tfvars || { echo "❌ terraform/terraform.tfvars not found. Copy terraform.tfvars.example"; exit 1; } + @echo "βœ… Prerequisites OK" + +init: check-prereqs ## Initialize Terraform + @echo "πŸ—οΈ Initializing Terraform..." + @cd terraform && terraform init + +##@ Deployment + +plan: init ## Plan infrastructure changes + @echo "πŸ“‹ Planning infrastructure..." + @cd terraform && terraform plan + +apply: init ## Deploy infrastructure + @echo "πŸš€ Deploying infrastructure..." + @cd terraform && terraform apply + @echo "" + @echo "βœ… Infrastructure deployed!" + @echo "πŸ“Š Run 'make outputs' to see deployment details" + +deploy: apply configure ## Full deployment: infrastructure + configuration + @echo "πŸŽ‰ ORION deployment complete!" + +##@ Configuration + +configure: ## Configure VMs with Ansible + @echo "βš™οΈ Configuring VMs with Ansible..." + @echo "⚠️ Ansible playbooks need to be created first" + @echo "πŸ“ Next step: cd ansible && ansible-playbook -i inventory playbooks/site.yml" + +##@ Kubernetes + +k8s-deploy: ## Deploy Kubernetes workloads + @echo "☸️ Deploying Kubernetes workloads..." + @kubectl apply -k kubernetes/infrastructure/ + @kubectl apply -k kubernetes/applications/ + @kubectl apply -k kubernetes/ai-agents/ + +##@ Management + +outputs: ## Show Terraform outputs + @cd terraform && terraform output deployment_summary + +status: ## Show infrastructure status + @echo "πŸ“Š Infrastructure Status:" + @cd terraform && terraform show -json | jq -r '.values.root_module.resources[] | select(.type == "proxmox_vm_qemu") | "\(.values.name) (VM \(.values.vmid)): \(.values.ipconfig0)"' + +destroy: ## Destroy infrastructure (DANGEROUS!) + @echo "⚠️ WARNING: This will destroy all infrastructure!" + @echo "Press Ctrl+C to cancel, or Enter to continue..." + @read confirm + @cd terraform && terraform destroy + +clean: ## Clean Terraform state and cache + @echo "🧹 Cleaning Terraform files..." + @rm -rf terraform/.terraform + @rm -f terraform/.terraform.lock.hcl + @rm -f terraform/terraform-plugin-proxmox.log + +##@ Validation + +verify: ## Verify deployment + @echo "βœ… Verifying deployment..." + @echo "" + @echo "Checking VMs..." + @cd terraform && terraform output k8s_master_ips + @cd terraform && terraform output k8s_worker_ips + @echo "" + @echo "Testing connectivity..." + @ping -c 1 192.168.100.1 >/dev/null 2>&1 && echo "βœ… Router reachable" || echo "❌ Router not reachable" + @ping -c 1 192.168.100.30 >/dev/null 2>&1 && echo "βœ… AI Coordinator reachable" || echo "❌ AI Coordinator not reachable" + @ping -c 1 192.168.100.50 >/dev/null 2>&1 && echo "βœ… NetBox reachable" || echo "❌ NetBox not reachable" + +##@ Documentation + +docs: ## Generate documentation + @echo "πŸ“š Documentation:" + @echo " Architecture: ARCHITECTURE_REVIEW.md" + @echo " Reference: docs/reference/" + @echo " Terraform: terraform/README.md" + +##@ Development + +fmt: ## Format Terraform files + @cd terraform && terraform fmt -recursive + +validate: init ## Validate Terraform configuration + @cd terraform && terraform validate + +##@ Quick Start + +quickstart: check-prereqs ## Quick start guide + @echo "╔═══════════════════════════════════════════════════════════════╗" + @echo "β•‘ ORION Infrastructure - Quick Start β•‘" + @echo "β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•" + @echo "" + @echo "1️⃣ Setup:" + @echo " cp terraform/terraform.tfvars.example terraform/terraform.tfvars" + @echo " # Edit terraform.tfvars with your Proxmox API token" + @echo "" + @echo "2️⃣ Deploy:" + @echo " make deploy" + @echo "" + @echo "3️⃣ Verify:" + @echo " make verify" + @echo "" + @echo "4️⃣ Access:" + @echo " make outputs" + @echo "" + @echo "πŸ“š Documentation: make docs" diff --git a/terraform/main.tf b/terraform/main.tf new file mode 100644 index 0000000..18e0466 --- /dev/null +++ b/terraform/main.tf @@ -0,0 +1,249 @@ +# ORION Infrastructure - Main Terraform Configuration +# Defines all VMs for the complete stack + +locals { + common_tags = concat(var.tags, [var.environment]) +} + +# ============================================================================= +# VM 200: Router (BIRD2 BGP, IPv6, Firewall) +# ============================================================================= + +resource "proxmox_vm_qemu" "router" { + name = "ORION-Router" + target_node = var.proxmox_node + vmid = 200 + + clone = var.cloud_init_template + full_clone = true + + cores = 8 + sockets = 1 + memory = 32768 + + disk { + slot = 0 + size = "50G" + type = "scsi" + storage = var.vm_storage_pool + ssd = 1 + } + + # WAN interface (vmbr0) + network { + model = "virtio" + bridge = "vmbr0" + tag = var.network_vlan_id + } + + # LAN interface (vmbr1) + network { + model = "virtio" + bridge = "vmbr1" + } + + # Guest network interface (vmbr2) + network { + model = "virtio" + bridge = "vmbr2" + } + + # Management interface + network { + model = "virtio" + bridge = "vmbr1" + } + + os_type = "cloud-init" + ipconfig0 = "ip=dhcp" # WAN from Telus + ipconfig1 = "ip=192.168.100.1/24" + ipconfig2 = "ip=192.168.200.1/24" + ipconfig3 = "ip=192.168.1.1/24" + + nameserver = join(" ", var.network_dns) + + sshkeys = join("\n", var.vm_ssh_keys) + + onboot = var.auto_start + startup = "order=1,up=30" + + tags = join(";", concat(local.common_tags, ["router", "network"])) +} + +# ============================================================================= +# VM 300: AI Coordinator (Multi-Agent Orchestration) +# ============================================================================= + +resource "proxmox_vm_qemu" "ai_coordinator" { + name = "ORION-AI-Coordinator" + target_node = var.proxmox_node + vmid = 300 + + clone = var.cloud_init_template + full_clone = true + + cores = 4 + sockets = 1 + memory = 16384 + + disk { + slot = 0 + size = "100G" + type = "scsi" + storage = var.vm_storage_pool + ssd = 1 + } + + network { + model = "virtio" + bridge = "vmbr1" + } + + os_type = "cloud-init" + ipconfig0 = "ip=192.168.100.30/24,gw=${var.network_gateway}" + nameserver = join(" ", var.network_dns) + sshkeys = join("\n", var.vm_ssh_keys) + + onboot = var.auto_start + startup = "order=3,up=30" + + tags = join(";", concat(local.common_tags, ["ai", "coordinator"])) +} + +# ============================================================================= +# VM 500: NetBox (IPAM and Network Documentation) +# ============================================================================= + +resource "proxmox_vm_qemu" "netbox" { + count = var.enable_netbox ? 1 : 0 + + name = "ORION-NetBox" + target_node = var.proxmox_node + vmid = var.netbox_vm_id + + clone = var.cloud_init_template + full_clone = true + + cores = var.netbox_cores + sockets = 1 + memory = var.netbox_memory + + disk { + slot = 0 + size = var.netbox_disk_size + type = "scsi" + storage = var.vm_storage_pool + ssd = 1 + } + + network { + model = "virtio" + bridge = "vmbr1" + } + + os_type = "cloud-init" + ipconfig0 = "ip=${var.netbox_ip_address}/${var.netbox_cidr},gw=${var.network_gateway}" + nameserver = join(" ", var.network_dns) + sshkeys = join("\n", var.vm_ssh_keys) + + onboot = var.auto_start + startup = "order=2,up=30" + + tags = join(";", concat(local.common_tags, ["netbox", "ipam"])) +} + +# ============================================================================= +# VMs 600-603: Kubernetes Cluster (K3s) +# ============================================================================= + +# K3s Master Node +resource "proxmox_vm_qemu" "k8s_master" { + count = var.enable_k8s_cluster ? var.k8s_master_count : 0 + + name = "ORION-K3s-Master-${count.index + 1}" + target_node = var.proxmox_node + vmid = var.k8s_master_vm_id + count.index + + clone = var.cloud_init_template + full_clone = true + + cores = var.k8s_master_cores + sockets = 1 + memory = var.k8s_master_memory + + disk { + slot = 0 + size = var.k8s_disk_size + type = "scsi" + storage = var.vm_storage_pool + ssd = 1 + } + + network { + model = "virtio" + bridge = "vmbr1" + } + + os_type = "cloud-init" + ipconfig0 = "ip=${cidrhost("${var.k8s_ip_range_start}/24", count.index)}/${var.netbox_cidr},gw=${var.network_gateway}" + nameserver = join(" ", var.network_dns) + sshkeys = join("\n", var.vm_ssh_keys) + + onboot = var.auto_start + startup = "order=4,up=30" + + tags = join(";", concat(local.common_tags, ["kubernetes", "k3s", "master"])) +} + +# K3s Worker Nodes +resource "proxmox_vm_qemu" "k8s_workers" { + count = var.enable_k8s_cluster ? var.k8s_worker_count : 0 + + name = "ORION-K3s-Worker-${count.index + 1}" + target_node = var.proxmox_node + vmid = var.k8s_worker_vm_id_start + count.index + + clone = var.cloud_init_template + full_clone = true + + cores = var.k8s_worker_cores + sockets = 1 + memory = var.k8s_worker_memory + + disk { + slot = 0 + size = var.k8s_disk_size + type = "scsi" + storage = var.vm_storage_pool + ssd = 1 + } + + network { + model = "virtio" + bridge = "vmbr1" + } + + os_type = "cloud-init" + ipconfig0 = "ip=${cidrhost("${var.k8s_ip_range_start}/24", var.k8s_master_count + count.index)}/${var.netbox_cidr},gw=${var.network_gateway}" + nameserver = join(" ", var.network_dns) + sshkeys = join("\n", var.vm_ssh_keys) + + onboot = var.auto_start + startup = "order=5,up=30" + + tags = join(";", concat(local.common_tags, ["kubernetes", "k3s", "worker"])) +} + +# ============================================================================= +# VM 100: macOS Sequoia (Optional - Development) +# ============================================================================= +# Note: macOS VM requires special OpenCore configuration +# This is a placeholder - use existing deploy-orion.sh macOS logic + +# Uncomment and configure if deploying macOS: +# resource "proxmox_vm_qemu" "macos" { +# name = "HACK-Sequoia-01" +# target_node = var.proxmox_node +# vmid = 100 +# # ... macOS-specific configuration +# } diff --git a/terraform/outputs.tf b/terraform/outputs.tf new file mode 100644 index 0000000..6e26802 --- /dev/null +++ b/terraform/outputs.tf @@ -0,0 +1,89 @@ +# Terraform Outputs for ORION Infrastructure + +output "router_vm_id" { + description = "Router VM ID" + value = proxmox_vm_qemu.router.vmid +} + +output "router_ip_lan" { + description = "Router LAN IP" + value = "192.168.100.1" +} + +output "ai_coordinator_vm_id" { + description = "AI Coordinator VM ID" + value = proxmox_vm_qemu.ai_coordinator.vmid +} + +output "ai_coordinator_ip" { + description = "AI Coordinator IP" + value = "192.168.100.30" +} + +output "netbox_vm_id" { + description = "NetBox VM ID" + value = var.enable_netbox ? proxmox_vm_qemu.netbox[0].vmid : null +} + +output "netbox_ip" { + description = "NetBox IP address" + value = var.enable_netbox ? var.netbox_ip_address : null +} + +output "netbox_url" { + description = "NetBox web URL" + value = var.enable_netbox ? "http://${var.netbox_ip_address}:8000" : null +} + +output "k8s_master_ips" { + description = "K8s master node IPs" + value = var.enable_k8s_cluster ? [for i in range(var.k8s_master_count) : cidrhost("${var.k8s_ip_range_start}/24", i)] : [] +} + +output "k8s_worker_ips" { + description = "K8s worker node IPs" + value = var.enable_k8s_cluster ? [for i in range(var.k8s_worker_count) : cidrhost("${var.k8s_ip_range_start}/24", var.k8s_master_count + i)] : [] +} + +output "k8s_api_server" { + description = "K8s API server URL" + value = var.enable_k8s_cluster ? "https://${cidrhost("${var.k8s_ip_range_start}/24", 0)}:6443" : null +} + +output "deployment_summary" { + description = "Summary of deployed resources" + value = <<-EOT + + ╔═══════════════════════════════════════════════════════════════╗ + β•‘ ORION Infrastructure Deployment Summary β•‘ + β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β• + + Router: + - VM ID: ${proxmox_vm_qemu.router.vmid} + - LAN IP: 192.168.100.1 + - WAN: DHCP (Telus) + - Services: BIRD2 BGP, IPv6, Firewall + + AI Coordinator: + - VM ID: ${proxmox_vm_qemu.ai_coordinator.vmid} + - IP: 192.168.100.30 + - Purpose: Multi-agent orchestration + + NetBox: + - VM ID: ${var.enable_netbox ? proxmox_vm_qemu.netbox[0].vmid : "N/A"} + - IP: ${var.enable_netbox ? var.netbox_ip_address : "N/A"} + - URL: ${var.enable_netbox ? "http://${var.netbox_ip_address}:8000" : "N/A"} + + Kubernetes Cluster: + - Master IPs: ${var.enable_k8s_cluster ? join(", ", [for i in range(var.k8s_master_count) : cidrhost("${var.k8s_ip_range_start}/24", i)]) : "N/A"} + - Worker IPs: ${var.enable_k8s_cluster ? join(", ", [for i in range(var.k8s_worker_count) : cidrhost("${var.k8s_ip_range_start}/24", var.k8s_master_count + i)]) : "N/A"} + - API Server: ${var.enable_k8s_cluster ? "https://${cidrhost("${var.k8s_ip_range_start}/24", 0)}:6443" : "N/A"} + + Next Steps: + 1. Configure VMs: cd ../ansible && ansible-playbook -i inventory playbooks/site.yml + 2. Deploy K8s apps: cd ../kubernetes && kubectl apply -k infrastructure/ + 3. Access NetBox: http://${var.enable_netbox ? var.netbox_ip_address : "N/A"}:8000 + 4. Configure BGP: SSH to router and verify BIRD2 sessions + + EOT +}