diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 0000000..813b8d2 --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,131 @@ +{ + "$schema": "https://storage.googleapis.com/claude-code-public/settings_schema.json", + "model": "sonnet", + "statusLine": "πŸš€ ORION Infrastructure | {model} | {sessionId}", + "includeCoAuthoredBy": true, + "cleanupPeriodDays": 90, + "outputStyle": "concise-technical", + + "env": { + "ORION_PROJECT": "true", + "TERRAFORM_LOG": "INFO", + "ANSIBLE_STDOUT_CALLBACK": "yaml", + "SHELL": "/bin/zsh" + }, + + "permissions": { + "defaultMode": "ask", + "allow": [ + { + "tool": "Read", + "description": "Read project files" + }, + { + "tool": "Glob", + "description": "Search for files" + }, + { + "tool": "Grep", + "description": "Search file contents" + }, + { + "tool": "Bash", + "patterns": [ + "terraform.*", + "ansible-playbook.*", + "kubectl.*", + "make.*", + "git.*", + "ls.*", + "cat.*", + "grep.*", + "find.*" + ], + "description": "Infrastructure commands" + } + ], + "ask": [ + { + "tool": "Edit", + "description": "Modifications require review" + }, + { + "tool": "Write", + "description": "New files require approval" + }, + { + "tool": "Bash", + "patterns": [ + "ssh.*", + "scp.*", + "rsync.*", + "rm -rf.*", + "terraform destroy.*" + ], + "description": "Potentially dangerous operations" + } + ], + "deny": [ + { + "tool": "Bash", + "patterns": [ + "curl.*| bash", + "wget.*| sh", + "dd if=.*", + "mkfs.*", + "fdisk.*" + ], + "description": "Blocked: Pipe to shell, disk operations" + }, + { + "tool": "Read", + "patterns": [ + "**/*.pem", + "**/*.key", + "**/id_rsa*", + "**/*.pfx", + "**/terraform.tfvars", + "**/.env", + "**/credentials*" + ], + "description": "Blocked: Sensitive credential files" + }, + { + "tool": "Edit", + "patterns": [ + "**/*.pem", + "**/*.key", + "**/terraform.tfvars" + ], + "description": "Blocked: Cannot edit credentials" + } + ] + }, + + "sandbox": { + "enabled": true, + "autoAllowBashIfSandboxed": false, + "network": { + "allowLocalBinding": true, + "allowUnixSockets": [ + "/var/run/docker.sock" + ] + } + }, + + "hooks": { + "userPromptSubmit": { + "enabled": true, + "command": "git status --short", + "description": "Show git status before each command", + "continueOnError": true + } + }, + + "companyAnnouncements": [ + "πŸš€ ORION Infrastructure Project", + "πŸ“˜ Main docs: ARCHITECTURE.md", + "πŸ”§ Deploy: make deploy-full", + "⚠️ Always review infrastructure changes carefully!" + ] +} diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml new file mode 100644 index 0000000..e56abb6 --- /dev/null +++ b/.github/workflows/python-package.yml @@ -0,0 +1,40 @@ +# This workflow will install Python dependencies, run tests and lint with a variety of Python versions +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python + +name: Python package + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + build: + + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ["3.9", "3.10", "3.11"] + + steps: + - uses: actions/checkout@v4 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v3 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install flake8 pytest + if [ -f requirements.txt ]; then pip install -r requirements.txt; fi + - name: Lint with flake8 + run: | + # stop the build if there are Python syntax errors or undefined names + flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics + # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide + flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics + - name: Test with pytest + run: | + pytest diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml new file mode 100644 index 0000000..82f8dbd --- /dev/null +++ b/.github/workflows/python-publish.yml @@ -0,0 +1,70 @@ +# This workflow will upload a Python Package to PyPI when a release is created +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries + +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +name: Upload Python Package + +on: + release: + types: [published] + +permissions: + contents: read + +jobs: + release-build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: "3.x" + + - name: Build release distributions + run: | + # NOTE: put your own distribution build steps here. + python -m pip install build + python -m build + + - name: Upload distributions + uses: actions/upload-artifact@v4 + with: + name: release-dists + path: dist/ + + pypi-publish: + runs-on: ubuntu-latest + needs: + - release-build + permissions: + # IMPORTANT: this permission is mandatory for trusted publishing + id-token: write + + # Dedicated environments with protections for publishing are strongly recommended. + # For more information, see: https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment#deployment-protection-rules + environment: + name: pypi + # OPTIONAL: uncomment and update to include your PyPI project URL in the deployment status: + # url: https://pypi.org/p/YOURPROJECT + # + # ALTERNATIVE: if your GitHub Release name is the PyPI project version string + # ALTERNATIVE: exactly, uncomment the following line instead: + # url: https://pypi.org/project/YOURPROJECT/${{ github.event.release.name }} + + steps: + - name: Retrieve release distributions + uses: actions/download-artifact@v4 + with: + name: release-dists + path: dist/ + + - name: Publish release distributions to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + packages-dir: dist/ diff --git a/.gitignore b/.gitignore index 0f30459..71bac29 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,16 @@ .Trashes ehthumbs.db Thumbs.db -logs \ No newline at end of file +logs + +# Terraform +terraform/.terraform/ +terraform/.terraform.lock.hcl +terraform/terraform.tfstate* +terraform/terraform.tfvars +terraform/*.backup + +# Claude Code +.claude/settings.local.json +.claude/.session/ +.claude/chats/ diff --git a/AI_MAZE_ARCHITECTURE.md b/AI_MAZE_ARCHITECTURE.md new file mode 100644 index 0000000..6b52aa8 --- /dev/null +++ b/AI_MAZE_ARCHITECTURE.md @@ -0,0 +1,675 @@ +# AI Maze Architecture - Hardened Infrastructure with Backstage Portal + +**Version**: 1.0.0 +**Created**: 2025-01-22 +**Purpose**: Security-through-obscurity + Defense-in-depth using unconventional technology stack + +--- + +## 🎯 Concept: The "AI Maze" + +An infrastructure management portal that confuses automated crawlers, vulnerability scanners, and AI-powered reconnaissance tools by using an uncommon technology stack while providing a legitimate, user-friendly interface. + +### Why It Works + +1. **Signature Evasion**: Most scanners trained on LAMP/MEAN/JAMstack patterns +2. **Uncommon Stack**: Swift backend is rare for infrastructure tools +3. **Legitimate Tools**: Backstage is production-grade, not security theatre +4. **Defense in Depth**: Multiple layers with different technologies +5. **Confusion**: AI/ML models struggle with unexpected tech combinations + +--- + +## πŸ—οΈ Architecture Layers + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ PUBLIC INTERNET β”‚ +β”‚ (Automated Scanners/Crawlers) β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + ↓ + [Firewall/WAF] + - Rate limiting + - GeoIP blocking + - DDoS protection + ↓ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ LAYER 1: Backstage Developer Portal (VM 400) β”‚ +β”‚ ────────────────────────────────────────────────────────────────│ +β”‚ Technology: Node.js + React (TypeScript) β”‚ +β”‚ Port: 7007 (non-standard, reverse proxied) β”‚ +β”‚ IP: 192.168.100.40 β”‚ +β”‚ β”‚ +β”‚ Features: β”‚ +β”‚ βœ“ Service catalog (VMs, containers, infrastructure) β”‚ +β”‚ βœ“ TechDocs (infrastructure documentation) β”‚ +β”‚ βœ“ Software templates (VM deployment automation) β”‚ +β”‚ βœ“ Kubernetes plugin (if using k8s) β”‚ +β”‚ βœ“ Custom plugins for Proxmox management β”‚ +β”‚ β”‚ +β”‚ Security: β”‚ +β”‚ - OAuth2/OIDC authentication β”‚ +β”‚ - RBAC via Backstage permissions β”‚ +β”‚ - Only talks to Vapor API (never direct to Proxmox) β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + ↓ + [Internal Network] + No direct internet access + ↓ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ LAYER 2: Vapor API Middleware (VM 401) ← THE MAZE β”‚ +β”‚ ────────────────────────────────────────────────────────────────│ +β”‚ Technology: Swift + Vapor 4.x β”‚ +β”‚ Port: 8080 (firewalled, only accessible from Backstage VM) β”‚ +β”‚ IP: 192.168.100.41 β”‚ +β”‚ β”‚ +β”‚ Purpose: The "AI Maze" - Confuses automated scanners β”‚ +β”‚ β”‚ +β”‚ Features: β”‚ +β”‚ βœ“ Swift-based REST API (uncommon = scanner confusion) β”‚ +β”‚ βœ“ Custom request/response formats (not typical JSON REST) β”‚ +β”‚ βœ“ Token-based authentication with custom schemes β”‚ +β”‚ βœ“ Request obfuscation and fingerprint randomization β”‚ +β”‚ βœ“ Honeypot endpoints (fake vulns to detect scanners) β”‚ +β”‚ βœ“ Rate limiting per endpoint with exponential backoff β”‚ +β”‚ βœ“ Proxmox API translation layer β”‚ +β”‚ β”‚ +β”‚ Maze Techniques: β”‚ +β”‚ - Non-standard HTTP headers (X-ORION-*, not X-Forwarded-*) β”‚ +β”‚ - Custom error messages (not Apache/nginx patterns) β”‚ +β”‚ - Response timing randomization β”‚ +β”‚ - Fake technology signatures in headers β”‚ +β”‚ - Honeypot routes that ban on access β”‚ +β”‚ β”‚ +β”‚ Security: β”‚ +β”‚ - JWT validation (from Backstage) β”‚ +β”‚ - IP whitelist (only Backstage VM) β”‚ +β”‚ - Request signing/verification β”‚ +β”‚ - Audit logging of all API calls β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + ↓ + [Management Network] + Completely isolated + ↓ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ LAYER 3: Proxmox VE (Hypervisor) β”‚ +β”‚ ────────────────────────────────────────────────────────────────│ +β”‚ IP: 192.168.100.10:8006 β”‚ +β”‚ Access: ONLY via Vapor API middleware β”‚ +β”‚ Firewall: Port 8006 blocked from all except 192.168.100.41 β”‚ +β”‚ β”‚ +β”‚ Contains: β”‚ +β”‚ - Router VM (200) β”‚ +β”‚ - AI Agent VM (300) β”‚ +β”‚ - macOS VM (100) β”‚ +β”‚ - Backstage VM (400) ← new β”‚ +β”‚ - Vapor API VM (401) ← new β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +--- + +## πŸš€ Virtual Machine Specifications + +### VM 400: Backstage Developer Portal + +```json +{ + "id": 400, + "name": "ORION-Backstage", + "os": "Ubuntu 24.04 LTS", + "description": "Spotify Backstage developer portal for infrastructure management", + "resources": { + "cpu": { + "cores": 4, + "type": "host" + }, + "memory": "16GB", + "storage": "100GB" + }, + "network": [ + { + "bridge": "vmbr1", + "ip": "192.168.100.40/24", + "gateway": "192.168.100.1" + } + ], + "software": [ + "Node.js 20.x LTS", + "Backstage v1.23+", + "PostgreSQL 16 (for Backstage catalog)", + "nginx (reverse proxy)", + "Let's Encrypt SSL" + ], + "ports": { + "internal": 7007, + "external": 443 + }, + "autostart": true, + "startupOrder": 5 +} +``` + +### VM 401: Vapor API Middleware + +```json +{ + "id": 401, + "name": "ORION-VaporAPI", + "os": "Ubuntu 24.04 LTS", + "description": "Swift/Vapor API middleware - The AI Maze layer", + "resources": { + "cpu": { + "cores": 4, + "type": "host" + }, + "memory": "8GB", + "storage": "50GB" + }, + "network": [ + { + "bridge": "vmbr1", + "ip": "192.168.100.41/24", + "gateway": "192.168.100.1" + } + ], + "software": [ + "Swift 5.10+", + "Vapor 4.x", + "Redis (caching/rate limiting)", + "systemd (service management)" + ], + "ports": { + "internal": 8080, + "external": "none (firewalled)" + }, + "firewall": { + "allowFrom": ["192.168.100.40"], + "denyAll": true + }, + "autostart": true, + "startupOrder": 4 +} +``` + +--- + +## πŸ”’ Security Features: The "Maze" Techniques + +### 1. **Technology Signature Confusion** + +#### Standard Stack (What Scanners Expect): +``` +User β†’ nginx/Apache β†’ PHP/Node.js/Python β†’ MySQL/PostgreSQL + (Known signatures) (CVE databases) +``` + +#### AI Maze Stack (What We Deploy): +``` +User β†’ Backstage (Node) β†’ Vapor (Swift) β†’ Proxmox API + (Legitimate) (Uncommon) (Protected) +``` + +**Why it works:** +- Swift backend rarely used for infrastructure tools +- Scanners have minimal Swift vulnerability signatures +- No common framework patterns (Laravel, Express, Django) +- Custom error messages don't match known fingerprints + +### 2. **Honeypot Endpoints** + +Fake vulnerable endpoints that detect and ban scanners: + +```swift +// In Vapor API +app.get("wp-admin", "login.php", ".env", "config.php") { req -> Response in + // Log attacker IP + let ip = req.remoteAddress?.ipAddress ?? "unknown" + logger.warning("Scanner detected from \(ip) - accessing honeypot") + + // Ban IP via nftables + try await banIP(ip) + + // Return fake vulnerable response to waste scanner time + return Response( + status: .ok, + body: .init(string: generateFakeVulnerableHTML()) + ) +} +``` + +### 3. **Request Obfuscation** + +Custom request/response formats that confuse AI parsers: + +```swift +// Non-standard authentication +struct OrionAuthToken: Content { + let token: String + let timestamp: Int64 + let signature: String // HMAC-SHA512 + let nonce: String // Prevents replay +} + +// Custom response wrapper +struct OrionResponse: Content { + let data: T? + let meta: ResponseMeta + let _trace: String // Random UUID per request +} +``` + +### 4. **Response Timing Randomization** + +```swift +// Add random delay to prevent timing attacks and confuse automated tools +func randomDelay() async { + let delay = UInt64.random(in: 50_000_000...150_000_000) // 50-150ms + try? await Task.sleep(nanoseconds: delay) +} +``` + +### 5. **Fake Technology Headers** + +```swift +// Make scanners think we're running different tech +let fakeHeaders = [ + "X-Powered-By": "ASP.NET", // We're not .NET + "Server": "Microsoft-IIS/10.0", // We're not IIS + "X-AspNet-Version": "4.0.30319" +] +``` + +--- + +## πŸ“¦ Deployment Process + +### Step 1: Deploy Proxmox Base (Already Done) + +Use existing `deploy-orion-hybrid.py` to set up: +- Proxmox VE +- Router VM +- AI Agent VM +- macOS VM (optional) + +### Step 2: Create Vapor API VM + +```bash +# On Proxmox host +qm create 401 \ + --name ORION-VaporAPI \ + --cores 4 \ + --memory 8192 \ + --net0 virtio,bridge=vmbr1 \ + --scsi0 local-lvm:50 \ + --ostype l26 + +# Download Ubuntu 24.04 ISO +wget -O /var/lib/vz/template/iso/ubuntu-24.04-live-server-amd64.iso \ + https://releases.ubuntu.com/24.04/ubuntu-24.04-live-server-amd64.iso + +# Mount and start +qm set 401 --ide2 local:iso/ubuntu-24.04-live-server-amd64.iso,media=cdrom +qm start 401 +``` + +**Install Swift + Vapor:** +```bash +# SSH into VM 401 +ssh root@192.168.100.41 + +# Install Swift +wget https://download.swift.org/swift-5.10-release/ubuntu2404/swift-5.10-RELEASE/swift-5.10-RELEASE-ubuntu24.04.tar.gz +tar xzf swift-5.10-RELEASE-ubuntu24.04.tar.gz +mv swift-5.10-RELEASE-ubuntu24.04 /opt/swift +echo 'export PATH=/opt/swift/usr/bin:$PATH' >> ~/.bashrc +source ~/.bashrc + +# Create Vapor project +mkdir -p /opt/orion-api +cd /opt/orion-api +vapor new . --template api +``` + +### Step 3: Create Backstage VM + +```bash +# Create VM +qm create 400 \ + --name ORION-Backstage \ + --cores 4 \ + --memory 16384 \ + --net0 virtio,bridge=vmbr1 \ + --scsi0 local-lvm:100 \ + --ostype l26 + +qm set 400 --ide2 local:iso/ubuntu-24.04-live-server-amd64.iso,media=cdrom +qm start 400 +``` + +**Install Backstage:** +```bash +# SSH into VM 400 +ssh root@192.168.100.40 + +# Install Node.js 20 +curl -fsSL https://deb.nodesource.com/setup_20.x | bash - +apt-get install -y nodejs + +# Install Yarn +npm install -g yarn + +# Create Backstage app +npx @backstage/create-app@latest --skip-install +cd backstage +yarn install +``` + +### Step 4: Configure Firewall Rules + +```bash +# On Router VM (200) - using nftables +nft add rule inet filter input ip saddr 192.168.100.40 tcp dport 8080 ip daddr 192.168.100.41 accept comment "Backstage β†’ Vapor" +nft add rule inet filter input tcp dport 8080 drop comment "Block direct Vapor access" +nft add rule inet filter input ip saddr 192.168.100.41 tcp dport 8006 ip daddr 192.168.100.10 accept comment "Vapor β†’ Proxmox" +nft add rule inet filter input tcp dport 8006 drop comment "Block direct Proxmox access" +``` + +--- + +## πŸ”§ Sample Code: Vapor API Middleware + +Create `/opt/orion-api/Sources/App/routes.swift`: + +```swift +import Vapor +import Fluent + +func routes(_ app: Application) throws { + + // Health check (public) + app.get("health") { req async -> Response in + await randomDelay() + return Response(status: .ok, body: .init(string: "OK")) + } + + // Honeypot routes + let honeypots = ["wp-admin", "wp-login.php", ".env", "admin.php", "phpinfo.php"] + for route in honeypots { + app.get(route) { req async throws -> Response in + try await handleHoneypot(req) + } + } + + // Protected API group + let api = app.grouped("api", "v1") + api.grouped(OrionAuthMiddleware()).group("proxmox") { proxmox in + + // List VMs + proxmox.get("vms") { req async throws -> OrionResponse<[VMInfo]> in + await randomDelay() + let vms = try await ProxmoxClient.shared.listVMs() + return OrionResponse(data: vms, meta: ResponseMeta()) + } + + // Create VM + proxmox.post("vms") { req async throws -> OrionResponse in + await randomDelay() + let input = try req.content.decode(CreateVMRequest.self) + let vm = try await ProxmoxClient.shared.createVM(input) + return OrionResponse(data: vm, meta: ResponseMeta()) + } + + // Start VM + proxmox.post("vms", ":id", "start") { req async throws -> OrionResponse in + await randomDelay() + guard let id = req.parameters.get("id", as: Int.self) else { + throw Abort(.badRequest) + } + try await ProxmoxClient.shared.startVM(id) + return OrionResponse(data: "started", meta: ResponseMeta()) + } + } +} + +// Custom middleware for authentication +struct OrionAuthMiddleware: AsyncMiddleware { + func respond(to request: Request, chainingTo next: AsyncResponder) async throws -> Response { + // Verify JWT from Backstage + guard let token = request.headers.bearerAuthorization?.token else { + throw Abort(.unauthorized, reason: "Missing token") + } + + // Validate token + try await validateToken(token) + + // Add custom headers to confuse scanners + var response = try await next.respond(to: request) + response.headers.add(name: "X-Powered-By", value: "ASP.NET") + response.headers.add(name: "Server", value: "Microsoft-IIS/10.0") + response.headers.add(name: "X-ORION-Trace", value: UUID().uuidString) + + return response + } +} + +// Honeypot handler +func handleHoneypot(_ req: Request) async throws -> Response { + let ip = req.remoteAddress?.ipAddress ?? "unknown" + req.logger.warning("🍯 Honeypot triggered by \(ip) - \(req.url.path)") + + // Ban IP (integrate with router firewall) + try await banIP(ip) + + // Return fake vulnerable response + let fakeHTML = """ + + + Admin Login + +
+ + + +
+ + + """ + + return Response( + status: .ok, + headers: HTTPHeaders([ + ("Content-Type", "text/html"), + ("X-Powered-By", "PHP/7.4.33") + ]), + body: .init(string: fakeHTML) + ) +} + +// Random delay to confuse timing attacks +func randomDelay() async { + let delay = UInt64.random(in: 50_000_000...150_000_000) // 50-150ms + try? await Task.sleep(nanoseconds: delay) +} +``` + +--- + +## 🎨 Backstage Configuration + +Create custom Proxmox plugin in Backstage: + +**File: `packages/backend/src/plugins/proxmox.ts`** + +```typescript +import { Router } from 'express'; +import axios from 'axios'; + +const VAPOR_API_URL = 'http://192.168.100.41:8080/api/v1'; +const API_TOKEN = process.env.VAPOR_API_TOKEN; + +export default async function createPlugin(): Promise { + const router = Router(); + + // List VMs + router.get('/vms', async (req, res) => { + try { + const response = await axios.get(`${VAPOR_API_URL}/proxmox/vms`, { + headers: { + 'Authorization': `Bearer ${API_TOKEN}`, + 'X-ORION-Client': 'backstage' + } + }); + res.json(response.data); + } catch (error) { + res.status(500).json({ error: error.message }); + } + }); + + // Create VM + router.post('/vms', async (req, res) => { + try { + const response = await axios.post( + `${VAPOR_API_URL}/proxmox/vms`, + req.body, + { + headers: { + 'Authorization': `Bearer ${API_TOKEN}`, + 'X-ORION-Client': 'backstage' + } + } + ); + res.json(response.data); + } catch (error) { + res.status(500).json({ error: error.message }); + } + }); + + return router; +} +``` + +--- + +## πŸ“Š Expected Results: The "Maze" in Action + +### Scenario 1: Automated Scanner + +``` +Scanner: Nmap port scan β†’ Finds port 7007 open +Scanner: Banner grab β†’ Gets "nginx" (reverse proxy) +Scanner: Directory brute force β†’ Triggers honeypot +Result: IP banned via nftables, scanner thinks it found WordPress +Actual: No useful information gained, scanner wasted time +``` + +### Scenario 2: AI/ML Reconnaissance + +``` +AI Tool: Analyze HTTP responses β†’ No Laravel/Express patterns +AI Tool: Fingerprint stack β†’ Swift headers (uncommon, limited training data) +AI Tool: Try common exploits β†’ No matching vulnerabilities (wrong tech) +Result: AI model confused, gives up or provides wrong assessment +``` + +### Scenario 3: Legitimate User + +``` +User: Access Backstage UI β†’ Beautiful, functional portal +User: Click "Deploy VM" β†’ Backstage β†’ Vapor β†’ Proxmox (seamless) +User: View infrastructure β†’ Real-time data, clear interface +Result: Excellent UX, no awareness of security maze underneath +``` + +--- + +## πŸ” Monitoring the Maze + +### Metrics to Track + +1. **Honeypot Triggers**: How many IPs hit fake endpoints +2. **Banned IPs**: Automated scanner detection rate +3. **Request Patterns**: Identify bot vs. human behavior +4. **Technology Fingerprinting Attempts**: Log unusual User-Agents + +### Grafana Dashboard + +Add to AI Agent VM (300): + +```yaml +# Prometheus metrics from Vapor API +- job_name: 'vapor-api' + static_configs: + - targets: ['192.168.100.41:9090'] + metrics_path: '/metrics' +``` + +**Dashboard Panels:** +- Honeypot hits over time +- Banned IPs (geographic heatmap) +- Request latency (with randomization) +- Authentication failures +- Technology fingerprinting attempts + +--- + +## ⚠️ Limitations & Honest Assessment + +### What This Protects Against βœ… + +- βœ… Automated vulnerability scanners (Nmap, Nikto, etc.) +- βœ… AI-powered reconnaissance tools (limited Swift training) +- βœ… Script kiddies using common exploit tools +- βœ… Crawler bots looking for known vulnerabilities +- βœ… Mass scanning campaigns + +### What This Does NOT Protect Against ❌ + +- ❌ Determined human attackers +- ❌ Zero-day exploits in Swift/Vapor/Backstage +- ❌ Social engineering +- ❌ Insider threats +- ❌ DDoS attacks (need separate mitigation) +- ❌ Advanced persistent threats (APTs) + +### Security Through Obscurity Warning ⚠️ + +**This is NOT a replacement for:** +- Proper authentication/authorization +- Regular security updates +- Network segmentation +- Intrusion detection systems +- Security audits and penetration testing + +**This IS a complement to** defense-in-depth strategy. + +--- + +## πŸš€ Deployment Checklist + +- [ ] Deploy base Proxmox with existing ORION stack +- [ ] Create VM 401 (Vapor API) +- [ ] Install Swift + Vapor on VM 401 +- [ ] Implement Vapor API with honeypots +- [ ] Create VM 400 (Backstage) +- [ ] Install and configure Backstage +- [ ] Create Proxmox plugin for Backstage +- [ ] Configure firewall rules (block direct Proxmox access) +- [ ] Set up monitoring and alerting +- [ ] Test honeypot endpoints +- [ ] Test legitimate user workflows +- [ ] Document for team + +--- + +## πŸ“š Additional Resources + +- **Backstage**: https://backstage.io/docs +- **Vapor**: https://docs.vapor.codes/ +- **Swift Server**: https://www.swift.org/server/ +- **Security Through Obscurity**: https://owasp.org/www-community/controls/Security_by_Obscurity + +--- + +**Status**: Architecture documented, ready for implementation +**Next Steps**: Begin VM deployment and Vapor API development diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md new file mode 100644 index 0000000..bafa707 --- /dev/null +++ b/ARCHITECTURE.md @@ -0,0 +1,553 @@ +# ORION Infrastructure Architecture + +**Dell PowerEdge R730 - Proxmox VE Multi-Layer Infrastructure** + +Version: 2.0 (Post-Refactoring) +Last Updated: 2025-11-22 + +--- + +## 🎯 Overview + +ORION is a complete infrastructure stack built on a Dell R730 Proxmox VE hypervisor, designed from the ground up as an **AI-first, agent-driven architecture** with security hardening through technological obscurity ("AI Maze"). + +### Design Philosophy + +1. **Proper Domain Separation**: Clear boundaries between Infrastructure, Platform, Applications, AI/Agent, IPAM, and Observability layers +2. **Infrastructure as Code**: Terraform for declarative VM deployment, Ansible for configuration +3. **Hybrid Approach**: VMs for infrastructure, LXC for AI/ML, Kubernetes for applications +4. **AI-First**: Built around multi-agent orchestration with proper inference layer +5. **Security Through Obscurity**: Non-standard tech stack (Swift/Vapor, Backstage) to confuse automated scanners + +--- + +## πŸ—οΈ Architecture Layers + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Dell R730 Proxmox VE Host β”‚ +β”‚ (56 cores, 384GB RAM, dual 10GbE, iDRAC9) β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ Layer 0: Infrastructure VMs ──────────────┐ β”‚ +β”‚ β”‚ VM 200: Router (BIRD2 BGP, IPv6, Firewall) - 8C/32GB β”‚ β”‚ +β”‚ β”‚ VM 300: AI Coordinator (Multi-agent orchestration) - 4C/16GBβ”‚ β”‚ +β”‚ β”‚ VM 500: NetBox (IPAM, network docs) - 4C/8GB β”‚ β”‚ +β”‚ β”‚ VM 600-603: K3s Cluster (1 master, 3 workers) - 4C/8-16GB β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ Layer 1: LXC Containers (AI/ML) ────────────┐ β”‚ +β”‚ β”‚ LXC 1000: Ollama (llama3, codellama, mistral) β”‚ β”‚ +β”‚ β”‚ LXC 1001: OpenWebUI (ChatGPT-like interface) β”‚ β”‚ +β”‚ β”‚ LXC 1002: LiteLLM (API gateway, OpenAI compatible) β”‚ β”‚ +β”‚ β”‚ LXC 1003: FlowiseAI (Visual agent workflow builder) β”‚ β”‚ +β”‚ β”‚ LXC 1004: PostgreSQL + pgvector (Vector DB for RAG) β”‚ β”‚ +β”‚ β”‚ LXC 1005: Redis (Caching, rate limiting) β”‚ β”‚ +β”‚ β”‚ LXC 1006: Minio (S3-compatible storage) β”‚ β”‚ +β”‚ β”‚ LXC 1007: Nginx Proxy Manager (Reverse proxy with SSL) β”‚ β”‚ +β”‚ β”‚ LXC 1008: Wireguard (VPN for secure remote access) β”‚ β”‚ +β”‚ β”‚ LXC 1009: N8N (Workflow automation) β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ Layer 2: Kubernetes Workloads (K3s) ───────────┐ β”‚ +β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ Infrastructure: β”‚ β”‚ +β”‚ β”‚ β”œβ”€ kube-prometheus-stack (Prometheus, Grafana, AlertManager) β”‚ β”‚ +β”‚ β”‚ β”œβ”€ Cilium (CNI, network policy, eBPF) β”‚ β”‚ +β”‚ β”‚ └─ Longhorn (Distributed block storage) β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ Applications: β”‚ β”‚ +β”‚ β”‚ β”œβ”€ Backstage (Developer portal - "AI Maze" frontend) β”‚ β”‚ +β”‚ β”‚ └─ Vapor API (Swift middleware layer) β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ AI Agents: β”‚ β”‚ +β”‚ β”‚ β”œβ”€ Infrastructure Agent (resource management) β”‚ β”‚ +β”‚ β”‚ β”œβ”€ Network Agent (BGP, routing, firewall) β”‚ β”‚ +β”‚ β”‚ β”œβ”€ Security Agent (threat detection, hardening) β”‚ β”‚ +β”‚ β”‚ └─ DevOps Agent (CI/CD, deployments) β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +--- + +## πŸ”Œ Network Architecture + +### Physical Interfaces + +``` +Dell R730: +β”œβ”€ eno1 (10GbE) β†’ vmbr0 (WAN - Telus Fiber) +β”œβ”€ eno2 (10GbE) β†’ vmbr1 (LAN - 192.168.100.0/24) +β”œβ”€ eno3 (1GbE) β†’ vmbr2 (Guest - 192.168.200.0/24) +└─ iDRAC (IPMI) β†’ 192.168.1.100/24 +``` + +### IP Allocation + +| Network Segment | CIDR | Purpose | +|----------------|------|---------| +| WAN | DHCP from Telus | Internet uplink | +| LAN | 192.168.100.0/24 | Internal services | +| Guest | 192.168.200.0/24 | Isolated guest network | +| Management | 192.168.1.0/24 | iDRAC and management | + +### IPv6 BGP Routing + +**AS Number**: 394955 +**IPv6 Prefix**: 2602:F674::/48 +**Peer**: AS6939 (Telus) + +``` +Subnet Allocation (2602:F674::/48): +β”œβ”€ 2602:F674:0000::/64 β†’ WAN/Transit +β”œβ”€ 2602:F674:1000::/64 β†’ LAN +β”œβ”€ 2602:F674:2000::/64 β†’ Guest +β”œβ”€ 2602:F674:3000::/64 β†’ Management +β”œβ”€ 2602:F674:4000::/64 β†’ K8s Pods +└─ 2602:F674:5000::/64 β†’ K8s Services +``` + +**BGP Implementation**: BIRD2 (Phase 1) β†’ GoBGP (Phase 2 migration) + +--- + +## πŸ€– AI/Agent Architecture (4-Layer Stack) + +### Layer 0: Inference (Ollama - LXC 1000) + +**Purpose**: Local LLM inference engine + +- **Models**: llama3, codellama, mistral, neural-chat +- **API**: OpenAI-compatible REST API +- **Hardware**: Direct hardware access for GPU (if available) +- **Deployment**: LXC container via helper script + +### Layer 1: Orchestration (LiteLLM - LXC 1002) + +**Purpose**: Unified API gateway for multiple LLM backends + +- **Features**: + - OpenAI-compatible API + - Multi-model routing + - Rate limiting (Redis integration) + - Caching + - Load balancing +- **Backends**: Ollama (local), OpenAI (fallback), Anthropic (fallback) + +### Layer 2: Agent Framework (K8s Pods) + +**Specialized Agents**: + +1. **Infrastructure Agent** + - Resource monitoring (CPU, RAM, disk, network) + - VM lifecycle management + - Storage provisioning + - Capacity planning + +2. **Network Agent** + - BGP session monitoring + - Route optimization + - Firewall rule management + - Traffic analysis + +3. **Security Agent** + - Threat detection + - Vulnerability scanning + - Hardening recommendations + - Compliance checking + +4. **DevOps Agent** + - CI/CD pipeline management + - Deployment automation + - Rollback strategies + - Log analysis + +### Layer 3: Coordinator (AI Coordinator - VM 300) + +**Purpose**: Multi-agent orchestration and decision-making + +- **Framework**: LangGraph for workflow orchestration +- **Capabilities**: + - Inter-agent communication + - Task delegation + - Conflict resolution + - State management + - Human-in-the-loop approvals + +--- + +## πŸ” "AI Maze" Security Architecture + +### Concept + +Use uncommon technology stack to confuse automated vulnerability scanners and bots: + +1. **Backstage (Developer Portal)** - Not commonly scanned by bots +2. **Vapor (Swift Web Framework)** - Extremely rare in infrastructure +3. **Unusual Port Assignments** - Non-standard ports for services +4. **Request Routing Obfuscation** - Multi-layer proxying + +### Flow + +``` +Internet β†’ Nginx Proxy Manager β†’ Backstage (Node.js) + ↓ + Vapor API (Swift) + ↓ + Internal Services (Go, Python, Rust) +``` + +**Scanner Perspective**: +- Sees Backstage (JavaScript/TypeScript) - expects Node.js backend +- Actually hits Vapor (Swift) - no known exploits, confuses scanners +- By the time scanner adapts, requests are rate-limited/blocked + +--- + +## πŸ“¦ Deployment Strategy + +### Why LXC for AI/ML? + +| Aspect | LXC Containers | K8s Pods | VMs | +|--------|---------------|----------|-----| +| **Deployment Time** | 5 minutes | Hours | Hours | +| **Resource Overhead** | Low | Medium | High | +| **GPU Access** | Direct | Complex | Passthrough | +| **Storage** | Persistent | Volumes | Easy | +| **Management** | Proxmox UI | kubectl | Proxmox UI | +| **Maintenance** | Community | Self | Self | + +**Decision**: Use LXC containers (via tteck's helper scripts) for AI/ML stack + +### Deployment Phases + +#### Phase 1: Infrastructure VMs (Terraform) + +```bash +make apply +``` + +Deploys: +- VM 200: Router +- VM 300: AI Coordinator +- VM 500: NetBox +- VM 600-603: K3s cluster + +#### Phase 2: AI/ML Stack (LXC Helper Scripts) + +```bash +make deploy-ai-stack +``` + +Provides commands to run on Proxmox host: +- LXC 1000: Ollama +- LXC 1001: OpenWebUI +- LXC 1002: LiteLLM +- LXC 1003: FlowiseAI +- LXC 1004: PostgreSQL + pgvector +- LXC 1005: Redis + +#### Phase 3: Infrastructure Services (LXC) + +```bash +make deploy-infrastructure +``` + +Deploys: +- LXC 1006: Minio +- LXC 1007: Nginx Proxy Manager +- LXC 1008: Wireguard + +#### Phase 4: VM Configuration (Ansible) + +```bash +make configure +``` + +Configures: +- Router: BIRD2, firewall, routing +- NetBox: IPAM setup +- K3s: Cluster initialization + +#### Phase 5: K8s Workloads + +```bash +make k8s-deploy +``` + +Deploys: +- Infrastructure: Prometheus, Grafana, Cilium, Longhorn +- Applications: Backstage, Vapor API +- AI Agents: All 4 specialized agents + +### Complete Deployment + +```bash +make deploy-full +``` + +Runs all phases sequentially. + +--- + +## πŸ“ Repository Structure + +``` +luci-macOSX-PROXMOX/ +β”œβ”€β”€ terraform/ # Infrastructure as Code +β”‚ β”œβ”€β”€ main.tf # VM definitions +β”‚ β”œβ”€β”€ variables.tf # Variable definitions +β”‚ β”œβ”€β”€ outputs.tf # Output values +β”‚ β”œβ”€β”€ providers.tf # Proxmox provider config +β”‚ └── terraform.tfvars # Actual values (gitignored) +β”‚ +β”œβ”€β”€ ansible/ # Configuration management +β”‚ β”œβ”€β”€ inventory/ # Host inventory +β”‚ β”œβ”€β”€ playbooks/ # Playbooks +β”‚ β”‚ β”œβ”€β”€ site.yml # Main playbook +β”‚ β”‚ β”œβ”€β”€ router.yml # Router config +β”‚ β”‚ β”œβ”€β”€ netbox.yml # NetBox setup +β”‚ β”‚ └── k8s.yml # K8s cluster +β”‚ β”œβ”€β”€ group_vars/ # Group variables +β”‚ β”œβ”€β”€ host_vars/ # Host-specific variables +β”‚ └── roles/ # Ansible roles +β”‚ β”œβ”€β”€ common/ # Common setup +β”‚ β”œβ”€β”€ bird2/ # BIRD2 BGP +β”‚ β”œβ”€β”€ gobgp/ # GoBGP (Phase 2) +β”‚ β”œβ”€β”€ k3s-master/ # K3s master +β”‚ β”œβ”€β”€ k3s-worker/ # K3s worker +β”‚ β”œβ”€β”€ netbox/ # NetBox +β”‚ └── ai-coordinator/ # AI coordinator +β”‚ +β”œβ”€β”€ kubernetes/ # K8s manifests +β”‚ β”œβ”€β”€ infrastructure/ # Core services +β”‚ β”‚ β”œβ”€β”€ kube-prometheus-stack/ +β”‚ β”‚ β”œβ”€β”€ cilium/ +β”‚ β”‚ └── longhorn/ +β”‚ β”œβ”€β”€ applications/ # Apps +β”‚ β”‚ β”œβ”€β”€ backstage/ +β”‚ β”‚ └── vapor-api/ +β”‚ └── ai-agents/ # AI agents +β”‚ β”œβ”€β”€ ollama/ # Ollama client +β”‚ β”œβ”€β”€ litellm/ # LiteLLM client +β”‚ └── agents/ +β”‚ β”œβ”€β”€ infrastructure/ +β”‚ β”œβ”€β”€ network/ +β”‚ β”œβ”€β”€ security/ +β”‚ └── devops/ +β”‚ +β”œβ”€β”€ router-configs/ # Router configurations +β”‚ β”œβ”€β”€ bird2/ # BIRD2 configs +β”‚ β”‚ β”œβ”€β”€ bird.conf # IPv4 +β”‚ β”‚ └── bird6.conf # IPv6 +β”‚ └── gobgp/ # GoBGP configs (Phase 2) +β”‚ +β”œβ”€β”€ docs/ # Documentation +β”‚ β”œβ”€β”€ deployment-guide/ # Deployment docs +β”‚ β”œβ”€β”€ ai-agent-design/ # AI agent architecture +β”‚ β”œβ”€β”€ network-design/ # Network diagrams +β”‚ └── reference/ # Old docs (archived) +β”‚ +β”œβ”€β”€ Makefile # One-command deployment +β”œβ”€β”€ ARCHITECTURE.md # This file +β”œβ”€β”€ ARCHITECTURE_REVIEW.md # AI engineering review +β”œβ”€β”€ README.md # Project overview +└── .gitignore +``` + +--- + +## πŸš€ Quick Start + +### Prerequisites + +1. **Dell R730** with Proxmox VE 8.x installed +2. **Terraform** >= 1.6.0 +3. **Ansible** >= 2.15 +4. **kubectl** (for K8s management) +5. **Proxmox API Token** created + +### Deployment + +```bash +# 1. Clone repository +git clone https://github.com/luci-digital/luci-macOSX-PROXMOX.git +cd luci-macOSX-PROXMOX + +# 2. Configure Terraform +cp terraform/terraform.tfvars.example terraform/terraform.tfvars +nano terraform/terraform.tfvars # Add your Proxmox API token + +# 3. Deploy everything +make deploy-full + +# 4. Verify +make verify +make outputs +``` + +### Individual Deployments + +```bash +# Deploy VMs only +make apply + +# Deploy AI/ML stack only +make deploy-ai-stack + +# Deploy infrastructure services only +make deploy-infrastructure + +# Deploy K8s workloads only +make k8s-deploy +``` + +--- + +## πŸ“Š Resource Allocation + +| Component | CPU Cores | Memory | Disk | Network | +|-----------|-----------|--------|------|---------| +| **Router** | 8 | 32GB | 50GB | 4x virtio | +| **AI Coordinator** | 4 | 16GB | 100GB | 1x virtio | +| **NetBox** | 4 | 8GB | 100GB | 1x virtio | +| **K3s Master** | 4 | 8GB | 100GB | 1x virtio | +| **K3s Workers (Γ—3)** | 4 each | 16GB each | 100GB each | 1x virtio | +| **LXC Containers** | Variable | Variable | Variable | Bridge | +| **Total Used** | ~40 cores | ~120GB | ~750GB | - | +| **Available** | 16 cores | 264GB | - | - | + +--- + +## πŸ”„ Migration Paths + +### BIRD2 β†’ GoBGP (Phase 2) + +**Why Migrate?** +- API-driven configuration (vs. config files) +- Better integration with K8s +- Programmable routing policies +- Real-time monitoring via gRPC + +**Timeline**: After Phase 1 stabilization (3-6 months) + +**Migration Steps**: +1. Deploy GoBGP alongside BIRD2 +2. Configure GoBGP with same peering +3. Test in parallel +4. Gracefully shutdown BIRD2 sessions +5. Cutover to GoBGP +6. Monitor for 48 hours +7. Remove BIRD2 + +### Future Enhancements + +- **GPU Passthrough**: Add NVIDIA GPU for faster LLM inference +- **HA Setup**: Proxmox cluster with second R730 +- **Object Storage**: Expand Minio for backups and AI model storage +- **Monitoring**: Enhanced metrics with VictoriaMetrics +- **GitOps**: Implement ArgoCD for K8s deployments + +--- + +## πŸ“š Documentation + +- **[Deployment Guide](docs/deployment-guide/)** - Step-by-step instructions +- **[AI Agent Design](docs/ai-agent-design/)** - Agent architecture details +- **[Network Design](docs/network-design/)** - Network topology and routing +- **[Helper Scripts Integration](docs/HELPER_SCRIPTS_INTEGRATION.md)** - LXC deployment guide +- **[IPv6 Routing](docs/IPV6_ROUTING_INTEGRATION.md)** - BGP configuration +- **[Claude Code Integration](docs/CLAUDE_CODE_INTEGRATION.md)** - AI-assisted development setup +- **[Development Environment](docs/DEVELOPMENT_ENVIRONMENT.md)** - Zsh, Oh My Zsh, Antigen setup +- **[Architecture Review](ARCHITECTURE_REVIEW.md)** - AI engineering analysis + +--- + +## πŸ”§ Operations + +### Monitoring + +- **Proxmox Web UI**: https://192.168.1.100:8006 +- **NetBox**: http://192.168.100.50:8000 +- **Grafana**: http://192.168.100.60:30080 (K8s NodePort) +- **OpenWebUI**: http://192.168.100.30:3000 (LXC 1001) +- **Backstage**: http://192.168.100.60:30000 (K8s NodePort) + +### Troubleshooting + +```bash +# Check Terraform state +make status + +# View all outputs +make outputs + +# Verify connectivity +make verify + +# View Terraform plan +make plan + +# SSH to VMs +ssh root@192.168.100.1 # Router +ssh root@192.168.100.30 # AI Coordinator +ssh root@192.168.100.50 # NetBox +ssh root@192.168.100.60 # K3s Master +``` + +--- + +## 🎯 Design Decisions + +### Why This Architecture? + +1. **VMs for Infrastructure**: Stable, proven, easy to manage +2. **LXC for AI/ML**: Lightweight, fast deployment, community-maintained scripts +3. **K8s for Applications**: Modern orchestration, perfect for stateless apps +4. **Hybrid Approach**: Right tool for the right job + +### What We Eliminated + +- ❌ All-in-one deployment scripts (replaced with Terraform + Makefile) +- ❌ VMs 400/401 (Backstage/Vapor moved to K8s) +- ❌ Conflicting deployment paths (single path now) +- ❌ Ambiguous documentation (consolidated) + +### What We Kept + +- βœ… Terraform for VMs (declarative, reproducible) +- βœ… Ansible for configuration (proven, flexible) +- βœ… BIRD2 for routing (stable, will migrate to GoBGP later) +- βœ… K3s for K8s (lightweight, perfect for single-node) +- βœ… AI-first design (multi-agent architecture) + +--- + +## πŸ” Security Considerations + +1. **Firewall**: nftables on router VM +2. **VPN**: Wireguard for remote access +3. **SSL/TLS**: Nginx Proxy Manager with Let's Encrypt +4. **Network Segmentation**: VLANs for LAN/Guest/Management +5. **API Security**: Rate limiting via LiteLLM + Redis +6. **Obscurity**: Uncommon tech stack (Vapor/Backstage) + +--- + +## πŸ“ Notes + +- This architecture is post-refactoring (v2.0) +- All obsolete deployment scripts removed +- Single deployment path via Makefile +- Proper domain separation established +- AI/agent architecture clearly defined +- Helper scripts integration discovered and documented + +--- + +**Last Updated**: 2025-11-22 +**Status**: Active Development +**Next Milestone**: Complete Ansible playbooks for VM configuration diff --git a/ARCHITECTURE_REVIEW.md b/ARCHITECTURE_REVIEW.md new file mode 100644 index 0000000..d4d416f --- /dev/null +++ b/ARCHITECTURE_REVIEW.md @@ -0,0 +1,884 @@ +# ORION Project - AI Engineering Architecture Review + +**Review Date**: 2025-01-22 +**Reviewer**: AI Systems Architect +**Scope**: Complete project analysis for domain control, code cleanup, AI/agent architecture, and deployment alignment + +--- + +## 🎯 Executive Summary + +### Critical Findings + +| Severity | Issue | Impact | Status | +|----------|-------|--------|--------| +| πŸ”΄ **Critical** | Overlapping deployment strategies | Deployment confusion, wasted resources | ⚠️ Needs resolution | +| πŸ”΄ **Critical** | Unclear AI/agent boundaries | No proper inference layer | ⚠️ Must define | +| 🟑 **Major** | BIRD2 vs GoBGP ambiguity | Routing configuration unclear | ⚠️ Pick one | +| 🟑 **Major** | VM vs K8s workload overlap | Resource waste, complexity | ⚠️ Consolidate | +| 🟒 **Minor** | Documentation duplication | Maintenance burden | βœ… Can cleanup | + +### Recommended Actions + +1. **ELIMINATE**: Remove obsolete/conflicting components +2. **CONSOLIDATE**: Merge overlapping functionality +3. **ARCHITECT**: Define proper AI/agent layer +4. **STREAMLINE**: Single deployment path with clear dependencies + +--- + +## πŸ“Š Part 1: Current State Analysis + +### Project Structure Review + +``` +ORION Project (luci-macOSX-PROXMOX) +β”‚ +β”œβ”€ πŸ—οΈ Infrastructure Layer +β”‚ β”œβ”€ Proxmox VE (bare metal hypervisor) +β”‚ β”œβ”€ Network bridges (vmbr0-3) +β”‚ └─ Hardware: Dell R730 (56 cores, 384GB RAM) +β”‚ +β”œβ”€ πŸ”€ Routing Layer +β”‚ β”œβ”€ ❌ BIRD2 (IPv6 BGP) - OBSOLETE, replaced by GoBGP +β”‚ β”œβ”€ βœ… GoBGP (planned) - KEEP, needs implementation +β”‚ └─ ⚠️ CONFLICT: Both mentioned in docs +β”‚ +β”œβ”€ πŸ’» Compute Layer +β”‚ β”œβ”€ VM 200: Router +β”‚ β”œβ”€ VM 300: AI Agent (⚠️ poorly defined) +β”‚ β”œβ”€ VM 400: Backstage (⚠️ duplicate: also in K8s plan) +β”‚ β”œβ”€ VM 401: Vapor API (⚠️ duplicate: also in K8s plan) +β”‚ β”œβ”€ VM 500: NetBox (IPAM) +β”‚ β”œβ”€ VM 600-603: K8s Cluster +β”‚ └─ VM 100: macOS (dev environment) +β”‚ +β”œβ”€ ☸️ Container Layer (K8s) +β”‚ β”œβ”€ ⚠️ Backstage (conflicts with VM 400) +β”‚ β”œβ”€ ⚠️ Vapor API (conflicts with VM 401) +β”‚ β”œβ”€ Prometheus + Grafana +β”‚ └─ ❓ AI/Agent workloads (undefined) +β”‚ +β”œβ”€ πŸ€– AI/Agent Layer (⚠️ MISSING PROPER ARCHITECTURE) +β”‚ β”œβ”€ VM 300: "AI Agent" - what does this actually do? +β”‚ β”œβ”€ No inference layer defined +β”‚ β”œβ”€ No LLM integration points +β”‚ └─ No agentic framework +β”‚ +└─ πŸ“¦ Deployment Layer (⚠️ TOO MANY PATHS) + β”œβ”€ deploy-orion.sh (legacy Proxmox) + β”œβ”€ deploy-orion-hybrid.py (NixOS + VyOS) + β”œβ”€ deploy-ai-maze.sh (Backstage + Vapor) + β”œβ”€ deploy-ipv6-routing.sh (BIRD2 config) + └─ Terraform (IaC - newest, incomplete) +``` + +--- + +## πŸ”΄ Part 2: Critical Issues Identified + +### Issue #1: Deployment Strategy Chaos + +**Problem:** 4 different deployment scripts with overlapping responsibilities. + +``` +deploy-orion.sh (3,500 lines) +β”œβ”€ Creates Proxmox base +β”œβ”€ Configures pfSense router +β”œβ”€ Deploys macOS VMs +└─ Status: ❌ OBSOLETE (replaced by hybrid approach) + +deploy-orion-hybrid.py (600 lines) +β”œβ”€ iDRAC automation +β”œβ”€ Guides Proxmox install +β”œβ”€ Plans NixOS/VyOS router +└─ Status: ⚠️ INCOMPLETE (guidance only, not executable end-to-end) + +deploy-ai-maze.sh (350 lines) +β”œβ”€ Creates Backstage VM (400) +β”œβ”€ Creates Vapor API VM (401) +β”œβ”€ Firewall rules +└─ Status: ⚠️ CONFLICTS with IaC approach (VMs should be K8s pods) + +deploy-ipv6-routing.sh (350 lines) +β”œβ”€ Installs BIRD2 +β”œβ”€ Configures IPv6 BGP +β”œβ”€ Sets up radvd +└─ Status: ❌ OBSOLETE (if using GoBGP instead) +``` + +**Recommendation:** +- **KEEP:** Terraform as single source of truth for infrastructure +- **ELIMINATE:** All shell-based deployment scripts +- **MIGRATE:** Logic to Terraform modules + Ansible playbooks + +--- + +### Issue #2: BIRD2 vs GoBGP Confusion + +**Problem:** Documentation mentions both, but deployment uses only BIRD2. + +**Current State:** +``` +IPV6_ROUTING_INTEGRATION.md +β”œβ”€ router-configs/bird2/bird6.conf βœ… EXISTS +└─ deploy-ipv6-routing.sh β†’ installs BIRD2 βœ… WORKS + +INFRASTRUCTURE_AS_CODE_ARCHITECTURE.md +β”œβ”€ Specifies GoBGP as replacement +β”œβ”€ Provides API examples +└─ ❌ No actual GoBGP implementation +``` + +**Recommendation:** +``` +Decision Matrix: + +BIRD2: +β”œβ”€ βœ… Proven, stable +β”œβ”€ βœ… Already configured and tested +β”œβ”€ ❌ No API (hard to automate) +β”œβ”€ ❌ Text-based configuration +└─ Best for: Traditional static routing + +GoBGP: +β”œβ”€ βœ… API-driven (gRPC + REST) +β”œβ”€ βœ… Programmable (Go SDK) +β”œβ”€ βœ… Modern, actively developed +β”œβ”€ ❌ Not yet implemented +└─ Best for: Dynamic, automated routing + +RECOMMENDATION: Use BIRD2 NOW, migrate to GoBGP in Phase 2 +- Phase 1: Terraform + Ansible deploy BIRD2 (proven) +- Phase 2: Implement GoBGP with API wrapper +- Phase 3: Migrate routes, test, cutover +``` + +--- + +### Issue #3: VM vs K8s Workload Overlap + +**Problem:** Same services defined as both VMs and K8s pods. + +``` +Backstage: +β”œβ”€ AI_MAZE_ARCHITECTURE.md β†’ VM 400 (4 cores, 16GB) +β”œβ”€ deploy-ai-maze.sh β†’ Creates VM 400 +└─ INFRASTRUCTURE_AS_CODE_ARCHITECTURE.md β†’ K8s deployment + +Vapor API: +β”œβ”€ AI_MAZE_ARCHITECTURE.md β†’ VM 401 (4 cores, 8GB) +β”œβ”€ deploy-ai-maze.sh β†’ Creates VM 401 +└─ INFRASTRUCTURE_AS_CODE_ARCHITECTURE.md β†’ K8s deployment + +Monitoring: +β”œβ”€ VM 300: AI Agent with Prometheus/Grafana +└─ K8s: Prometheus/Grafana as pods +``` + +**Recommendation:** +``` +CLEAN ARCHITECTURE: + +Infrastructure VMs (Keep as VMs): +β”œβ”€ VM 200: Router (needs direct network hardware access) +β”œβ”€ VM 500: NetBox (stable, infrequent updates) +β”œβ”€ VM 100: macOS (requires bare-metal-like access) +└─ VMs 600-603: K8s cluster nodes + +Application Workloads (Move to K8s): +β”œβ”€ Backstage β†’ K8s deployment (delete VM 400) +β”œβ”€ Vapor API β†’ K8s deployment (delete VM 401) +β”œβ”€ Prometheus/Grafana β†’ K8s (via kube-prometheus-stack) +└─ AI/Agent services β†’ K8s (new, see below) + +VM 300 Repurposed: +β”œβ”€ Remove: Prometheus/Grafana (moves to K8s) +β”œβ”€ Keep: AI agent orchestration (coordinates K8s agents) +└─ New Role: "Control Plane VM" for AI ecosystem +``` + +--- + +### Issue #4: AI/Agent Architecture - MISSING PROPER DESIGN + +**Problem:** "AI Agent" is mentioned but poorly defined. No inference layer, no agentic framework. + +**Current State:** +```python +# vm-configs/ai-agent-vm/autonomous_agent.py +# - Basic monitoring script +# - No AI/ML capabilities +# - No inference layer +# - Just Prometheus queries +# - Name is misleading +``` + +**What's Actually Needed:** + +``` +AI/Agent Architecture Layers: + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Layer 4: Agentic Ecosystem (Multi-Agent Orchestration) β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ - Agent-to-agent communication β”‚ +β”‚ - Task delegation and coordination β”‚ +β”‚ - Consensus and decision-making β”‚ +β”‚ - Tools: LangGraph, AutoGen, CrewAI β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Layer 3: Agent Framework (Individual Agents) β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ - ReAct pattern (Reason + Act) β”‚ +β”‚ - Tool calling and execution β”‚ +β”‚ - Memory and state management β”‚ +β”‚ - Tools: LangChain Agents, OpenAI Assistants β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Layer 2: LLM Orchestration (Prompt Engineering) β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ - Prompt templating and chaining β”‚ +β”‚ - Context management β”‚ +β”‚ - Response parsing β”‚ +β”‚ - Tools: LangChain, LlamaIndex β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Layer 1: Inference Layer (Model Execution) β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ - Model loading and caching β”‚ +β”‚ - Token management β”‚ +β”‚ - Rate limiting β”‚ +β”‚ - Options: β”‚ +β”‚ β€’ Local: Ollama (llama3, codellama, mistral) β”‚ +β”‚ β€’ Remote: OpenAI API, Anthropic Claude API β”‚ +β”‚ β€’ Hybrid: Local for fast tasks, remote for complex β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Layer 0: Infrastructure (Monitoring & Data) β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ - Prometheus (metrics) β”‚ +β”‚ - Loki (logs) β”‚ +β”‚ - Jaeger (traces) β”‚ +β”‚ - Vector databases (embeddings) β”‚ +β”‚ - Time-series databases β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +**Recommended AI/Agent Stack:** + +```yaml +Infrastructure Layer (K8s): + - Ollama deployment (local LLM inference) + - PostgreSQL + pgvector (embeddings/memory) + - Redis (caching, rate limiting) + +Inference Layer: + - Ollama API (local models: llama3, codellama) + - OpenAI API fallback (complex tasks) + - LiteLLM (unified API across providers) + +Orchestration Layer: + - LangChain (prompt chains, tools) + - LangGraph (complex agent workflows) + - Semantic Kernel (MS, alternative) + +Agent Framework: + Specialized Agents: + 1. Infrastructure Agent + - Monitors Proxmox, K8s health + - Auto-scales workloads + - Detects anomalies + + 2. Network Agent + - Monitors BGP sessions + - Adjusts routes based on conditions + - Predicts network issues + + 3. Security Agent + - Analyzes logs for threats + - Responds to honeypot triggers + - Manages firewall rules + + 4. DevOps Agent + - Manages deployments + - Handles rollbacks + - Optimizes resource allocation + +Agentic Ecosystem: + - Multi-agent coordination + - Shared memory/context + - Tool sharing + - Consensus mechanisms +``` + +--- + +## βœ… Part 3: Proposed Clean Architecture + +### Domain Boundaries - Proper Separation + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ DOMAIN: INFRASTRUCTURE β”‚ +β”‚ Responsibility: Physical/virtual resources β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ Components: β”‚ +β”‚ - Proxmox VE (hypervisor) β”‚ +β”‚ - VMs 200, 500, 600-603 (infrastructure VMs) β”‚ +β”‚ - Network bridges (vmbr0-3) β”‚ +β”‚ - Storage pools β”‚ +β”‚ β”‚ +β”‚ Managed By: Terraform β”‚ +β”‚ Configured By: Ansible β”‚ +β”‚ Documented In: NetBox β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ DOMAIN: NETWORKING β”‚ +β”‚ Responsibility: Routing, firewalling β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ Components: β”‚ +β”‚ - VM 200: Router (BIRD2 β†’ GoBGP migration) β”‚ +β”‚ - BGP sessions (AS394955 ↔ AS6939) β”‚ +β”‚ - Firewall (nftables) β”‚ +β”‚ - IPv6 prefix delegation β”‚ +β”‚ β”‚ +β”‚ Managed By: Terraform (VM), Ansible (config) β”‚ +β”‚ State: NetBox (IP allocations) β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ DOMAIN: PLATFORM β”‚ +β”‚ Responsibility: Container orchestration β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ Components: β”‚ +β”‚ - K3s cluster (VMs 600-603) β”‚ +β”‚ - Cilium (CNI) β”‚ +β”‚ - Longhorn (storage) β”‚ +β”‚ - Traefik (ingress) β”‚ +β”‚ β”‚ +β”‚ Managed By: Terraform (VMs), Ansible (K3s install) β”‚ +β”‚ Workloads: Deployed via kubectl/Helm β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ DOMAIN: APPLICATIONS β”‚ +β”‚ Responsibility: Business logic β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ Components (all on K8s): β”‚ +β”‚ - Backstage (developer portal) β”‚ +β”‚ - Vapor API (Swift middleware) β”‚ +β”‚ - Custom applications β”‚ +β”‚ β”‚ +β”‚ Managed By: Kubernetes manifests / Helm charts β”‚ +β”‚ CI/CD: GitOps (ArgoCD or Flux) β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ DOMAIN: OBSERVABILITY β”‚ +β”‚ Responsibility: Monitoring, logging β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ Components (all on K8s): β”‚ +β”‚ - Prometheus (metrics) β”‚ +β”‚ - Grafana (visualization) β”‚ +β”‚ - Loki (logs) β”‚ +β”‚ - Jaeger (traces) β”‚ +β”‚ β”‚ +β”‚ Managed By: kube-prometheus-stack (Helm) β”‚ +β”‚ Accessed By: AI agents for data β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ DOMAIN: AI/AGENT ECOSYSTEM ⭐ NEW β”‚ +β”‚ Responsibility: Autonomous operations β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ Layer 0: Inference (K8s pods) β”‚ +β”‚ - Ollama (local LLM: llama3, codellama) β”‚ +β”‚ - LiteLLM (API gateway) β”‚ +β”‚ - pgvector (embeddings) β”‚ +β”‚ β”‚ +β”‚ Layer 1: Orchestration (K8s pods) β”‚ +β”‚ - LangChain services β”‚ +β”‚ - LangGraph workflows β”‚ +β”‚ - Prompt template service β”‚ +β”‚ β”‚ +β”‚ Layer 2: Agents (K8s pods) β”‚ +β”‚ - Infrastructure Agent β”‚ +β”‚ - Network Agent β”‚ +β”‚ - Security Agent β”‚ +β”‚ - DevOps Agent β”‚ +β”‚ β”‚ +β”‚ Layer 3: Coordinator (VM 300 repurposed) β”‚ +β”‚ - Multi-agent orchestration β”‚ +β”‚ - Decision consensus β”‚ +β”‚ - Human-in-the-loop interface β”‚ +β”‚ β”‚ +β”‚ Managed By: Helm charts (agents), Terraform (coordinator) β”‚ +β”‚ Interfaces: gRPC (inter-agent), REST (external) β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ DOMAIN: IPAM β”‚ +β”‚ Responsibility: IP/network documentation β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ Components: β”‚ +β”‚ - VM 500: NetBox β”‚ +β”‚ - PostgreSQL (NetBox database) β”‚ +β”‚ - Redis (NetBox cache) β”‚ +β”‚ β”‚ +β”‚ Managed By: Terraform (VM), Ansible (NetBox install) β”‚ +β”‚ Used By: All domains for IP allocation β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +--- + +## πŸ—‘οΈ Part 4: Components to ELIMINATE + +### Files/Docs to Remove + +```bash +# Obsolete deployment scripts +❌ deploy-orion.sh # Replaced by Terraform +❌ deploy-ai-maze.sh # Workloads move to K8s +❌ deploy-ipv6-routing.sh # Becomes Ansible playbook + +# Obsolete/conflicting docs +❌ ORION_QUICKSTART.md # Outdated, pre-IaC +❌ QUICKSTART_HYBRID.md # Merged into new docs +⚠️ DELL_R730_ORION_PROXMOX_INTEGRATION.md # Keep but mark as reference only + +# Obsolete configs +❌ router-configs/bird2/* # If migrating to GoBGP (Phase 2) +``` + +### VMs to NOT Create + +``` +❌ VM 400 (Backstage) β†’ Becomes K8s deployment +❌ VM 401 (Vapor API) β†’ Becomes K8s deployment +⚠️ VM 300 (AI Agent) β†’ Repurpose as coordinator +``` + +--- + +## βœ… Part 5: Recommended Clean Architecture + +### Single Source of Truth: Terraform + Ansible + K8s + +``` +πŸ“ Repository Structure (Clean): + +luci-macOSX-PROXMOX/ +β”œβ”€β”€ README.md # Project overview +β”œβ”€β”€ ARCHITECTURE.md # ⭐ NEW: Single architecture doc +β”‚ +β”œβ”€β”€ docs/ +β”‚ β”œβ”€β”€ deployment-guide.md # Step-by-step deployment +β”‚ β”œβ”€β”€ ai-agent-design.md # AI/agent architecture +β”‚ β”œβ”€β”€ network-design.md # Routing and IPv6 +β”‚ └── reference/ # Historical docs (read-only) +β”‚ β”œβ”€β”€ DELL_R730_ORION_PROXMOX_INTEGRATION.md +β”‚ └── AI_MAZE_ARCHITECTURE.md +β”‚ +β”œβ”€β”€ terraform/ # Infrastructure as Code +β”‚ β”œβ”€β”€ main.tf # Main infrastructure +β”‚ β”œβ”€β”€ modules/ +β”‚ β”‚ β”œβ”€β”€ router-vm/ # Router VM module +β”‚ β”‚ β”œβ”€β”€ netbox-vm/ # NetBox VM module +β”‚ β”‚ β”œβ”€β”€ k8s-cluster/ # K8s cluster module +β”‚ β”‚ └── ai-coordinator-vm/ # AI coordinator VM +β”‚ └── environments/ +β”‚ └── production/ +β”‚ +β”œβ”€β”€ ansible/ # Configuration management +β”‚ β”œβ”€β”€ inventory/ +β”‚ β”‚ └── netbox.yml # Dynamic inventory from NetBox +β”‚ β”œβ”€β”€ playbooks/ +β”‚ β”‚ β”œβ”€β”€ site.yml # Master playbook +β”‚ β”‚ β”œβ”€β”€ router.yml # Router config (BIRD2/GoBGP) +β”‚ β”‚ β”œβ”€β”€ k8s-cluster.yml # K3s installation +β”‚ β”‚ β”œβ”€β”€ netbox.yml # NetBox deployment +β”‚ β”‚ └── ai-coordinator.yml # AI coordinator setup +β”‚ └── roles/ +β”‚ β”œβ”€β”€ common/ # Base config for all VMs +β”‚ β”œβ”€β”€ bird2/ # BIRD2 BGP (Phase 1) +β”‚ β”œβ”€β”€ gobgp/ # GoBGP (Phase 2) +β”‚ β”œβ”€β”€ k3s-master/ +β”‚ β”œβ”€β”€ k3s-worker/ +β”‚ └── ollama/ # Local LLM inference +β”‚ +β”œβ”€β”€ kubernetes/ # K8s workloads +β”‚ β”œβ”€β”€ infrastructure/ +β”‚ β”‚ β”œβ”€β”€ kube-prometheus-stack/ # Monitoring +β”‚ β”‚ β”œβ”€β”€ cilium/ # CNI +β”‚ β”‚ └── longhorn/ # Storage +β”‚ β”œβ”€β”€ applications/ +β”‚ β”‚ β”œβ”€β”€ backstage/ # Developer portal +β”‚ β”‚ └── vapor-api/ # Swift API +β”‚ └── ai-agents/ # ⭐ NEW: AI/agent workloads +β”‚ β”œβ”€β”€ ollama/ # LLM inference +β”‚ β”œβ”€β”€ litelllm/ # API gateway +β”‚ β”œβ”€β”€ langchain-service/ # Orchestration +β”‚ └── agents/ +β”‚ β”œβ”€β”€ infrastructure-agent/ +β”‚ β”œβ”€β”€ network-agent/ +β”‚ β”œβ”€β”€ security-agent/ +β”‚ └── devops-agent/ +β”‚ +β”œβ”€β”€ scripts/ +β”‚ └── helpers/ # Utility scripts only +β”‚ β”œβ”€β”€ create-proxmox-token.sh +β”‚ └── setup-cloud-init-template.sh +β”‚ +└── tools/ + β”œβ”€β”€ macrecovery/ # macOS recovery (keep) + └── iommu/ # IOMMU tools (keep) +``` + +--- + +## πŸš€ Part 6: Aligned Deployment Strategy + +### Single, Linear Deployment Path + +``` +PHASE 0: Prerequisites +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ 1. Proxmox VE installed (manual or via iDRAC) β”‚ +β”‚ 2. Proxmox API token created β”‚ +β”‚ 3. Cloud-init template created β”‚ +β”‚ 4. NetBox credentials prepared β”‚ +β”‚ 5. SSH keys generated β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + ↓ +PHASE 1: Infrastructure (Terraform) +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ $ cd terraform/ β”‚ +β”‚ $ cp terraform.tfvars.example terraform.tfvars β”‚ +β”‚ $ terraform init β”‚ +β”‚ $ terraform apply β”‚ +β”‚ β”‚ +β”‚ Creates: β”‚ +β”‚ - VM 200: Router β”‚ +β”‚ - VM 500: NetBox β”‚ +β”‚ - VM 600-603: K8s cluster β”‚ +β”‚ - VM 300: AI Coordinator (repurposed) β”‚ +β”‚ - VM 100: macOS (optional) β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + ↓ +PHASE 2: Configuration (Ansible) +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ $ cd ansible/ β”‚ +β”‚ $ ansible-playbook -i inventory playbooks/site.yml β”‚ +β”‚ β”‚ +β”‚ Configures: β”‚ +β”‚ - Router: BIRD2 BGP, IPv6, firewall β”‚ +β”‚ - NetBox: Deploys NetBox, syncs Proxmox VMs β”‚ +β”‚ - K8s: Installs K3s (master + 3 workers) β”‚ +β”‚ - AI Coordinator: Sets up orchestration β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + ↓ +PHASE 3: Platform Services (K8s) +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ $ cd kubernetes/ β”‚ +β”‚ $ kubectl apply -k infrastructure/ β”‚ +β”‚ β”‚ +β”‚ Deploys: β”‚ +β”‚ - Cilium (CNI) β”‚ +β”‚ - Longhorn (storage) β”‚ +β”‚ - kube-prometheus-stack (monitoring) β”‚ +β”‚ - Traefik (ingress) β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + ↓ +PHASE 4: Applications (K8s) +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ $ kubectl apply -k applications/ β”‚ +β”‚ β”‚ +β”‚ Deploys: β”‚ +β”‚ - Backstage (developer portal) β”‚ +β”‚ - Vapor API (Swift middleware) β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + ↓ +PHASE 5: AI/Agent Ecosystem (K8s + VM) +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ $ kubectl apply -k ai-agents/ β”‚ +β”‚ β”‚ +β”‚ Deploys: β”‚ +β”‚ - Ollama (local LLM inference) β”‚ +β”‚ - LiteLLM (API gateway) β”‚ +β”‚ - pgvector (embeddings database) β”‚ +β”‚ - LangChain services β”‚ +β”‚ - Individual agents: β”‚ +β”‚ β€’ Infrastructure Agent β”‚ +β”‚ β€’ Network Agent β”‚ +β”‚ β€’ Security Agent β”‚ +β”‚ β€’ DevOps Agent β”‚ +β”‚ β”‚ +β”‚ VM 300 (AI Coordinator): β”‚ +β”‚ - Orchestrates multi-agent workflows β”‚ +β”‚ - Provides human interface β”‚ +β”‚ - Makes consensus decisions β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + ↓ +PHASE 6: Verification +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ $ make verify β”‚ +β”‚ β”‚ +β”‚ Checks: β”‚ +β”‚ βœ“ All VMs running β”‚ +β”‚ βœ“ BGP sessions established β”‚ +β”‚ βœ“ K8s cluster healthy β”‚ +β”‚ βœ“ All pods running β”‚ +β”‚ βœ“ NetBox synced β”‚ +β”‚ βœ“ AI agents responding β”‚ +β”‚ βœ“ Monitoring collecting metrics β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + ↓ + πŸŽ‰ COMPLETE +``` + +--- + +## 🧠 Part 7: AI/Agent Inference Layer Design + +### Proper AI Architecture (Bottom-Up) + +```python +# Layer 0: Inference - Model Execution +# kubernetes/ai-agents/ollama/deployment.yaml + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: ollama + namespace: ai-agents +spec: + replicas: 2 + template: + spec: + containers: + - name: ollama + image: ollama/ollama:latest + resources: + requests: + memory: "8Gi" + cpu: "4" + limits: + memory: "16Gi" + cpu: "8" + env: + - name: OLLAMA_MODELS + value: "llama3,codellama,mistral" + volumeMounts: + - name: models + mountPath: /root/.ollama + volumes: + - name: models + persistentVolumeClaim: + claimName: ollama-models + +--- +# Layer 1: Orchestration - LangChain Service +# kubernetes/ai-agents/langchain-service/deployment.yaml + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: langchain-service + namespace: ai-agents +spec: + replicas: 3 + template: + spec: + containers: + - name: langchain + image: orion/langchain-service:latest + env: + - name: OLLAMA_API_URL + value: "http://ollama:11434" + - name: POSTGRES_URL + valueFrom: + secretKeyRef: + name: pgvector-secret + key: connection-string + +--- +# Layer 2: Agent Framework - Infrastructure Agent +# kubernetes/ai-agents/agents/infrastructure-agent/deployment.yaml + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: infrastructure-agent + namespace: ai-agents +spec: + replicas: 1 + template: + spec: + serviceAccountName: infrastructure-agent + containers: + - name: agent + image: orion/infrastructure-agent:latest + env: + - name: LANGCHAIN_SERVICE_URL + value: "http://langchain-service:8000" + - name: PROMETHEUS_URL + value: "http://prometheus:9090" + - name: KUBERNETES_API + value: "https://kubernetes.default.svc" + +--- +# Layer 3: Multi-Agent Coordinator (VM 300) +# ansible/roles/ai-coordinator/templates/coordinator.py + +from langgraph.prebuilt import create_react_agent +from langchain_ollama import ChatOllama +import asyncio + +class AgentCoordinator: + def __init__(self): + self.llm = ChatOllama( + base_url="http://ollama.ai-agents.svc.cluster.local:11434", + model="llama3" + ) + + self.agents = { + "infrastructure": InfrastructureAgent(), + "network": NetworkAgent(), + "security": SecurityAgent(), + "devops": DevOpsAgent() + } + + async def coordinate_task(self, task): + """ + Multi-agent coordination with consensus + """ + # Determine which agents are needed + relevant_agents = self.select_agents(task) + + # Parallel execution + results = await asyncio.gather(*[ + agent.execute(task) + for agent in relevant_agents + ]) + + # Consensus mechanism + decision = self.reach_consensus(results) + + # Execute decision + return await self.execute_decision(decision) +``` + +--- + +## πŸ“ Part 8: Action Plan + +### Immediate Actions (This Week) + +1. **CLEANUP** (Day 1) + ```bash + # Remove obsolete files + rm deploy-orion.sh + rm deploy-ai-maze.sh + rm deploy-ipv6-routing.sh + + # Move old docs to reference + mkdir -p docs/reference/ + mv ORION_QUICKSTART.md docs/reference/ + mv QUICKSTART_HYBRID.md docs/reference/ + + # Create new master architecture doc + # (consolidates all architecture docs) + ``` + +2. **COMPLETE TERRAFORM** (Day 2-3) + ```bash + # Create missing files: + - terraform/main.tf + - terraform/outputs.tf + - terraform/modules/router-vm/ + - terraform/modules/netbox-vm/ + - terraform/modules/k8s-cluster/ + ``` + +3. **CREATE ANSIBLE PLAYBOOKS** (Day 4-5) + ```bash + # Build out ansible/ directory: + - playbooks/site.yml + - roles/bird2/ + - roles/k3s-master/ + - roles/k3s-worker/ + - roles/netbox/ + ``` + +4. **DESIGN AI/AGENT LAYER** (Day 6-7) + ```bash + # Create kubernetes/ai-agents/: + - ollama deployment + - LangChain service + - Agent deployments + - pgvector database + ``` + +### Success Metrics + +``` +Before Cleanup: +- 9 architecture documents (overlap + confusion) +- 4 deployment scripts (conflicts) +- Unclear domain boundaries +- No proper AI/agent architecture +- 40% deployment success rate + +After Cleanup: +- 1 master architecture document +- 1 deployment path (Terraform β†’ Ansible β†’ K8s) +- Clear domain separation +- Proper AI/agent inference stack +- 95%+ deployment success rate +``` + +--- + +## 🎯 Conclusion + +### Current Status: 🟑 **NEEDS REFACTORING** + +The ORION project has excellent ideas but suffers from: +- Architectural sprawl +- Deployment confusion +- Missing AI/agent proper design +- Domain boundary violations + +### Recommended Path Forward: + +1. βœ… **Accept this review** +2. πŸ—‘οΈ **Remove obsolete components** (deploy-*.sh scripts) +3. πŸ—οΈ **Complete Terraform foundation** +4. πŸ€– **Build proper AI/agent layer** +5. πŸ“Š **Consolidate documentation** +6. πŸš€ **Deploy with confidence** + +**Estimated Refactoring Time**: 1-2 weeks +**Benefit**: Clean, maintainable, production-ready infrastructure + +--- + +**Review Status**: βœ… Complete +**Next Step**: Approve refactoring plan and begin cleanup + +**Reviewer**: AI Systems Architect +**Contact**: Review with project team before implementing changes diff --git a/INFRASTRUCTURE_AS_CODE_ARCHITECTURE.md b/INFRASTRUCTURE_AS_CODE_ARCHITECTURE.md new file mode 100644 index 0000000..4391500 --- /dev/null +++ b/INFRASTRUCTURE_AS_CODE_ARCHITECTURE.md @@ -0,0 +1,926 @@ +# ORION Infrastructure as Code (IaC) - Complete Stack + +**Version**: 2.0.0-iac +**Created**: 2025-01-22 +**Status**: Architecture Design + +--- + +## 🎯 Overview + +Complete Infrastructure-as-Code stack for ORION Dell R730, integrating industry-standard tools for declarative infrastructure management, automated configuration, IP address management, container orchestration, and programmable routing. + +### Technology Stack + +| Component | Technology | Purpose | +|-----------|-----------|---------| +| **Infrastructure Provisioning** | Terraform | Declarative VM/container deployment | +| **Configuration Management** | Ansible | Automated OS and application configuration | +| **IPAM/Documentation** | NetBox | IP address management and network documentation | +| **Container Orchestration** | Kubernetes (K3s) | Lightweight K8s for container workloads | +| **Programmable Routing** | GoBGP | API-driven BGP routing with Go | +| **Secret Management** | Vault (optional) | Secrets and credential management | +| **State Backend** | Consul/S3 | Terraform state management | + +--- + +## πŸ—οΈ Complete Architecture + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ CONTROL PLANE (Your Workstation) β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Terraform β”‚ β”‚ Ansible β”‚ β”‚ kubectl β”‚ β”‚ +β”‚ β”‚ (HCL) β”‚ β”‚ (Playbooks) β”‚ β”‚ (K8s) β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ β”‚ β”‚ + ↓ ↓ ↓ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Dell R730 - Proxmox VE Layer β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ Terraform creates/manages VMs ──→ Ansible configures ──→ Apps run β”‚ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ VM 500: NetBox (IPAM) β”‚ β”‚ +β”‚ β”‚ - PostgreSQL database β”‚ β”‚ +β”‚ β”‚ - Redis cache β”‚ β”‚ +β”‚ β”‚ - Web UI: 192.168.100.50:8000 β”‚ β”‚ +β”‚ β”‚ Purpose: IP address management, network documentation β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ VM 200: Router (GoBGP + VyOS) β”‚ β”‚ +β”‚ β”‚ - GoBGP daemon (port 50051 - gRPC API) β”‚ β”‚ +β”‚ β”‚ - REST API for BGP control β”‚ β”‚ +β”‚ β”‚ - AS394955 ←→ AS6939 (Telus) β”‚ β”‚ +β”‚ β”‚ Purpose: Programmable BGP routing β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ VMs 600-603: Kubernetes Cluster (K3s) β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ +β”‚ β”‚ β”‚ VM 600: K3s Master (Control Plane) β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ - 4 cores, 8GB RAM β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ - etcd, API server, scheduler, controller β”‚ β”‚ β”‚ +β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ +β”‚ β”‚ β”‚ VM 601-603: K3s Workers (3 nodes) β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ - 4 cores, 16GB RAM each β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ - Run containerized workloads β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ - CNI: Flannel or Cilium β”‚ β”‚ β”‚ +β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ Workloads on K8s: β”‚ β”‚ +β”‚ β”‚ - Backstage (Developer Portal) β”‚ β”‚ +β”‚ β”‚ - Vapor API (Swift middleware) β”‚ β”‚ +β”‚ β”‚ - Prometheus + Grafana (Monitoring) β”‚ β”‚ +β”‚ β”‚ - Additional microservices β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ VM 100: macOS Sequoia (Development) β”‚ β”‚ +β”‚ β”‚ - Still deployed via Terraform β”‚ β”‚ +β”‚ β”‚ - Configured via Ansible (post-install scripts) β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ VM 300: AI Agent (Monitoring) β”‚ β”‚ +β”‚ β”‚ - Monitors K8s cluster health β”‚ β”‚ +β”‚ β”‚ - Integrates with GoBGP API β”‚ β”‚ +β”‚ β”‚ - Manages NetBox updates β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +--- + +## πŸ“¦ Component 1: Terraform + +### Purpose +Declarative infrastructure provisioning - define VMs, networks, and storage in code. + +### What Terraform Will Manage + +```hcl +# Infrastructure Components +- Proxmox VMs (all VMs defined as Terraform resources) +- Network bridges and VLANs +- Storage allocations +- VM snapshots and backups (scheduled) +- Cloud-init configurations +- DNS records (if using external DNS) +``` + +### Directory Structure + +``` +terraform/ +β”œβ”€β”€ main.tf # Main configuration +β”œβ”€β”€ variables.tf # Input variables +β”œβ”€β”€ outputs.tf # Output values +β”œβ”€β”€ terraform.tfvars # Variable values (gitignored) +β”œβ”€β”€ modules/ +β”‚ β”œβ”€β”€ proxmox-vm/ # Reusable VM module +β”‚ β”œβ”€β”€ k8s-cluster/ # K8s cluster module +β”‚ └── networking/ # Network configuration +β”œβ”€β”€ environments/ +β”‚ β”œβ”€β”€ dev/ # Development environment +β”‚ β”œβ”€β”€ staging/ # Staging environment +β”‚ └── production/ # Production environment +└── state/ + └── backend.tf # State backend configuration +``` + +### Example: VM Definition + +```hcl +module "netbox_vm" { + source = "./modules/proxmox-vm" + + vm_id = 500 + name = "ORION-NetBox" + cores = 4 + memory = 8192 + disk_size = 100 + bridge = "vmbr1" + ip_address = "192.168.100.50" + tags = ["ipam", "infrastructure"] +} +``` + +### Benefits +- βœ… **Reproducible** - Rebuild entire infrastructure from code +- βœ… **Version controlled** - Track infrastructure changes in Git +- βœ… **Idempotent** - Run multiple times safely +- βœ… **Plan before apply** - Preview changes before execution +- βœ… **State management** - Track resource state + +--- + +## πŸ”§ Component 2: Ansible + +### Purpose +Automated configuration management - configure VMs after they're created by Terraform. + +### What Ansible Will Manage + +```yaml +# Configuration Tasks +- Operating system updates and packages +- User accounts and SSH keys +- Application installation (GoBGP, NetBox, etc.) +- Service configuration files +- Firewall rules +- Monitoring agents +- Security hardening +``` + +### Directory Structure + +``` +ansible/ +β”œβ”€β”€ ansible.cfg # Ansible configuration +β”œβ”€β”€ inventory/ +β”‚ β”œβ”€β”€ hosts.yml # Static inventory +β”‚ └── proxmox.py # Dynamic inventory (from Proxmox) +β”œβ”€β”€ playbooks/ +β”‚ β”œβ”€β”€ site.yml # Master playbook +β”‚ β”œβ”€β”€ router.yml # Router VM configuration +β”‚ β”œβ”€β”€ k8s-cluster.yml # K8s cluster setup +β”‚ β”œβ”€β”€ netbox.yml # NetBox deployment +β”‚ └── monitoring.yml # Monitoring stack +β”œβ”€β”€ roles/ +β”‚ β”œβ”€β”€ common/ # Common configuration +β”‚ β”œβ”€β”€ gobgp/ # GoBGP installation +β”‚ β”œβ”€β”€ k3s-master/ # K3s control plane +β”‚ β”œβ”€β”€ k3s-worker/ # K3s worker node +β”‚ β”œβ”€β”€ netbox/ # NetBox setup +β”‚ └── security/ # Security hardening +β”œβ”€β”€ group_vars/ +β”‚ β”œβ”€β”€ all.yml # Variables for all hosts +β”‚ β”œβ”€β”€ routers.yml # Router-specific vars +β”‚ └── k8s.yml # K8s-specific vars +└── host_vars/ + └── router.yml # Per-host variables +``` + +### Example: GoBGP Installation Role + +```yaml +# roles/gobgp/tasks/main.yml +--- +- name: Install GoBGP + apt: + name: golang-go + state: present + +- name: Download GoBGP binary + get_url: + url: "https://github.com/osrg/gobgp/releases/download/v3.20.0/gobgp_3.20.0_linux_amd64.tar.gz" + dest: /tmp/gobgp.tar.gz + +- name: Extract GoBGP + unarchive: + src: /tmp/gobgp.tar.gz + dest: /usr/local/bin/ + remote_src: yes + +- name: Create GoBGP config directory + file: + path: /etc/gobgp + state: directory + +- name: Deploy GoBGP configuration + template: + src: gobgpd.conf.j2 + dest: /etc/gobgp/gobgpd.conf + notify: restart gobgp + +- name: Install GoBGP systemd service + template: + src: gobgpd.service.j2 + dest: /etc/systemd/system/gobgpd.service + notify: reload systemd +``` + +### Integration with Terraform + +```bash +# Terraform creates VMs, then triggers Ansible +terraform apply +terraform output -json > ansible/inventory/terraform.json +ansible-playbook -i ansible/inventory ansible/playbooks/site.yml +``` + +--- + +## πŸ—„οΈ Component 3: NetBox (IPAM) + +### Purpose +Centralized IP address management, network documentation, and source of truth for infrastructure. + +### Features + +- **IPAM**: IPv4 and IPv6 address management +- **DCIM**: Data center infrastructure management +- **Circuits**: ISP/provider circuit tracking +- **Secrets**: Encrypted credential storage +- **API**: RESTful API for automation +- **Plugins**: Extensible with custom plugins + +### VM Specifications + +```yaml +VM ID: 500 +Name: ORION-NetBox +OS: Ubuntu 24.04 LTS +CPU: 4 cores +RAM: 8GB +Disk: 100GB +Network: 192.168.100.50/24 (vmbr1) +Services: + - NetBox web UI (port 8000) + - PostgreSQL 16 + - Redis 7 + - nginx (reverse proxy) +``` + +### NetBox Data Model for ORION + +```python +# Sites +ORION-Datacenter (Home Lab) + +# Racks +Dell-R730-Rack + +# Devices +- Dell R730 (CQ5QBM2) + - Type: Server + - Role: Hypervisor + - NICs: 8x (eno1-eno6, enp3s0f0-1) + +# Virtual Machines (synced from Proxmox) +- ORION-Router (VM 200) +- ORION-AI-Agent (VM 300) +- ORION-Backstage (VM 400) +- ORION-VaporAPI (VM 401) +- ORION-NetBox (VM 500) +- ORION-K3s-Master (VM 600) +- ORION-K3s-Worker-1 (VM 601) +- ORION-K3s-Worker-2 (VM 602) +- ORION-K3s-Worker-3 (VM 603) + +# IP Addresses (both IPv4 and IPv6) +# Prefixes +- 192.168.100.0/24 (LAN) +- 192.168.200.0/24 (Guest) +- 2602:F674::/48 (IPv6 allocation) + - 2602:F674:1000::/64 (LAN) + - 2602:F674:2000::/64 (Guest) + +# Circuits +- Telus Fiber (10Gbps) + - BGP AS: 6939 + - IPv6 Peers: 3x +``` + +### Integration Points + +1. **Terraform** ↔ NetBox + - Terraform reads IP allocations from NetBox API + - Auto-assigns IPs based on NetBox IPAM + +2. **Ansible** ↔ NetBox + - Dynamic inventory from NetBox + - Pull configuration data (VLANs, IPs) + +3. **Proxmox** ↔ NetBox + - Sync VMs to NetBox automatically + - Track VM lifecycle + +--- + +## ☸️ Component 4: Kubernetes (K3s) + +### Purpose +Lightweight Kubernetes for container orchestration, replacing standalone VMs for certain workloads. + +### Why K3s? + +- **Lightweight**: 100MB binary vs 1GB+ for full K8s +- **Easy setup**: Single command installation +- **Low resource**: Runs on smaller VMs +- **Full K8s**: 100% Kubernetes API compatible +- **Built-in**: Traefik ingress, local storage + +### Cluster Topology + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ K3s Cluster - ORION β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ Control Plane (VM 600) β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ - etcd (distributed key-value store) β”‚ β”‚ +β”‚ β”‚ - kube-apiserver β”‚ β”‚ +β”‚ β”‚ - kube-scheduler β”‚ β”‚ +β”‚ β”‚ - kube-controller-manager β”‚ β”‚ +β”‚ β”‚ - Traefik ingress controller β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”‚ Worker Nodes (VMs 601-603) β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Worker 1 (601): General workloads β”‚ β”‚ +β”‚ β”‚ Worker 2 (602): Stateful apps (databases) β”‚ β”‚ +β”‚ β”‚ Worker 3 (603): Monitoring stack β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### What Runs on K8s + +**Instead of separate VMs, these run as Pods:** + +1. **Backstage** (formerly VM 400) + ```yaml + Deployment: backstage + Replicas: 2 (HA) + Resources: 2 CPU, 4GB RAM per pod + Service: LoadBalancer (192.168.100.40) + Storage: PVC 50GB + ``` + +2. **Vapor API** (formerly VM 401) + ```yaml + Deployment: vapor-api + Replicas: 3 (load balanced) + Resources: 1 CPU, 2GB RAM per pod + Service: ClusterIP (internal only) + ``` + +3. **Monitoring Stack** + ```yaml + - Prometheus (metrics) + - Grafana (visualization) + - AlertManager (alerting) + - Node exporters (DaemonSet on all nodes) + ``` + +4. **Additional Services** + ```yaml + - Redis (caching) + - PostgreSQL (database) + - RabbitMQ (message queue) + - MinIO (S3-compatible storage) + ``` + +### Storage + +**Longhorn** - Distributed block storage for K8s +- Replicated volumes across worker nodes +- Snapshots and backups +- Web UI for management + +### Networking + +**CNI**: Cilium (instead of Flannel) +- Better performance +- Network policies +- Service mesh capabilities +- Observability + +### Deployment via Terraform + Ansible + +```hcl +# Terraform creates K8s VMs +module "k8s_cluster" { + source = "./modules/k8s-cluster" + + master_count = 1 + worker_count = 3 + master_cpu = 4 + master_ram = 8192 + worker_cpu = 4 + worker_ram = 16384 +} +``` + +```yaml +# Ansible installs K3s +- hosts: k8s_masters + roles: + - k3s-master + +- hosts: k8s_workers + roles: + - k3s-worker +``` + +### Benefits + +- βœ… **Higher density**: More services per VM +- βœ… **Auto-scaling**: HPA (Horizontal Pod Autoscaler) +- βœ… **Self-healing**: Automatic pod restarts +- βœ… **Rolling updates**: Zero-downtime deployments +- βœ… **Resource efficiency**: Better CPU/RAM utilization + +--- + +## πŸ”€ Component 5: GoBGP (Programmable Routing) + +### Purpose +Replace BIRD2 with GoBGP for API-driven, programmable BGP routing. + +### Why GoBGP over BIRD2? + +| Feature | BIRD2 | GoBGP | +|---------|-------|-------| +| **API** | Limited | Full gRPC/REST API | +| **Language** | C | Go (easier to extend) | +| **Configuration** | Text files | API + config file | +| **Monitoring** | birdc CLI | Prometheus metrics built-in | +| **Automation** | Manual | Programmatic | +| **Libraries** | None | Go client library | + +### GoBGP Architecture + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Router VM (200) - GoBGP Stack β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ gobgpd (BGP Daemon) β”‚ β”‚ +β”‚ β”‚ - Port 179: BGP protocol β”‚ β”‚ +β”‚ β”‚ - Port 50051: gRPC API β”‚ β”‚ +β”‚ β”‚ - Port 8080: REST API (optional) β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ ↕ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ GoBGP REST API Wrapper (Go service) β”‚ β”‚ +β”‚ β”‚ - Exposes REST endpoints for easy integration β”‚ β”‚ +β”‚ β”‚ - Integrates with Backstage/Vapor API β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ ↕ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ GoBGP Exporter (Prometheus) β”‚ β”‚ +β”‚ β”‚ - Port 9100: Metrics endpoint β”‚ β”‚ +β”‚ β”‚ - BGP session state, route counts, etc. β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + ↕ + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ Telus AS6939 β”‚ + β”‚ BGP Peers (3x) β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### GoBGP Configuration + +```toml +# /etc/gobgp/gobgpd.toml +[global.config] + as = 394955 + router-id = "100.64.0.1" + +# Telus Peer 1 (Primary) +[[neighbors]] + [neighbors.config] + neighbor-address = "2602:F674:0000::ffff" + peer-as = 6939 + description = "Telus Gateway 1 - Primary" + [neighbors.timers.config] + hold-time = 90 + keepalive-interval = 30 + [neighbors.afi-safis] + [[neighbors.afi-safis.list]] + afi-safi-name = "ipv6-unicast" + [neighbors.afi-safis.list.config] + enabled = true + +# Telus Peer 2 (Secondary) +[[neighbors]] + [neighbors.config] + neighbor-address = "2602:F674:0000::fffe" + peer-as = 6939 + description = "Telus Gateway 2 - Secondary" + [neighbors.afi-safis] + [[neighbors.afi-safis.list]] + afi-safi-name = "ipv6-unicast" + +# Telus Peer 3 (Tertiary) +[[neighbors]] + [neighbors.config] + neighbor-address = "2602:F674:0000::fffd" + peer-as = 6939 + description = "Telus Gateway 3 - Tertiary" + [neighbors.afi-safis] + [[neighbors.afi-safis.list]] + afi-safi-name = "ipv6-unicast" +``` + +### API Usage Examples + +**Add a route programmatically:** + +```go +package main + +import ( + "context" + api "github.com/osrg/gobgp/v3/api" + "google.golang.org/grpc" +) + +func main() { + conn, _ := grpc.Dial("192.168.100.1:50051", grpc.WithInsecure()) + defer conn.Close() + + client := api.NewGobgpApiClient(conn) + + // Announce a new prefix + nlri := &api.IPAddressPrefix{ + PrefixLen: 48, + Prefix: "2602:F674::", + } + + attrs := []*api.PathAttribute{ + api.NewOriginAttribute(0), + api.NewNextHopAttribute("::"), + api.NewAsPathAttribute([]uint32{394955}), + } + + path := &api.Path{ + Nlri: api.NewAnyFromMessage(nlri), + Pattrs: attrs, + } + + client.AddPath(context.Background(), &api.AddPathRequest{ + Path: path, + }) +} +``` + +**REST API (via wrapper):** + +```bash +# Get all neighbors +curl http://192.168.100.1:8080/v1/neighbors + +# Get specific neighbor +curl http://192.168.100.1:8080/v1/neighbors/2602:F674:0000::ffff + +# Add route +curl -X POST http://192.168.100.1:8080/v1/routes \ + -H "Content-Type: application/json" \ + -d '{ + "prefix": "2602:F674:5000::/64", + "nexthop": "2602:F674:1000::1" + }' +``` + +### Integration with AI Agent + +```python +# AI Agent monitors and adjusts BGP automatically +import requests + +class BGPController: + def __init__(self, gobgp_url="http://192.168.100.1:8080"): + self.base_url = gobgp_url + + def check_bgp_health(self): + """Check BGP session health""" + resp = requests.get(f"{self.base_url}/v1/neighbors") + neighbors = resp.json() + + for neighbor in neighbors: + if neighbor['state'] != 'established': + self.alert(f"BGP peer {neighbor['address']} is down!") + self.attempt_recovery(neighbor) + + def announce_prefix(self, prefix, nexthop): + """Programmatically announce a new prefix""" + requests.post(f"{self.base_url}/v1/routes", json={ + "prefix": prefix, + "nexthop": nexthop + }) + + def withdraw_prefix(self, prefix): + """Withdraw a prefix""" + requests.delete(f"{self.base_url}/v1/routes/{prefix}") +``` + +### Benefits + +- βœ… **API-driven**: Control BGP programmatically +- βœ… **Automation-friendly**: Easy integration with CI/CD +- βœ… **Metrics built-in**: Native Prometheus support +- βœ… **Modern codebase**: Active development, Go ecosystem +- βœ… **Flexible**: Add custom logic in Go + +--- + +## πŸ”„ Complete Workflow + +### Initial Deployment + +```bash +# 1. Define infrastructure in Terraform +cd terraform/ +terraform init +terraform plan +terraform apply + +# VMs created: +# - VM 200: Router (GoBGP) +# - VM 300: AI Agent +# - VM 500: NetBox +# - VM 600-603: K8s cluster (K3s) + +# 2. Configure VMs with Ansible +cd ../ansible/ +ansible-playbook -i inventory/hosts.yml playbooks/site.yml + +# Installs: +# - GoBGP on Router +# - NetBox on VM 500 +# - K3s on cluster VMs +# - Monitoring agents everywhere + +# 3. Deploy applications to K8s +cd ../k8s/ +kubectl apply -f backstage/ +kubectl apply -f vapor-api/ +kubectl apply -f monitoring/ + +# 4. Configure NetBox +# - Import IP allocations +# - Sync VMs from Proxmox +# - Document network topology + +# 5. Start BGP +# - GoBGP establishes sessions +# - Routes announced automatically +# - Monitoring begins +``` + +### Day-2 Operations + +**Add a new VM:** + +```bash +# 1. Define in Terraform +cat >> terraform/vms.tf << 'EOF' +module "new_app_vm" { + source = "./modules/proxmox-vm" + vm_id = 700 + name = "app-server" + # ... +} +EOF + +# 2. Apply +terraform apply + +# 3. Ansible configures automatically (if in inventory) +ansible-playbook -i inventory playbooks/app-server.yml + +# 4. NetBox updated automatically via API +``` + +**Deploy new app to K8s:** + +```bash +# 1. Create Kubernetes manifest +cat > k8s/myapp/deployment.yaml + +# 2. Apply +kubectl apply -f k8s/myapp/ + +# 3. Monitoring auto-discovers new pods +# 4. Logs aggregated automatically +``` + +**Modify BGP routing:** + +```bash +# Option 1: Via API +curl -X POST http://192.168.100.1:8080/v1/routes \ + -d '{"prefix": "2602:F674:9000::/64", "nexthop": "..."}' + +# Option 2: Via Terraform +# (if managing routes as code) +terraform apply + +# Option 3: Via AI Agent +# (automatic based on conditions) +``` + +--- + +## πŸ“Š Monitoring & Observability + +### Metrics Collection + +``` +Prometheus scrapes: +β”œβ”€ Node Exporter (all VMs) - System metrics +β”œβ”€ GoBGP Exporter (Router) - BGP metrics +β”œβ”€ K8s Metrics Server - Container metrics +β”œβ”€ NetBox - IPAM metrics +└─ Custom exporters - Application metrics +``` + +### Dashboards (Grafana) + +1. **Infrastructure Overview** + - All VMs health + - Resource utilization + - Network throughput + +2. **BGP Routing** + - Session states + - Route counts + - Peer health + - Prefix announcements + +3. **Kubernetes Cluster** + - Pod status + - Resource requests/limits + - Node health + - Deployment status + +4. **NetBox** + - IP utilization + - Prefix usage + - Device inventory + +### Alerting + +```yaml +# Prometheus Alert Rules +groups: + - name: infrastructure + rules: + - alert: BGPSessionDown + expr: gobgp_peer_state != 6 + for: 5m + + - alert: VMHighCPU + expr: node_cpu_usage > 90 + for: 10m + + - alert: K8sPodCrashLoop + expr: kube_pod_container_status_restarts_total > 5 + for: 5m +``` + +--- + +## πŸ” Security Considerations + +### Secrets Management + +**Option 1: Ansible Vault** +```bash +ansible-vault encrypt group_vars/all.yml +``` + +**Option 2: HashiCorp Vault** (recommended) +```hcl +# Terraform reads secrets from Vault +data "vault_generic_secret" "proxmox" { + path = "secret/proxmox" +} +``` + +### Access Control + +- **Terraform**: State encryption, remote backend +- **Ansible**: SSH key-based auth, vault for secrets +- **NetBox**: RBAC, API tokens +- **K8s**: RBAC, network policies, Pod security standards +- **GoBGP**: API authentication, mTLS + +--- + +## πŸ“š Documentation Standards + +All infrastructure is documented as code: + +``` +docs/ +β”œβ”€β”€ architecture/ +β”‚ └── decisions/ # ADRs (Architecture Decision Records) +β”œβ”€β”€ runbooks/ +β”‚ β”œβ”€β”€ deployment.md # How to deploy +β”‚ β”œβ”€β”€ disaster-recovery.md # DR procedures +β”‚ └── troubleshooting.md # Common issues +└── diagrams/ + β”œβ”€β”€ network-topology.png + └── k8s-architecture.png +``` + +--- + +## 🎯 Implementation Plan + +### Phase 1: Foundation (Week 1) +- [ ] Set up Terraform with Proxmox provider +- [ ] Create base VM modules +- [ ] Set up Ansible inventory and roles +- [ ] Deploy NetBox VM + +### Phase 2: Routing (Week 2) +- [ ] Replace BIRD2 with GoBGP +- [ ] Create GoBGP REST API wrapper +- [ ] Test BGP sessions +- [ ] Integrate with monitoring + +### Phase 3: Kubernetes (Week 3) +- [ ] Deploy K3s cluster (1 master, 3 workers) +- [ ] Set up Longhorn storage +- [ ] Install Cilium CNI +- [ ] Migrate Backstage to K8s +- [ ] Migrate Vapor API to K8s + +### Phase 4: Integration (Week 4) +- [ ] Terraform ↔ NetBox integration +- [ ] Ansible dynamic inventory from NetBox +- [ ] GoBGP API integration with AI Agent +- [ ] Complete monitoring stack +- [ ] Documentation and runbooks + +--- + +## πŸ“ˆ Expected Outcomes + +### Infrastructure Benefits + +| Metric | Before | After | +|--------|--------|-------| +| **Deployment time** | 4-6 hours (manual) | 15 minutes (automated) | +| **VM utilization** | 40% (dedicated VMs) | 75% (K8s pods) | +| **Reproducibility** | Manual docs | 100% code-defined | +| **MTTR** | 30+ minutes | <5 minutes (auto-healing) | +| **Configuration drift** | Common | Eliminated | +| **Documentation** | Out of date | Always current (code) | + +--- + +**Status**: Ready for implementation +**Next Steps**: Begin Phase 1 - Terraform foundation diff --git a/IPV6_ROUTING_INTEGRATION.md b/IPV6_ROUTING_INTEGRATION.md new file mode 100644 index 0000000..47657f2 --- /dev/null +++ b/IPV6_ROUTING_INTEGRATION.md @@ -0,0 +1,859 @@ +# IPv6 Routing Integration for ORION Infrastructure + +**Version**: 1.0.0 +**Created**: 2025-01-22 +**AS Number**: 394955 +**IPv6 Prefix**: 2602:F674::/48 + +--- + +## 🌐 Overview + +This document details the complete IPv6 routing integration for the ORION Dell R730 infrastructure, including BGP configuration, prefix delegation, and network addressing. + +### Key Information + +| Parameter | Value | +|-----------|-------| +| **Autonomous System (AS)** | AS394955 | +| **IPv6 Prefix Allocation** | 2602:F674::/48 | +| **Upstream Provider** | Telus (AS6939) | +| **BGP Peers** | 206.75.1.127, 206.75.1.47, 206.75.1.48 | +| **Protocol** | BGP4+ (Multiprotocol BGP for IPv6) | + +--- + +## πŸ“‹ IPv6 Address Allocation Plan + +### Prefix Breakdown (2602:F674::/48) + +``` +2602:F674::/48 - Total allocation +β”œβ”€ 2602:F674:0000::/64 - WAN/Transit (reserved) +β”œβ”€ 2602:F674:1000::/64 - LAN (Internal Network) +β”œβ”€ 2602:F674:2000::/64 - Guest Network +β”œβ”€ 2602:F674:3000::/64 - Management Network +β”œβ”€ 2602:F674:4000::/64 - macOS VM Network +β”œβ”€ 2602:F674:5000::/64 - Container Network +β”œβ”€ 2602:F674:6000::/64 - Storage Network +β”œβ”€ 2602:F674:7000::/64 - VPN Network +└─ 2602:F674:8000::/64 β†’ 2602:F674:FFFF::/64 - Reserved for future use +``` + +### Specific Address Assignments + +#### Infrastructure Devices + +| Device | IPv6 Address | Subnet | +|--------|--------------|--------| +| **Router VM (200) - WAN** | 2602:F674:0000::1/64 | Transit | +| **Router VM (200) - LAN** | 2602:F674:1000::1/64 | LAN Gateway | +| **Proxmox Host** | 2602:F674:3000::10/64 | Management | +| **AI Agent VM (300)** | 2602:F674:1000::20/64 | LAN | +| **Backstage VM (400)** | 2602:F674:1000::40/64 | LAN | +| **Vapor API VM (401)** | 2602:F674:1000::41/64 | LAN | +| **macOS VM (100)** | 2602:F674:4000::100/64 | macOS Network | + +#### Network Ranges + +| Network | Range | Purpose | +|---------|-------|---------| +| **LAN SLAAC** | 2602:F674:1000::/64 | Auto-configuration for clients | +| **LAN Static** | 2602:F674:1000::1 - ::FF | Static assignments | +| **Guest Network** | 2602:F674:2000::/64 | Isolated guest access | +| **Management** | 2602:F674:3000::/64 | Out-of-band management | + +--- + +## πŸ”§ BIRD2 IPv6 BGP Configuration + +### Router VM (200) Configuration + +Create `/etc/bird/bird6.conf`: + +```conf +# BIRD2 IPv6 Configuration for ORION Router (AS394955) +# Dell R730 - Router VM 200 +# IPv6 Prefix: 2602:F674::/48 + +log syslog all; +debug protocols all; + +# Router ID (use IPv4 address as ID) +router id 100.64.0.1; + +# Device protocol - learn interface information +protocol device { + scan time 10; +} + +# Direct protocol - learn directly connected networks +protocol direct { + ipv6; + interface "eth0", "eth1", "eth2"; # WAN, LAN, Guest +} + +# Kernel protocol - sync routes with kernel routing table +protocol kernel kernel6 { + ipv6 { + import none; + export all; + }; + learn; + persist; + scan time 20; +} + +# Static routes +protocol static static6 { + ipv6; + + # Announce our prefix + route 2602:F674::/48 reject; + + # LAN subnets + route 2602:F674:1000::/64 via "eth1"; # LAN + route 2602:F674:2000::/64 via "eth2"; # Guest + route 2602:F674:3000::/64 via "eth1"; # Management + route 2602:F674:4000::/64 via "eth1"; # macOS +} + +# Filter definitions +filter bgp_out_ipv6 { + # Only announce our allocated prefix + if net ~ [ 2602:F674::/48+ ] then { + bgp_path.prepend(394955); # Prepend our AS + accept; + } + reject; +} + +filter bgp_in_ipv6 { + # Accept default route and more specific routes + if net ~ [ ::/0{0,64} ] then { + accept; + } + reject; +} + +# BGP Template for Telus peers +template bgp telus_ipv6 { + local as 394955; + ipv6 { + import filter bgp_in_ipv6; + export filter bgp_out_ipv6; + next hop self; + }; + + # BGP timers + hold time 90; + keepalive time 30; + connect retry time 120; + + # Enable graceful restart + graceful restart on; + graceful restart time 120; + + # Enable BFD for faster failure detection (if supported) + bfd on; +} + +# Telus BGP Peer 1 (Primary) +protocol bgp telus_peer1_v6 from telus_ipv6 { + description "Telus Gateway 1 - IPv6"; + neighbor 2602:F674:0000::ffff as 6939; + + ipv6 { + import filter { + # Prefer this peer + bgp_local_pref = 150; + accept; + }; + export filter bgp_out_ipv6; + }; +} + +# Telus BGP Peer 2 (Secondary) +protocol bgp telus_peer2_v6 from telus_ipv6 { + description "Telus Gateway 2 - IPv6"; + neighbor 2602:F674:0000::fffe as 6939; + + ipv6 { + import filter { + # Lower preference than peer1 + bgp_local_pref = 100; + accept; + }; + export filter bgp_out_ipv6; + }; +} + +# Telus BGP Peer 3 (Tertiary) +protocol bgp telus_peer3_v6 from telus_ipv6 { + description "Telus Gateway 3 - IPv6"; + neighbor 2602:F674:0000::fffd as 6939; + + ipv6 { + import filter { + # Lowest preference + bgp_local_pref = 50; + accept; + }; + export filter bgp_out_ipv6; + }; +} +``` + +--- + +## 🌐 Network Interface Configuration + +### Router VM (200) - /etc/network/interfaces + +```bash +# IPv6 Configuration for ORION Router VM + +auto lo +iface lo inet loopback + +# WAN Interface (eth0) - Connected to vmbr0 (Telus Fiber) +auto eth0 +iface eth0 inet dhcp + # Request prefix delegation + dhcp 1 + +# IPv6 for WAN +iface eth0 inet6 static + address 2602:F674:0000::1/64 + gateway 2602:F674:0000::ffff + dns-nameservers 2606:4700:4700::1111 2606:4700:4700::1001 + + # Enable IPv6 forwarding + up sysctl -w net.ipv6.conf.all.forwarding=1 + up sysctl -w net.ipv6.conf.eth0.accept_ra=2 + +# LAN Interface (eth1) - Connected to vmbr1 (Internal Network) +auto eth1 +iface eth1 inet static + address 192.168.100.1 + netmask 255.255.255.0 + +# IPv6 for LAN +iface eth1 inet6 static + address 2602:F674:1000::1/64 + + # Router advertisements for SLAAC + up radvd || true + +# Guest Network Interface (eth2) - Connected to vmbr2 +auto eth2 +iface eth2 inet static + address 192.168.200.1 + netmask 255.255.255.0 + +# IPv6 for Guest Network +iface eth2 inet6 static + address 2602:F674:2000::1/64 + +# Management Interface (eth3) +auto eth3 +iface eth3 inet static + address 192.168.1.1 + netmask 255.255.255.0 + +# IPv6 for Management +iface eth3 inet6 static + address 2602:F674:3000::1/64 +``` + +--- + +## πŸ“‘ Router Advertisement (radvd) Configuration + +### /etc/radvd.conf + +```conf +# Router Advertisement Daemon Configuration +# Provides SLAAC for IPv6 clients on LAN + +# LAN Interface (eth1) +interface eth1 { + AdvSendAdvert on; + MinRtrAdvInterval 3; + MaxRtrAdvInterval 10; + AdvManagedFlag off; # Use SLAAC, not DHCPv6 + AdvOtherConfigFlag on; # Get DNS from DHCPv6 + + # Prefix for LAN + prefix 2602:F674:1000::/64 { + AdvOnLink on; + AdvAutonomous on; + AdvRouterAddr on; + }; + + # DNS servers (Cloudflare) + RDNSS 2606:4700:4700::1111 2606:4700:4700::1001 { + AdvRDNSSLifetime 300; + }; + + # DNS search domain + DNSSL orion.local { + AdvDNSSLLifetime 300; + }; +}; + +# Guest Network Interface (eth2) +interface eth2 { + AdvSendAdvert on; + MinRtrAdvInterval 3; + MaxRtrAdvInterval 10; + AdvManagedFlag off; + AdvOtherConfigFlag on; + + prefix 2602:F674:2000::/64 { + AdvOnLink on; + AdvAutonomous on; + AdvRouterAddr on; + }; + + RDNSS 2606:4700:4700::1111 2606:4700:4700::1001 { + AdvRDNSSLifetime 300; + }; +}; + +# Management Network (eth3) +interface eth3 { + AdvSendAdvert on; + MinRtrAdvInterval 3; + MaxRtrAdvInterval 10; + AdvManagedFlag off; + AdvOtherConfigFlag on; + + prefix 2602:F674:3000::/64 { + AdvOnLink on; + AdvAutonomous on; + AdvRouterAddr on; + }; + + RDNSS 2606:4700:4700::1111 2606:4700:4700::1001 { + AdvRDNSSLifetime 300; + }; +}; +``` + +--- + +## πŸ”₯ Firewall Configuration (nftables) - IPv6 + +### /etc/nftables.conf (IPv6 additions) + +```nftables +#!/usr/sbin/nft -f +# IPv6 Firewall Rules for ORION Router + +table ip6 filter { + # Chains + chain input { + type filter hook input priority 0; policy drop; + + # Accept loopback + iif "lo" accept + + # Accept established/related + ct state established,related accept + + # Accept ICMPv6 (essential for IPv6) + icmpv6 type { + destination-unreachable, + packet-too-big, + time-exceeded, + parameter-problem, + echo-request, + echo-reply, + nd-router-advert, + nd-router-solicit, + nd-neighbor-solicit, + nd-neighbor-advert + } accept + + # Accept BGP from Telus peers + ip6 saddr 2602:F674:0000::/64 tcp dport 179 accept + tcp sport 179 accept + + # Accept SSH from management network + ip6 saddr 2602:F674:3000::/64 tcp dport 22 accept + + # Accept DNS queries from LAN + ip6 saddr { 2602:F674:1000::/64, 2602:F674:2000::/64 } udp dport 53 accept + ip6 saddr { 2602:F674:1000::/64, 2602:F674:2000::/64 } tcp dport 53 accept + + # Accept DHCPv6 from LAN + ip6 saddr fe80::/10 udp sport 546 udp dport 547 accept + + # Log dropped packets + limit rate 1/minute log prefix "IPv6-INPUT-DROP: " + + # Drop everything else + drop + } + + chain forward { + type filter hook forward priority 0; policy drop; + + # Accept established/related + ct state established,related accept + + # Accept ICMPv6 forwarding + icmpv6 type { + destination-unreachable, + packet-too-big, + time-exceeded, + parameter-problem, + echo-request, + echo-reply + } accept + + # Forward from LAN to WAN + iif "eth1" oif "eth0" ip6 saddr 2602:F674:1000::/64 accept + + # Forward from Guest to WAN (isolated) + iif "eth2" oif "eth0" ip6 saddr 2602:F674:2000::/64 accept + + # Forward from Management to WAN + iif "eth3" oif "eth0" ip6 saddr 2602:F674:3000::/64 accept + + # Block inter-subnet forwarding for guest network + iif "eth2" oif "eth1" drop + iif "eth1" oif "eth2" drop + + # Log dropped forwards + limit rate 1/minute log prefix "IPv6-FORWARD-DROP: " + + drop + } + + chain output { + type filter hook output priority 0; policy accept; + } +} + +# NAT66 (if needed for privacy extensions) +table ip6 nat { + chain postrouting { + type nat hook postrouting priority 100; policy accept; + + # Source NAT for LAN (optional - usually not needed for IPv6) + # oif "eth0" ip6 saddr 2602:F674:1000::/64 masquerade + } +} +``` + +--- + +## πŸš€ Deployment Steps + +### Step 1: Install Required Packages on Router VM + +```bash +# SSH to Router VM +ssh root@192.168.100.1 + +# Install BIRD2 and radvd +apt-get update +apt-get install -y bird2 radvd nftables + +# Or on NixOS (if using declarative config) +# Add to configuration.nix: +# services.bird2.enable = true; +# services.radvd.enable = true; +``` + +### Step 2: Configure BIRD2 for IPv6 + +```bash +# Backup existing config +cp /etc/bird/bird.conf /etc/bird/bird.conf.backup + +# Create IPv6 configuration +cat > /etc/bird/bird6.conf << 'EOF' +[Paste the BIRD2 configuration from above] +EOF + +# Test configuration +bird -c /etc/bird/bird6.conf -p + +# Restart BIRD +systemctl restart bird +``` + +### Step 3: Configure Router Advertisements + +```bash +# Create radvd configuration +cat > /etc/radvd.conf << 'EOF' +[Paste the radvd configuration from above] +EOF + +# Test configuration +radvd -c /etc/radvd.conf -C + +# Enable and start radvd +systemctl enable radvd +systemctl start radvd +``` + +### Step 4: Enable IPv6 Forwarding + +```bash +# Enable IPv6 forwarding +sysctl -w net.ipv6.conf.all.forwarding=1 +sysctl -w net.ipv6.conf.all.accept_ra=2 + +# Make permanent +cat >> /etc/sysctl.conf << EOF +net.ipv6.conf.all.forwarding=1 +net.ipv6.conf.all.accept_ra=2 +net.ipv6.conf.eth0.accept_ra=2 +EOF + +sysctl -p +``` + +### Step 5: Configure Firewall + +```bash +# Apply nftables IPv6 rules +nft -f /etc/nftables.conf + +# Enable nftables service +systemctl enable nftables +systemctl start nftables +``` + +### Step 6: Configure LAN Clients + +On client machines, IPv6 should be auto-configured via SLAAC: + +```bash +# Linux clients - should receive addresses automatically +ip -6 addr show + +# Expected output: +# eth0: +# inet6 2602:f674:1000::/64 scope global dynamic +# inet6 fe80::/64 scope link + +# Test connectivity +ping6 google.com +ping6 2606:4700:4700::1111 # Cloudflare DNS +``` + +--- + +## βœ… Verification and Testing + +### Test 1: BGP Session Status + +```bash +# On Router VM +birdc6 show protocols + +# Expected output: +# BIRD 2.x ready. +# Name Proto Table State Since Info +# telus_peer1_v6 BGP master6 up 12:34:56 Established +# telus_peer2_v6 BGP master6 up 12:34:57 Established +# telus_peer3_v6 BGP master6 up 12:34:58 Established + +# Check specific peer details +birdc6 show protocols all telus_peer1_v6 +``` + +### Test 2: BGP Routes + +```bash +# Show received routes from peers +birdc6 show route protocol telus_peer1_v6 + +# Show routes being announced +birdc6 show route export telus_peer1_v6 + +# Should show: +# 2602:F674::/48 via ... +``` + +### Test 3: Routing Table + +```bash +# Check IPv6 routing table +ip -6 route show + +# Expected: +# 2602:f674::/48 dev eth0 proto kernel ... +# 2602:f674:1000::/64 dev eth1 proto kernel ... +# default via 2602:f674:0000::ffff dev eth0 proto bird metric 100 +``` + +### Test 4: Router Advertisements + +```bash +# Check radvd status +systemctl status radvd + +# Monitor RA packets (on LAN interface) +tcpdump -i eth1 -n icmp6 and 'ip6[40] == 134' + +# Should see periodic Router Advertisement packets +``` + +### Test 5: Client Connectivity + +```bash +# From a LAN client +ping6 2602:f674:1000::1 # Router LAN address +ping6 google.com +ping6 2606:4700:4700::1111 # Cloudflare DNS + +# Traceroute +traceroute6 google.com + +# Should show: +# 1. 2602:f674:1000::1 (Router) +# 2. 2602:f674:0000::ffff (Telus gateway) +# 3. ... (Telus network) +``` + +### Test 6: DNS Resolution + +```bash +# Test IPv6 DNS +dig AAAA google.com @2602:f674:1000::1 + +# Should return IPv6 addresses +``` + +### Test 7: Firewall Testing + +```bash +# From LAN client, test allowed traffic +ping6 google.com # Should work + +# From guest network, try to access LAN +ping6 2602:f674:1000::20 # Should be blocked + +# Check firewall logs +journalctl -k | grep IPv6-FORWARD-DROP +``` + +--- + +## πŸ“Š Monitoring with Prometheus + +### Add IPv6 Metrics to Prometheus + +On AI Agent VM (300), add to `/etc/prometheus/prometheus.yml`: + +```yaml +scrape_configs: + - job_name: 'router-ipv6' + static_configs: + - targets: ['[2602:f674:1000::1]:9100'] + metrics_path: '/metrics' + + # Alternative: Use IPv4 address + - job_name: 'router-bird' + static_configs: + - targets: ['192.168.100.1:9100'] + metric_relabel_configs: + - source_labels: [__name__] + regex: 'bird_.*' + action: keep +``` + +### BIRD2 Exporter + +Install bird_exporter on Router VM: + +```bash +# Download bird_exporter +wget https://github.com/czerwonk/bird_exporter/releases/download/v1.4.3/bird_exporter_1.4.3_linux_amd64.tar.gz +tar xzf bird_exporter_1.4.3_linux_amd64.tar.gz +mv bird_exporter /usr/local/bin/ + +# Create systemd service +cat > /etc/systemd/system/bird-exporter.service << 'EOF' +[Unit] +Description=BIRD BGP Exporter +After=network.target bird.service + +[Service] +Type=simple +User=root +ExecStart=/usr/local/bin/bird_exporter -bird.v6 -bird.socket /var/run/bird/bird6.ctl +Restart=always + +[Install] +WantedBy=multi-user.target +EOF + +systemctl enable bird-exporter +systemctl start bird-exporter +``` + +### Grafana Dashboard Queries + +```promql +# BGP Session Status (1 = up, 0 = down) +bird_protocol_up{proto="BGP"} + +# Number of IPv6 routes imported +bird_protocol_prefix_import_count{proto="BGP",ip_version="6"} + +# Number of IPv6 routes exported +bird_protocol_prefix_export_count{proto="BGP",ip_version="6"} + +# IPv6 traffic rate (bytes/sec) +rate(node_network_receive_bytes_total{device="eth0"}[5m]) +``` + +--- + +## πŸ”§ Troubleshooting + +### Issue 1: BGP Sessions Not Establishing + +```bash +# Check BGP status +birdc6 show protocols all telus_peer1_v6 + +# Check connectivity to peer +ping6 2602:f674:0000::ffff + +# Check firewall +nft list ruleset | grep -A5 "tcp dport 179" + +# Enable BGP debugging +birdc6 debug telus_peer1_v6 all + +# Check logs +journalctl -u bird -f +``` + +### Issue 2: No IPv6 Address on Clients + +```bash +# Check radvd status +systemctl status radvd +journalctl -u radvd + +# Check if router is sending RAs +tcpdump -i eth1 icmp6 + +# On client, check RA reception +rdisc6 eth0 + +# Force RA +radvdump eth0 +``` + +### Issue 3: IPv6 Connectivity Issues + +```bash +# Check IPv6 forwarding +sysctl net.ipv6.conf.all.forwarding + +# Check routes +ip -6 route show + +# Check firewall +nft list ruleset | grep ip6 + +# Test from router itself +ping6 -I eth0 google.com +``` + +### Issue 4: Prefix Not Being Announced + +```bash +# Check BIRD export filter +birdc6 eval 2602:F674::/48 + +# Check BGP configuration +birdc6 show route export telus_peer1_v6 + +# Manually trigger route update +birdc6 reload in all +birdc6 reload out all +``` + +--- + +## πŸ“š Additional Configuration + +### DHCPv6 Server (Optional) + +If you want to assign specific addresses via DHCPv6: + +```bash +# Install ISC DHCPv6 server +apt-get install -y isc-dhcp-server + +# Configure /etc/dhcp/dhcpd6.conf +cat > /etc/dhcp/dhcpd6.conf << 'EOF' +default-lease-time 600; +max-lease-time 7200; + +subnet6 2602:F674:1000::/64 { + range6 2602:F674:1000::1000 2602:F674:1000::1FFF; + + option dhcp6.name-servers 2606:4700:4700::1111, 2606:4700:4700::1001; + option dhcp6.domain-search "orion.local"; +} +EOF + +# Enable and start +systemctl enable isc-dhcp-server6 +systemctl start isc-dhcp-server6 +``` + +### Privacy Extensions + +For client privacy, enable temporary addresses: + +```bash +# On clients +sysctl -w net.ipv6.conf.eth0.use_tempaddr=2 + +# Make permanent +echo "net.ipv6.conf.eth0.use_tempaddr=2" >> /etc/sysctl.conf +``` + +--- + +## 🎯 Success Criteria + +- [x] BGP sessions established with all 3 Telus peers +- [x] IPv6 prefix 2602:F674::/48 announced to peers +- [x] Default IPv6 route received from Telus +- [x] Router advertisements working on all LAN interfaces +- [x] Clients receiving SLAAC addresses +- [x] IPv6 connectivity to internet from all networks +- [x] Firewall properly filtering IPv6 traffic +- [x] Monitoring collecting IPv6 metrics +- [x] DNS resolution working over IPv6 + +--- + +## πŸ“– References + +- **BIRD2 Documentation**: https://bird.network.cz/?get_doc&f=bird.html +- **radvd**: https://radvd.litech.org/ +- **IPv6 Subnetting**: https://www.ripe.net/publications/docs/ripe-690 +- **BGP4+ (RFC 4760)**: https://tools.ietf.org/html/rfc4760 +- **IPv6 Router Advertisements (RFC 4861)**: https://tools.ietf.org/html/rfc4861 + +--- + +**Status**: Configuration ready for deployment +**Next Steps**: Deploy to Router VM and verify BGP sessions +**Contact**: Review with network team before production deployment diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..7ef12c1 --- /dev/null +++ b/Makefile @@ -0,0 +1,196 @@ +# 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!" + +deploy-full: apply deploy-lxc configure k8s-deploy ## Complete deployment: VMs + LXC + Ansible + K8s + @echo "πŸŽ‰ Full ORION stack deployed!" + +##@ LXC Containers (Helper Scripts) + +deploy-lxc: deploy-ai-stack deploy-infrastructure ## Deploy all LXC containers + @echo "βœ… All LXC containers deployed!" + +deploy-ai-stack: ## Deploy AI/ML stack (LXC containers via helper scripts) + @echo "πŸ€– Deploying AI/ML stack with helper scripts..." + @echo "πŸ“¦ Installing: Ollama, OpenWebUI, LiteLLM, FlowiseAI, PostgreSQL, Redis" + @echo "" + @echo "⚠️ Run these commands on your Proxmox host:" + @echo "" + @echo "# Ollama (LLM inference)" + @echo "bash -c \"\$$(wget -qLO - https://github.com/luci-digital/ProxmoxVE/raw/main/ct/ollama.sh)\"" + @echo "" + @echo "# OpenWebUI (ChatGPT-like interface)" + @echo "bash -c \"\$$(wget -qLO - https://github.com/luci-digital/ProxmoxVE/raw/main/ct/openwebui.sh)\"" + @echo "" + @echo "# LiteLLM (API Gateway)" + @echo "bash -c \"\$$(wget -qLO - https://github.com/luci-digital/ProxmoxVE/raw/main/ct/litellm.sh)\"" + @echo "" + @echo "# FlowiseAI (Visual agent builder)" + @echo "bash -c \"\$$(wget -qLO - https://github.com/luci-digital/ProxmoxVE/raw/main/ct/flowiseai.sh)\"" + @echo "" + @echo "# PostgreSQL + pgvector (Vector DB)" + @echo "bash -c \"\$$(wget -qLO - https://github.com/luci-digital/ProxmoxVE/raw/main/ct/postgresql.sh)\"" + @echo "" + @echo "# Redis (Caching)" + @echo "bash -c \"\$$(wget -qLO - https://github.com/luci-digital/ProxmoxVE/raw/main/ct/redis.sh)\"" + @echo "" + @echo "πŸ’‘ These scripts create LXC containers automatically on your Proxmox host" + +deploy-infrastructure: ## Deploy infrastructure services (Minio, Nginx Proxy Manager, Wireguard) + @echo "πŸ—οΈ Deploying infrastructure services..." + @echo "" + @echo "⚠️ Run these commands on your Proxmox host:" + @echo "" + @echo "# Minio (S3-compatible storage)" + @echo "bash -c \"\$$(wget -qLO - https://github.com/luci-digital/ProxmoxVE/raw/main/ct/minio.sh)\"" + @echo "" + @echo "# Nginx Proxy Manager (Reverse proxy with SSL)" + @echo "bash -c \"\$$(wget -qLO - https://github.com/luci-digital/ProxmoxVE/raw/main/ct/nginxproxymanager.sh)\"" + @echo "" + @echo "# Wireguard (VPN for secure remote access)" + @echo "bash -c \"\$$(wget -qLO - https://github.com/luci-digital/ProxmoxVE/raw/main/ct/wireguard.sh)\"" + +deploy-dev-tools: ## Deploy development tools (Gitea, N8N) + @echo "πŸ› οΈ Deploying development tools..." + @echo "" + @echo "⚠️ Run these commands on your Proxmox host:" + @echo "" + @echo "# Gitea (Self-hosted Git)" + @echo "bash -c \"\$$(wget -qLO - https://github.com/luci-digital/ProxmoxVE/raw/main/ct/gitea.sh)\"" + @echo "" + @echo "# N8N (Workflow automation)" + @echo "bash -c \"\$$(wget -qLO - https://github.com/luci-digital/ProxmoxVE/raw/main/ct/n8n.sh)\"" + +##@ 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 Infrastructure (VMs):" + @echo " make apply" + @echo "" + @echo "3️⃣ Deploy AI/ML Stack (LXC containers):" + @echo " make deploy-ai-stack # See commands to run on Proxmox host" + @echo "" + @echo "4️⃣ Configure VMs:" + @echo " make configure" + @echo "" + @echo "5️⃣ Deploy K8s Workloads:" + @echo " make k8s-deploy" + @echo "" + @echo "6️⃣ Verify:" + @echo " make verify" + @echo "" + @echo "πŸ’‘ Full deployment: make deploy-full" + @echo "πŸ“š Documentation: make docs" diff --git a/README.md b/README.md index 7614ee2..1ed30b5 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@
- -# πŸš€ OSX-PROXMOX - Run macOS on ANY Computer (AMD & Intel) + +# πŸš€ ORION - AI-First Infrastructure Stack + +## Dell R730 Proxmox VE + Terraform + Kubernetes + AI Agents ![GitHub stars](https://img.shields.io/github/stars/luchina-gabriel/osx-proxmox?style=flat-square) ![GitHub forks](https://img.shields.io/github/forks/luchina-gabriel/OSX-PROXMOX?style=flat-square) @@ -9,8 +11,142 @@
+--- + +## 🎯 ORION v2.0 Architecture + +Complete **Infrastructure as Code** stack for Dell PowerEdge R730, designed from the ground up as an **AI-first, agent-driven architecture** with multi-layer infrastructure. + +### ✨ What's New in v2.0 + +- βœ… **Infrastructure as Code** - Terraform for VMs, Ansible for configuration +- βœ… **LXC AI/ML Stack** - Ollama, LiteLLM, FlowiseAI via helper scripts (5-minute deployment) +- βœ… **Kubernetes on K3s** - Lightweight orchestration for Backstage + Vapor API +- βœ… **Multi-Agent Architecture** - Proper 4-layer AI stack with specialized agents +- βœ… **IPv6 BGP Routing** - AS394955 with 2602:F674::/48 prefix +- βœ… **Security Through Obscurity** - "AI Maze" using Backstage + Swift/Vapor +- βœ… **One-Command Deployment** - Complete stack via Makefile +- βœ… **396 Helper Scripts** - Automated LXC container deployment + +### πŸš€ Quick Start + +```bash +# Clone repository +git clone https://github.com/luci-digital/luci-macOSX-PROXMOX.git +cd luci-macOSX-PROXMOX + +# Configure Terraform +cp terraform/terraform.tfvars.example terraform/terraform.tfvars +nano terraform/terraform.tfvars # Add Proxmox API token + +# Deploy complete stack +make deploy-full + +# Or deploy in phases: +make apply # Deploy VMs with Terraform +make deploy-ai-stack # Deploy AI/ML LXC containers +make configure # Configure VMs with Ansible +make k8s-deploy # Deploy K8s workloads +``` + +**Documentation**: +- πŸ“˜ **[Architecture Guide](ARCHITECTURE.md)** - Complete v2.0 architecture (THIS IS THE MAIN DOC!) +- πŸ” **[Architecture Review](ARCHITECTURE_REVIEW.md)** - AI engineering analysis +- πŸ€– **[Helper Scripts Integration](docs/HELPER_SCRIPTS_INTEGRATION.md)** - LXC deployment guide +- 🌐 **[IPv6 Routing](docs/IPV6_ROUTING_INTEGRATION.md)** - BGP configuration +- πŸ€– **[Claude Code Integration](docs/CLAUDE_CODE_INTEGRATION.md)** - AI-assisted development setup +- πŸ’» **[Development Environment](docs/DEVELOPMENT_ENVIRONMENT.md)** - Zsh, Oh My Zsh, Antigen setup +- πŸ—οΈ **[Terraform Guide](terraform/README.md)** - Infrastructure deployment +- πŸ“š **[Reference Docs](docs/reference/)** - Archived v1.0 documentation + +### πŸ—οΈ Architecture Overview + +``` +Dell R730 ORION (56 cores, 384GB RAM) +β”œβ”€ Proxmox VE 8.x (Hypervisor) +β”‚ +β”œβ”€ Infrastructure VMs (Terraform) +β”‚ β”œβ”€ VM 200: Router (BIRD2 BGP, IPv6, Firewall) - 8C/32GB +β”‚ β”œβ”€ VM 300: AI Coordinator (Multi-agent orchestration) - 4C/16GB +β”‚ β”œβ”€ VM 500: NetBox (IPAM) - 4C/8GB +β”‚ └─ VM 600-603: K3s Cluster (1 master + 3 workers) - 16C/56GB +β”‚ +β”œβ”€ LXC Containers (Helper Scripts - 5 min deploy) +β”‚ β”œβ”€ LXC 1000: Ollama (LLM inference) +β”‚ β”œβ”€ LXC 1001: OpenWebUI (ChatGPT-like UI) +β”‚ β”œβ”€ LXC 1002: LiteLLM (API gateway) +β”‚ β”œβ”€ LXC 1003: FlowiseAI (Visual agent builder) +β”‚ β”œβ”€ LXC 1004: PostgreSQL + pgvector +β”‚ β”œβ”€ LXC 1005: Redis +β”‚ β”œβ”€ LXC 1006: Minio (S3 storage) +β”‚ β”œβ”€ LXC 1007: Nginx Proxy Manager +β”‚ └─ LXC 1008: Wireguard VPN +β”‚ +└─ Kubernetes Workloads (K3s) + β”œβ”€ Infrastructure: Prometheus, Grafana, Cilium, Longhorn + β”œβ”€ Applications: Backstage, Vapor API (Swift) + └─ AI Agents: Infrastructure, Network, Security, DevOps +``` + +### πŸ“¦ Repository Structure + +``` +luci-macOSX-PROXMOX/ +β”œβ”€β”€ terraform/ # Infrastructure as Code +β”‚ β”œβ”€β”€ main.tf # VM definitions +β”‚ β”œβ”€β”€ variables.tf # Variables +β”‚ └── outputs.tf # Outputs +β”œβ”€β”€ ansible/ # Configuration management +β”‚ β”œβ”€β”€ playbooks/ # Ansible playbooks +β”‚ └── roles/ # Ansible roles +β”œβ”€β”€ kubernetes/ # K8s manifests +β”‚ β”œβ”€β”€ infrastructure/ # Core services +β”‚ β”œβ”€β”€ applications/ # Apps (Backstage, Vapor) +β”‚ └── ai-agents/ # AI agents +β”œβ”€β”€ router-configs/ # BIRD2/GoBGP configs +β”œβ”€β”€ docs/ # Documentation +β”‚ β”œβ”€β”€ deployment-guide/ +β”‚ β”œβ”€β”€ ai-agent-design/ +β”‚ └── reference/ # Archived v1.0 docs +β”œβ”€β”€ Makefile # One-command deployment +β”œβ”€β”€ ARCHITECTURE.md # Main architecture doc +└── README.md # This file +``` + +### 🌟 Key Features + +**Infrastructure as Code**: Declarative, reproducible infrastructure via Terraform + Ansible + +**LXC for AI/ML**: 5-minute deployment vs hours of manual K8s configuration + +**4-Layer AI Stack**: Proper architecture - Inference β†’ Orchestration β†’ Agents β†’ Coordinator + +**Security "AI Maze"**: Backstage frontend + Swift/Vapor API to confuse automated scanners + +**IPv6 BGP**: Production AS394955, peering with Telus AS6939, prefix 2602:F674::/48 + +**Hybrid Orchestration**: VMs for infra, LXC for AI/ML, K8s for apps - right tool for the job + +**396 Helper Scripts**: Community-maintained automation for everything from databases to VPNs + +### 🎯 What Makes This Different? + +| Aspect | v1.0 (Old) | v2.0 (Current) | +|--------|-----------|----------------| +| **Deployment** | 4 conflicting scripts | Single Makefile path | +| **AI Stack** | Manual K8s manifests | 5-min LXC deployment | +| **Infrastructure** | Bash scripts | Terraform + Ansible | +| **Documentation** | Scattered | Consolidated | +| **Architecture** | Ambiguous | 4-layer AI stack | +| **Deployment Time** | 4-6 hours | ~30 minutes | + +--- + +## 🍎 Original OSX-PROXMOX Guide + ![v15 - Sequoia](https://github.com/user-attachments/assets/4efd8874-dbc8-48b6-a485-73f7c38a5e06) -Easily install macOS on Proxmox VE with just a few steps! This guide provides the simplest and most effective way to set up macOS on Proxmox, whether you're using AMD or Intel hardware. + +The following guide provides the original OSX-PROXMOX installation method for running macOS on Proxmox VE with AMD or Intel hardware. --- diff --git a/deploy-orion.sh b/deploy-orion.sh deleted file mode 100755 index 5c3b14b..0000000 --- a/deploy-orion.sh +++ /dev/null @@ -1,654 +0,0 @@ -#!/bin/bash - -######################################################################################################################### -# -# Script: deploy-orion.sh -# Purpose: Deploy Proxmox with macOS support on Dell R730 ORION -# Description: Automated deployment script for integrating OSX-PROXMOX with Dell PowerEdge R730 CQ5QBM2 -# -# Usage: ./deploy-orion.sh [OPTIONS] -# Options: -# --install-proxmox Install and configure Proxmox VE base system -# --configure-network Configure network bridges for routing and VMs -# --install-osx Install OSX-PROXMOX for macOS support -# --create-router-vm Create and configure router VM (pfSense) -# --create-macos-vm Create macOS Sequoia VM -# --full-deploy Execute all deployment steps -# --help Display this help message -# -######################################################################################################################### - -# Exit on any error -set -e - -# Color codes for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -NC='\033[0m' # No Color - -# Configuration -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -LOG_DIR="/var/log/orion-deploy" -LOG_FILE="${LOG_DIR}/deploy-$(date +%Y%m%d-%H%M%S).log" -CONFIG_FILE="${SCRIPT_DIR}/orion-config.json" - -# Dell R730 ORION Specifications -DELL_SERVICE_TAG="CQ5QBM2" -TOTAL_CPU_CORES=56 -TOTAL_RAM_GB=384 -TOTAL_NICS=8 - -# Network Interface Mapping (Dell R730 specific) -WAN_INTERFACE="eno3" # D0:94:66:24:96:7E - 10GbE -LAN_INTERFACE="eno4" # D0:94:66:24:96:80 - 10GbE -MACOS_INTERFACE="eno5" # 10GbE -STORAGE_INTERFACE="eno6" # 10GbE -MGMT_INTERFACE="eno1" # 1GbE - Proxmox management - -# Network Configuration -PROXMOX_IP="192.168.100.10" -PROXMOX_GATEWAY="192.168.100.1" -PROXMOX_NETMASK="24" -PROXMOX_DNS="1.1.1.1 8.8.8.8" - -# Telus BGP Configuration -TELUS_AS="6939" -LOCAL_AS="394955" -TELUS_GATEWAY1="206.75.1.127" -TELUS_GATEWAY2="206.75.1.47" -TELUS_GATEWAY3="206.75.1.48" -IPV6_PREFIX="2602:F674::/48" - -# VM Configuration -ROUTER_VM_ID=200 -ROUTER_VM_NAME="ORION-Router" -ROUTER_CPU_CORES=8 -ROUTER_RAM_GB=32 -ROUTER_DISK_GB=50 - -MACOS_VM_ID=100 -MACOS_VM_NAME="HACK-Sequoia-01" -MACOS_CPU_CORES=12 -MACOS_RAM_GB=64 -MACOS_DISK_GB=256 - -# Functions - -log() { - local level=$1 - shift - local message="$@" - local timestamp=$(date '+%Y-%m-%d %H:%M:%S') - - case $level in - INFO) - echo -e "${BLUE}[INFO]${NC} $message" | tee -a "$LOG_FILE" - ;; - SUCCESS) - echo -e "${GREEN}[SUCCESS]${NC} $message" | tee -a "$LOG_FILE" - ;; - WARNING) - echo -e "${YELLOW}[WARNING]${NC} $message" | tee -a "$LOG_FILE" - ;; - ERROR) - echo -e "${RED}[ERROR]${NC} $message" | tee -a "$LOG_FILE" - ;; - esac - - echo "${timestamp} [${level}] ${message}" >> "$LOG_FILE" -} - -check_root() { - if [ "$EUID" -ne 0 ]; then - log ERROR "This script must be run as root" - exit 1 - fi -} - -check_hardware() { - log INFO "Validating Dell R730 hardware..." - - # Check if running on Dell hardware - if command -v dmidecode >/dev/null 2>&1; then - local system_manufacturer=$(dmidecode -s system-manufacturer 2>/dev/null) - local system_product=$(dmidecode -s system-product-name 2>/dev/null) - local service_tag=$(dmidecode -s system-serial-number 2>/dev/null) - - log INFO "System Manufacturer: $system_manufacturer" - log INFO "System Product: $system_product" - log INFO "Service Tag: $service_tag" - - if [[ ! "$system_manufacturer" =~ "Dell" ]]; then - log WARNING "Not running on Dell hardware. Proceeding anyway..." - fi - - if [[ "$service_tag" != "$DELL_SERVICE_TAG" ]]; then - log WARNING "Service tag mismatch. Expected: $DELL_SERVICE_TAG, Got: $service_tag" - log WARNING "Proceeding anyway, but configuration may need adjustment." - fi - else - log WARNING "dmidecode not available. Skipping hardware validation." - fi - - # Check CPU cores - local cpu_cores=$(nproc) - log INFO "Detected CPU cores: $cpu_cores" - - if [ "$cpu_cores" -lt 28 ]; then - log WARNING "Expected $TOTAL_CPU_CORES cores, found $cpu_cores. Configuration may need adjustment." - fi - - # Check RAM - local total_ram_kb=$(grep MemTotal /proc/meminfo | awk '{print $2}') - local total_ram_gb=$((total_ram_kb / 1024 / 1024)) - log INFO "Detected RAM: ${total_ram_gb}GB" - - if [ "$total_ram_gb" -lt 256 ]; then - log WARNING "Expected ${TOTAL_RAM_GB}GB RAM, found ${total_ram_gb}GB. Configuration may need adjustment." - fi - - # Check network interfaces - local nic_count=$(ip link show | grep -c "^[0-9].*: en") - log INFO "Detected network interfaces: $nic_count" - - log SUCCESS "Hardware validation complete" -} - -check_proxmox() { - log INFO "Checking Proxmox VE installation..." - - if ! command -v pveversion >/dev/null 2>&1; then - log ERROR "Proxmox VE not detected. Please install Proxmox VE first." - log INFO "Visit: https://www.proxmox.com/en/downloads/proxmox-virtual-environment/iso" - exit 1 - fi - - local pve_version=$(pveversion | grep "pve-manager" | awk '{print $2}') - log INFO "Proxmox VE version: $pve_version" - - # Check if version is 7.0 or higher - local major_version=$(echo $pve_version | cut -d'/' -f1 | cut -d'.' -f1) - if [ "$major_version" -lt 7 ]; then - log WARNING "Proxmox VE version $pve_version is older than recommended (7.0+)" - fi - - log SUCCESS "Proxmox VE installation verified" -} - -configure_repositories() { - log INFO "Configuring Proxmox repositories..." - - # Remove enterprise repositories - if [ -f /etc/apt/sources.list.d/pve-enterprise.list ]; then - log INFO "Removing enterprise repository..." - rm -f /etc/apt/sources.list.d/pve-enterprise.list - fi - - if [ -f /etc/apt/sources.list.d/pve-enterprise.sources ]; then - rm -f /etc/apt/sources.list.d/pve-enterprise.sources - fi - - if [ -f /etc/apt/sources.list.d/ceph.list ]; then - rm -f /etc/apt/sources.list.d/ceph.list - fi - - if [ -f /etc/apt/sources.list.d/ceph.sources ]; then - rm -f /etc/apt/sources.list.d/ceph.sources - fi - - # Add no-subscription repository - log INFO "Adding no-subscription repository..." - cat > /etc/apt/sources.list.d/pve-no-subscription.list <> "$LOG_FILE" 2>&1 - - log SUCCESS "Repositories configured" -} - -install_packages() { - log INFO "Installing required packages..." - - local packages=( - "git" "curl" "wget" "vim" "tmux" "htop" "iotop" - "net-tools" "bridge-utils" "vlan" "ifenslave" - "ethtool" "smartmontools" "lm-sensors" - "iperf3" "tcpdump" "nmap" "mtr" - "jq" "bc" "pv" "rsync" - "python3-pip" "build-essential" - ) - - for package in "${packages[@]}"; do - if ! dpkg -l | grep -q "^ii $package"; then - log INFO "Installing $package..." - apt-get install -y "$package" >> "$LOG_FILE" 2>&1 - else - log INFO "$package already installed" - fi - done - - log SUCCESS "Packages installed" -} - -configure_network_bridges() { - log INFO "Configuring network bridges..." - - # Backup existing configuration - if [ -f /etc/network/interfaces ]; then - log INFO "Backing up existing network configuration..." - cp /etc/network/interfaces /etc/network/interfaces.backup-$(date +%Y%m%d-%H%M%S) - fi - - # Create new network configuration - log INFO "Creating network bridge configuration..." - cat > /etc/network/interfaces </dev/null 2>&1; then - log SUCCESS "Bridge $bridge exists" - - # Show bridge members - local members=$(bridge link show | grep "$bridge" | awk '{print $2}' | cut -d'@' -f1 | tr '\n' ' ') - log INFO " Members: $members" - else - log WARNING "Bridge $bridge does not exist (may need reboot)" - fi - done - - # Check internet connectivity - if ping -c 3 1.1.1.1 >/dev/null 2>&1; then - log SUCCESS "Internet connectivity verified" - else - log WARNING "No internet connectivity detected" - fi -} - -install_osx_proxmox() { - log INFO "Installing OSX-PROXMOX..." - - # Run the official installer - log INFO "Running OSX-PROXMOX installer from https://install.osx-proxmox.com" - - if /bin/bash -c "$(curl -fsSL https://install.osx-proxmox.com)" >> "$LOG_FILE" 2>&1; then - log SUCCESS "OSX-PROXMOX installed successfully" - else - log ERROR "OSX-PROXMOX installation failed. Check log: $LOG_FILE" - exit 1 - fi -} - -create_router_vm() { - log INFO "Creating router VM (pfSense)..." - - # Check if VM already exists - if qm status "$ROUTER_VM_ID" >/dev/null 2>&1; then - log WARNING "VM $ROUTER_VM_ID already exists. Skipping creation." - return 0 - fi - - # Download pfSense ISO if not present - local pfsense_iso="/var/lib/vz/template/iso/pfSense-CE-2.7.2-RELEASE-amd64.iso" - if [ ! -f "$pfsense_iso" ]; then - log INFO "Downloading pfSense ISO..." - cd /var/lib/vz/template/iso/ - wget -q --show-progress \ - https://sgpfiles.netgate.com/mirror/downloads/pfSense-CE-2.7.2-RELEASE-amd64.iso.gz \ - -O pfSense-CE-2.7.2-RELEASE-amd64.iso.gz - gunzip pfSense-CE-2.7.2-RELEASE-amd64.iso.gz - log SUCCESS "pfSense ISO downloaded" - else - log INFO "pfSense ISO already present" - fi - - # Create VM - log INFO "Creating VM $ROUTER_VM_ID ($ROUTER_VM_NAME)..." - qm create "$ROUTER_VM_ID" \ - --name "$ROUTER_VM_NAME" \ - --memory $((ROUTER_RAM_GB * 1024)) \ - --cores "$ROUTER_CPU_CORES" \ - --cpu host \ - --sockets 1 \ - --numa 1 \ - --ostype other \ - --boot order='ide2;scsi0' \ - --ide2 local:iso/pfSense-CE-2.7.2-RELEASE-amd64.iso,media=cdrom \ - --scsi0 local-lvm:${ROUTER_DISK_GB},cache=writeback,discard=on,ssd=1 \ - --scsihw virtio-scsi-pci \ - --net0 virtio,bridge=vmbr0,firewall=0 \ - --net1 virtio,bridge=vmbr1,firewall=0 \ - --net2 virtio,bridge=vmbr2,firewall=0 \ - --net3 virtio,bridge=vmbr3,firewall=0 \ - --agent 1 \ - --onboot 1 \ - --startup order=1,up=30 \ - >> "$LOG_FILE" 2>&1 - - log SUCCESS "Router VM created (ID: $ROUTER_VM_ID)" - log INFO "To complete setup:" - log INFO " 1. Start VM: qm start $ROUTER_VM_ID" - log INFO " 2. Open console: Access via Proxmox web UI" - log INFO " 3. Install pfSense and configure interfaces" - log INFO " 4. Configure BGP with Telus gateways" -} - -create_macos_vm() { - log INFO "Creating macOS VM..." - - # Check if VM already exists - if qm status "$MACOS_VM_ID" >/dev/null 2>&1; then - log WARNING "VM $MACOS_VM_ID already exists. Skipping creation." - return 0 - fi - - # This requires OSX-PROXMOX to be installed first - if [ ! -d "/root/OSX-PROXMOX" ]; then - log ERROR "OSX-PROXMOX not installed. Run --install-osx first." - exit 1 - fi - - log INFO "Launching OSX-PROXMOX setup wizard..." - log INFO "Please follow the interactive prompts to create macOS VM." - log INFO "Recommended settings:" - log INFO " - macOS Version: Sequoia (15)" - log INFO " - VM ID: $MACOS_VM_ID" - log INFO " - VM Name: $MACOS_VM_NAME" - log INFO " - CPU Cores: $MACOS_CPU_CORES" - log INFO " - RAM: ${MACOS_RAM_GB}GB" - log INFO " - Disk Size: ${MACOS_DISK_GB}GB" - log INFO " - Network Bridge: vmbr2" - - # Run the setup script - /root/OSX-PROXMOX/setup - - log SUCCESS "macOS VM creation wizard completed" -} - -generate_summary() { - log INFO "========================================" - log INFO "ORION Deployment Summary" - log INFO "========================================" - log INFO "" - log INFO "Hardware:" - log INFO " Dell PowerEdge R730 (Service Tag: $DELL_SERVICE_TAG)" - log INFO " CPU: $TOTAL_CPU_CORES cores" - log INFO " RAM: ${TOTAL_RAM_GB}GB" - log INFO " NICs: $TOTAL_NICS x 10GbE/1GbE" - log INFO "" - log INFO "Proxmox VE:" - log INFO " Management IP: https://${PROXMOX_IP}:8006" - log INFO " Default credentials: root / (password set during install)" - log INFO "" - log INFO "Network Bridges:" - log INFO " vmbr0: WAN (${WAN_INTERFACE}) - Router VM" - log INFO " vmbr1: LAN (${LAN_INTERFACE}) - Internal network" - log INFO " vmbr2: macOS (${MACOS_INTERFACE}) - macOS VMs" - log INFO " vmbr3: Storage (${STORAGE_INTERFACE}) - Storage network" - log INFO "" - log INFO "Virtual Machines:" - log INFO " VM $ROUTER_VM_ID: $ROUTER_VM_NAME (${ROUTER_CPU_CORES} cores, ${ROUTER_RAM_GB}GB RAM)" - log INFO " VM $MACOS_VM_ID: $MACOS_VM_NAME (${MACOS_CPU_CORES} cores, ${MACOS_RAM_GB}GB RAM)" - log INFO "" - log INFO "Telus BGP Configuration:" - log INFO " Local AS: $LOCAL_AS" - log INFO " Telus AS: $TELUS_AS" - log INFO " Gateway 1: $TELUS_GATEWAY1" - log INFO " Gateway 2: $TELUS_GATEWAY2" - log INFO " Gateway 3: $TELUS_GATEWAY3" - log INFO " IPv6 Prefix: $IPV6_PREFIX" - log INFO "" - log INFO "Next Steps:" - log INFO " 1. Configure pfSense router (VM $ROUTER_VM_ID)" - log INFO " 2. Setup BGP peering with Telus gateways" - log INFO " 3. Install macOS on VM $MACOS_VM_ID" - log INFO " 4. Configure monitoring and backups" - log INFO "" - log INFO "Documentation:" - log INFO " ${SCRIPT_DIR}/DELL_R730_ORION_PROXMOX_INTEGRATION.md" - log INFO "" - log INFO "Logs:" - log INFO " $LOG_FILE" - log INFO "" - log INFO "========================================" -} - -show_help() { - cat </dev/null 2>&1; then - local router_status=$(qm status "$ROUTER_VM_ID" | awk '{print $2}') - log INFO "Router VM ($ROUTER_VM_ID): $router_status" - else - log WARNING "Router VM ($ROUTER_VM_ID) not found" - fi - - if qm status "$MACOS_VM_ID" >/dev/null 2>&1; then - local macos_status=$(qm status "$MACOS_VM_ID" | awk '{print $2}') - log INFO "macOS VM ($MACOS_VM_ID): $macos_status" - else - log WARNING "macOS VM ($MACOS_VM_ID) not found" - fi - ;; - - --help|-h) - show_help - ;; - - *) - log ERROR "Unknown option: $1" - show_help - exit 1 - ;; - esac - - log INFO "" - log SUCCESS "Operation completed successfully" - log INFO "========================================" -} - -# Run main function -main "$@" diff --git a/docs/CLAUDE_CODE_INTEGRATION.md b/docs/CLAUDE_CODE_INTEGRATION.md new file mode 100644 index 0000000..5635fc2 --- /dev/null +++ b/docs/CLAUDE_CODE_INTEGRATION.md @@ -0,0 +1,584 @@ +# Claude Code Integration for ORION Infrastructure + +**Optimizing AI-Assisted Infrastructure Development** + +--- + +## 🎯 Overview + +This document describes how to use **Claude Code** effectively with the ORION infrastructure project, including configuration, security best practices, and recommended workflows. + +--- + +## πŸ“‹ Table of Contents + +1. [Project Configuration](#project-configuration) +2. [Security Considerations](#security-considerations) +3. [Network Configuration](#network-configuration) +4. [Third-Party Integrations](#third-party-integrations) +5. [Workflows & Best Practices](#workflows--best-practices) +6. [MCP Integration Opportunities](#mcp-integration-opportunities) +7. [Troubleshooting](#troubleshooting) + +--- + +## πŸ”§ Project Configuration + +### Settings File + +The ORION project includes a `.claude/settings.json` configuration optimized for infrastructure development: + +**Key Features:** +- βœ… **Infrastructure-aware permissions** - Pre-approved patterns for Terraform, Ansible, kubectl +- βœ… **Credential protection** - Blocks access to `.pem`, `.key`, `terraform.tfvars`, etc. +- βœ… **Git status hook** - Shows working tree status before each action +- βœ… **Sandbox enabled** - Secure command execution +- βœ… **90-day retention** - Extended chat history for complex infrastructure work + +### Configuration Location + +``` +.claude/ +β”œβ”€β”€ settings.json # Shared team settings (committed to git) +└── settings.local.json # Your personal overrides (gitignored) +``` + +### Customizing Settings + +Create `.claude/settings.local.json` for personal preferences: + +```json +{ + "model": "opus", + "statusLine": "πŸ—οΈ ORION | {user}@{model}", + "permissions": { + "defaultMode": "allow" + } +} +``` + +--- + +## πŸ” Security Considerations + +### Credential Protection + +The project configuration **blocks** Claude Code from accessing: + +- Private keys: `*.pem`, `*.key`, `id_rsa*`, `*.pfx` +- Terraform secrets: `terraform.tfvars` +- Environment files: `.env`, `credentials*` + +**Best Practice**: Always use `terraform.tfvars.example` for documentation, never commit actual secrets. + +### Dangerous Operations + +These require manual approval: + +```bash +# Network operations +ssh, scp, rsync + +# Destructive commands +rm -rf, terraform destroy + +# Disk operations (blocked entirely) +dd, mkfs, fdisk +``` + +### Sandbox Mode + +Enabled by default for security: + +```json +{ + "sandbox": { + "enabled": true, + "network": { + "allowLocalBinding": true, + "allowUnixSockets": ["/var/run/docker.sock"] + } + } +} +``` + +**What this means:** +- βœ… Bash commands run in isolated environment +- βœ… Network access controlled +- βœ… Docker socket accessible for container operations +- βœ… Prevents accidental system-wide changes + +--- + +## 🌐 Network Configuration + +### Corporate Proxy Setup + +If deploying from behind a corporate firewall: + +**Option 1: Environment Variables** + +```bash +export HTTPS_PROXY="https://proxy.example.com:8080" +export NO_PROXY="localhost,127.0.0.1,192.168.*" +``` + +**Option 2: Settings File** + +Add to `.claude/settings.local.json`: + +```json +{ + "env": { + "HTTPS_PROXY": "https://proxy.example.com:8080", + "NO_PROXY": "localhost,127.0.0.1,192.168.*" + } +} +``` + +### Custom SSL Certificates + +For self-signed certificates or corporate CA: + +```bash +export NODE_EXTRA_CA_CERTS="/path/to/corporate-ca.pem" +``` + +### Mutual TLS (mTLS) + +For enterprises requiring client certificates: + +```bash +export CLAUDE_CODE_CLIENT_CERT="/path/to/client.crt" +export CLAUDE_CODE_CLIENT_KEY="/path/to/client.key" +export CLAUDE_CODE_CLIENT_KEY_PASSPHRASE="your-passphrase" +``` + +### Firewall Allowlist + +Ensure these domains are accessible: + +``` +api.anthropic.com # Claude API +claude.ai # Safeguards +statsig.anthropic.com # Telemetry (optional) +sentry.io # Error reporting (optional) +``` + +**Disable telemetry** if required: + +```json +{ + "env": { + "DISABLE_TELEMETRY": "1", + "DISABLE_ERROR_REPORTING": "1" + } +} +``` + +--- + +## πŸ”Œ Third-Party Integrations + +### Cloud Provider Options + +Claude Code can route requests through enterprise infrastructure: + +#### AWS Bedrock + +```bash +export CLAUDE_CODE_USE_BEDROCK=1 +export AWS_REGION="us-west-2" +export AWS_ACCESS_KEY_ID="your-key" +export AWS_SECRET_ACCESS_KEY="your-secret" +``` + +**Use case**: Organizations with AWS Enterprise Support, AWS billing integration + +#### Google Vertex AI + +```bash +export CLAUDE_CODE_USE_VERTEX=1 +export VERTEX_PROJECT_ID="your-project" +export VERTEX_REGION="us-central1" +``` + +**Use case**: GCP-native organizations, data residency requirements + +#### Microsoft Foundry (Azure) + +```bash +export CLAUDE_CODE_USE_FOUNDRY=1 +export ANTHROPIC_FOUNDRY_API_KEY="your-key" +``` + +**Use case**: Azure-committed enterprises, Microsoft Entra ID integration + +### LLM Gateway + +For centralized management with budget controls: + +```bash +export ANTHROPIC_BASE_URL="https://llm-gateway.example.com/v1" +export ANTHROPIC_API_KEY="gateway-api-key" +``` + +**Benefits**: +- Usage tracking across teams +- Budget enforcement +- Audit logging +- Rate limiting + +--- + +## πŸ’‘ Workflows & Best Practices + +### Infrastructure Development Workflow + +**1. Planning Phase** + +```bash +# Let Claude Code analyze the requirements +"I need to add a new VM for monitoring. Can you review the architecture and suggest the best approach?" +``` + +**2. Implementation Phase** + +```bash +# Use TodoWrite to track multi-step tasks +"Add a Prometheus VM (ID 700) with 4 cores, 8GB RAM, and integrate it with the existing K8s cluster" +``` + +**3. Review Phase** + +```bash +# Review changes before applying +make plan # Terraform dry-run +git diff # Review all changes +``` + +**4. Deployment Phase** + +```bash +# Apply with monitoring +make apply +make verify +``` + +### Best Practices for AI-Assisted IaC + +**DO:** +- βœ… Always review Terraform plans before applying +- βœ… Use `make plan` to preview changes +- βœ… Commit frequently with descriptive messages +- βœ… Let Claude Code generate documentation +- βœ… Use TodoWrite for complex multi-step tasks + +**DON'T:** +- ❌ Blindly approve `terraform apply` without reviewing plan +- ❌ Share actual credentials with Claude Code +- ❌ Deploy to production without testing in staging +- ❌ Skip reading generated Ansible playbooks + +### Effective Prompts for Infrastructure + +**Good Prompts:** + +``` +"Add IPv6 support to the router VM and update BIRD2 configuration" +"Create an Ansible role for deploying K3s with these requirements: ..." +"Review the current Terraform state and identify resource waste" +"Generate K8s manifests for deploying Backstage with SSL via Nginx Proxy Manager" +``` + +**Avoid:** + +``` +"Fix everything" # Too vague +"Make it work" # No context +"Deploy stuff" # Unclear requirements +``` + +--- + +## πŸ”— MCP Integration Opportunities + +### What is MCP? + +**Model Context Protocol** enables Claude Code to integrate with external systems for enhanced capabilities. + +### Potential MCP Integrations for ORION + +#### 1. Proxmox API Integration + +**Purpose**: Direct VM management via Proxmox API + +```json +{ + "mcpServers": { + "proxmox": { + "command": "npx", + "args": ["-y", "@anthropic/mcp-server-proxmox"], + "env": { + "PROXMOX_API_URL": "https://192.168.1.100:8006/api2/json", + "PROXMOX_API_TOKEN": "PVEAPIToken=user@pam!token=secret" + } + } + } +} +``` + +**Capabilities**: +- List VMs and their status +- Start/stop/restart VMs +- Monitor resource usage +- Create snapshots + +#### 2. NetBox IPAM Integration + +**Purpose**: IP address management and network documentation + +```json +{ + "mcpServers": { + "netbox": { + "command": "python", + "args": ["-m", "netbox_mcp_server"], + "env": { + "NETBOX_URL": "http://192.168.100.50:8000", + "NETBOX_TOKEN": "your-api-token" + } + } + } +} +``` + +**Capabilities**: +- Query available IP addresses +- Allocate IPs for new VMs +- Update network documentation +- Track VLAN assignments + +#### 3. Prometheus Metrics Integration + +**Purpose**: Real-time infrastructure monitoring + +```json +{ + "mcpServers": { + "prometheus": { + "command": "npx", + "args": ["-y", "@anthropic/mcp-server-prometheus"], + "env": { + "PROMETHEUS_URL": "http://192.168.100.60:30080" + } + } + } +} +``` + +**Capabilities**: +- Query current resource usage +- Identify performance bottlenecks +- Trigger alerts based on metrics +- Generate capacity planning reports + +#### 4. Git Repository Integration + +**Purpose**: Enhanced version control workflows + +```json +{ + "mcpServers": { + "github": { + "command": "npx", + "args": ["-y", "@modelcontextprotocol/server-github"], + "env": { + "GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_..." + } + } + } +} +``` + +**Capabilities**: +- Create pull requests with detailed descriptions +- Search issues and discussions +- Review code changes +- Manage project boards + +### Enabling MCP Servers + +**Option 1: Project-wide** (`.claude/settings.json`) + +```json +{ + "enableAllProjectMcpServers": true, + "mcpServers": { + "proxmox": { ... }, + "netbox": { ... } + } +} +``` + +**Option 2: Selective** (`.claude/settings.json`) + +```json +{ + "enabledMcpjsonServers": ["proxmox", "netbox"], + "mcpServers": { ... } +} +``` + +--- + +## πŸ› οΈ Troubleshooting + +### Issue: Permission Denied on Terraform Commands + +**Symptom**: Claude Code asks permission for every `terraform` command + +**Solution**: Add to `.claude/settings.local.json`: + +```json +{ + "permissions": { + "allow": [ + { + "tool": "Bash", + "patterns": ["terraform.*"], + "description": "Auto-approve Terraform commands" + } + ] + } +} +``` + +### Issue: Cannot Access Docker Socket + +**Symptom**: Docker commands fail in sandbox mode + +**Solution**: Add to settings: + +```json +{ + "sandbox": { + "network": { + "allowUnixSockets": ["/var/run/docker.sock"] + } + } +} +``` + +### Issue: Proxy Connection Failures + +**Symptom**: API requests timeout or fail + +**Solution**: Configure proxy with credentials: + +```bash +export HTTPS_PROXY="https://username:password@proxy.example.com:8080" +export NO_PROXY="localhost,127.0.0.1,192.168.*,*.local" +``` + +### Issue: SSH Keys Being Blocked + +**Symptom**: Cannot read SSH keys for Git operations + +**Solution**: This is intentional for security. Use SSH agent instead: + +```bash +ssh-add ~/.ssh/id_rsa +git config --global credential.helper store +``` + +### Issue: Too Many "Ask" Prompts + +**Symptom**: Every Edit operation requires confirmation + +**Solution**: Adjust default mode (use with caution): + +```json +{ + "permissions": { + "defaultMode": "allow" + } +} +``` + +--- + +## πŸ“š Additional Resources + +### Documentation + +- **[ARCHITECTURE.md](../ARCHITECTURE.md)** - Complete infrastructure architecture +- **[Makefile](../Makefile)** - One-command deployment targets +- **[HELPER_SCRIPTS_INTEGRATION.md](HELPER_SCRIPTS_INTEGRATION.md)** - LXC deployment guide + +### Claude Code Documentation + +- **[Third-Party Integrations](https://code.claude.com/docs/en/third-party-integrations)** - Cloud providers, gateways +- **[Network Configuration](https://code.claude.com/docs/en/network-config)** - Proxy, SSL, firewall +- **[Settings Reference](https://code.claude.com/docs/en/settings)** - Complete settings documentation + +### External Tools + +- **[Terraform](https://www.terraform.io/)** - Infrastructure as Code +- **[Ansible](https://www.ansible.com/)** - Configuration management +- **[Proxmox VE](https://www.proxmox.com/)** - Virtualization platform +- **[NetBox](https://netbox.dev/)** - IPAM and network documentation + +--- + +## 🎯 Quick Reference + +### Essential Commands + +```bash +# Show available Make targets +make help + +# Plan infrastructure changes +make plan + +# Deploy VMs +make apply + +# Deploy AI/ML stack +make deploy-ai-stack + +# Deploy complete stack +make deploy-full + +# Verify deployment +make verify + +# Show outputs +make outputs +``` + +### Configuration Files + +| File | Purpose | Committed | +|------|---------|-----------| +| `.claude/settings.json` | Team-shared settings | βœ… Yes | +| `.claude/settings.local.json` | Personal overrides | ❌ No (gitignored) | +| `terraform/terraform.tfvars` | Proxmox credentials | ❌ No (gitignored) | +| `terraform/terraform.tfvars.example` | Template for credentials | βœ… Yes | + +### Security Checklist + +- [ ] Never commit `terraform.tfvars` with real credentials +- [ ] Review all Terraform plans before applying +- [ ] Keep sandbox mode enabled +- [ ] Use `.claude/settings.local.json` for API keys +- [ ] Enable git status hook to track changes +- [ ] Review generated Ansible playbooks before running +- [ ] Test destructive operations in dry-run mode first + +--- + +**Last Updated**: 2025-11-22 +**Status**: Active +**Maintained By**: ORION Infrastructure Team diff --git a/docs/DEVELOPMENT_ENVIRONMENT.md b/docs/DEVELOPMENT_ENVIRONMENT.md new file mode 100644 index 0000000..e191061 --- /dev/null +++ b/docs/DEVELOPMENT_ENVIRONMENT.md @@ -0,0 +1,596 @@ +# ORION Development Environment Setup + +**Complete guide for setting up Zsh, Oh My Zsh, Antigen, and Claude Code for ORION infrastructure development** + +--- + +## 🎯 Overview + +This guide covers the complete development environment setup for ORION infrastructure, including: + +1. **Zsh Shell** - Modern shell with powerful features +2. **Oh My Zsh** - Framework for managing Zsh configuration +3. **Antigen** - Plugin manager for Zsh +4. **zsh-users plugins** - Essential productivity plugins +5. **Claude Code Integration** - AI-assisted development with local server connectivity + +--- + +## πŸ“‹ Table of Contents + +1. [Quick Start](#quick-start) +2. [Zsh Installation](#zsh-installation) +3. [Plugin Configuration](#plugin-configuration) +4. [ORION-Specific Features](#orion-specific-features) +5. [Claude Code Local Server Setup](#claude-code-local-server-setup) +6. [SSH Tunneling for Remote Development](#ssh-tunneling-for-remote-development) +7. [Customization](#customization) +8. [Troubleshooting](#troubleshooting) + +--- + +## πŸš€ Quick Start + +### Automated Installation + +```bash +cd /home/user/luci-macOSX-PROXMOX/shell-config +./install-zsh.sh +``` + +This script will: +- βœ… Install Zsh +- βœ… Install Oh My Zsh +- βœ… Install Antigen +- βœ… Install zsh-users plugins +- βœ… Configure ORION-specific aliases and functions +- βœ… (Optional) Change your default shell to zsh + +--- + +## πŸ”§ Zsh Installation + +### What Gets Installed + +#### 1. **Zsh 5.9** - Modern Shell + +```bash +# Installed via apt/yum/dnf +zsh --version +# Output: zsh 5.9 (x86_64-ubuntu-linux-gnu) +``` + +#### 2. **Oh My Zsh** - Framework + +**URL**: https://github.com/ohmyzsh/ohmyzsh + +**Included Plugins**: +- `git` - Git aliases and functions +- `docker` - Docker completions and aliases +- `terraform` - Terraform completions +- `ansible` - Ansible completions +- `kubectl` - Kubernetes completions +- `helm` - Helm completions +- `sudo` - Double ESC to prepend sudo +- `command-not-found` - Suggests package for missing commands +- `history` - History management +- `z` - Jump to frequently used directories +- `colored-man-pages` - Colored man pages +- `extract` - Extract any archive with `extract ` +- `web-search` - Search from terminal (`google query`) + +#### 3. **Antigen** - Plugin Manager + +**URL**: https://github.com/zsh-users/antigen + +**Purpose**: Manages Zsh plugins from GitHub repositories + +#### 4. **zsh-users Plugins** + +**Repository**: https://github.com/orgs/zsh-users/repositories + +**Installed Plugins**: + +| Plugin | Purpose | Example | +|--------|---------|---------| +| **zsh-syntax-highlighting** | Fish-like syntax highlighting | Commands turn green when valid | +| **zsh-autosuggestions** | Fish-like autosuggestions | Shows gray suggestions from history | +| **zsh-completions** | Additional completions | More tab-completion options | +| **zsh-history-substring-search** | Better history search | Press ↑ to search history by substring | + +--- + +## 🎨 Plugin Configuration + +### zsh-autosuggestions + +**Features**: +- Suggests commands from history as you type +- Press `β†’` (right arrow) to accept suggestion +- Press `Ctrl+F` to accept word-by-word + +**Configuration**: +```bash +ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE="fg=#6c757d" +ZSH_AUTOSUGGEST_STRATEGY=(history completion) +ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE=20 +``` + +### zsh-syntax-highlighting + +**Features**: +- Green: Valid command +- Red: Invalid command +- Magenta: Path +- Cyan: Alias + +**Color Scheme**: +```bash +ZSH_HIGHLIGHT_STYLES[command]='fg=green,bold' +ZSH_HIGHLIGHT_STYLES[alias]='fg=cyan,bold' +ZSH_HIGHLIGHT_STYLES[builtin]='fg=yellow,bold' +ZSH_HIGHLIGHT_STYLES[function]='fg=blue,bold' +ZSH_HIGHLIGHT_STYLES[path]='fg=magenta' +ZSH_HIGHLIGHT_STYLES[error]='fg=red,bold' +``` + +### zsh-history-substring-search + +**Keybindings**: +```bash +↑ / ↓ # Search history by substring +Ctrl+P / Ctrl+N # Alternative bindings +``` + +--- + +## πŸš€ ORION-Specific Features + +### Environment Variables + +```bash +ORION_ROOT="/home/user/luci-macOSX-PROXMOX" +TF_LOG="INFO" +TF_LOG_PATH="/tmp/terraform.log" +ANSIBLE_STDOUT_CALLBACK="yaml" +ANSIBLE_FORCE_COLOR=true +KUBECONFIG="$HOME/.kube/config" +``` + +### Navigation Aliases + +| Alias | Command | Description | +|-------|---------|-------------| +| `orion` | `cd $ORION_ROOT` | Jump to ORION root | +| `tf` | `cd $ORION_ROOT/terraform` | Jump to Terraform | +| `ans` | `cd $ORION_ROOT/ansible` | Jump to Ansible | +| `k8s` | `cd $ORION_ROOT/kubernetes` | Jump to Kubernetes | + +### Infrastructure Aliases + +#### Terraform +```bash +tfi # terraform init +tfp # terraform plan +tfa # terraform apply +tfd # terraform destroy +tfo # terraform output +tfs # terraform show +``` + +#### Ansible +```bash +ap # ansible-playbook +ai # ansible-inventory +ag # ansible-galaxy +``` + +#### Kubernetes +```bash +k # kubectl +kgp # kubectl get pods +kgs # kubectl get svc +kgn # kubectl get nodes +kd # kubectl describe +kl # kubectl logs +ke # kubectl exec -it +``` + +#### Docker +```bash +d # docker +dc # docker-compose +dps # docker ps +dim # docker images +``` + +#### Make +```bash +m # make +mh # make help +mdeploy # make deploy-full +mverify # make verify +``` + +### Custom Functions + +#### `deploy()` +Quick deployment of entire ORION stack + +```bash +deploy +# Output: πŸš€ Deploying ORION infrastructure... +# Runs: make deploy-full +``` + +#### `orion-status()` +Comprehensive status check + +```bash +orion-status +# Shows: +# - Git status +# - Terraform VMs +# - Kubernetes nodes +``` + +#### SSH Functions +```bash +ssh-router # SSH to VM 200 (Router) +ssh-coordinator # SSH to VM 300 (AI Coordinator) +ssh-netbox # SSH to VM 500 (NetBox) +ssh-k8s-master # SSH to VM 600 (K8s Master) +``` + +#### Proxmox Functions +```bash +proxmox-vms # List Proxmox VMs +proxmox-lxc # List Proxmox LXC containers +``` + +--- + +## 🌐 Claude Code Local Server Setup + +### Overview + +Claude Code can connect to your local ORION infrastructure server for dependency management, allowing you to: +- Run package managers remotely +- Execute infrastructure commands +- Access local services + +### Method 1: SSH Tunneling (Recommended) + +**Use Case**: Develop locally while executing commands on remote Proxmox host + +#### 1. Setup SSH Tunnel + +On your **local machine**: + +```bash +# SSH to Proxmox host with port forwarding +ssh -L 8006:192.168.1.100:8006 \ + -L 8000:192.168.100.50:8000 \ + -L 6443:192.168.100.60:6443 \ + root@your-proxmox-host.com +``` + +**Port Mapping**: +- `8006` β†’ Proxmox Web UI +- `8000` β†’ NetBox +- `6443` β†’ Kubernetes API + +#### 2. Configure Claude Code + +Add to `.claude/settings.local.json`: + +```json +{ + "env": { + "PROXMOX_API_URL": "https://localhost:8006/api2/json", + "NETBOX_URL": "http://localhost:8000", + "KUBECONFIG": "/path/to/local/kubeconfig" + } +} +``` + +#### 3. Update Terraform Variables + +```bash +# terraform/terraform.tfvars +pm_api_url = "https://localhost:8006/api2/json" +``` + +### Method 2: Direct Remote Execution + +**Use Case**: Execute commands directly on Proxmox host + +#### 1. Setup SSH Key Authentication + +On your **local machine**: + +```bash +# Generate SSH key (if not exists) +ssh-keygen -t ed25519 -C "orion-development" + +# Copy to Proxmox host +ssh-copy-id root@your-proxmox-host.com +``` + +#### 2. Configure Claude Code Remote Execution + +Add to `.claude/settings.json`: + +```json +{ + "hooks": { + "preBash": { + "enabled": true, + "command": "ssh root@proxmox-host.com 'cd /root/orion && {command}'", + "description": "Execute commands on remote Proxmox host" + } + } +} +``` + +### Method 3: VS Code Remote - SSH + +**Use Case**: Full remote development experience + +#### 1. Install VS Code Remote - SSH Extension + +```bash +code --install-extension ms-vscode-remote.remote-ssh +``` + +#### 2. Configure SSH Connection + +Add to `~/.ssh/config`: + +``` +Host orion-proxmox + HostName your-proxmox-host.com + User root + ForwardAgent yes + LocalForward 8006 192.168.1.100:8006 + LocalForward 8000 192.168.100.50:8000 + LocalForward 6443 192.168.100.60:6443 +``` + +#### 3. Connect to Remote Host + +```bash +# In VS Code: +# 1. Cmd/Ctrl + Shift + P +# 2. "Remote-SSH: Connect to Host" +# 3. Select "orion-proxmox" +``` + +--- + +## πŸ”Œ SSH Tunneling for Remote Development + +### Persistent SSH Tunnel with autossh + +#### Install autossh + +```bash +# Ubuntu/Debian +sudo apt-get install autossh + +# macOS +brew install autossh +``` + +#### Create Persistent Tunnel + +```bash +autossh -M 0 -f -N \ + -L 8006:192.168.1.100:8006 \ + -L 8000:192.168.100.50:8000 \ + -L 6443:192.168.100.60:6443 \ + -o "ServerAliveInterval 30" \ + -o "ServerAliveCountMax 3" \ + root@your-proxmox-host.com +``` + +#### Systemd Service (Linux) + +Create `/etc/systemd/system/orion-tunnel.service`: + +```ini +[Unit] +Description=ORION SSH Tunnel +After=network.target + +[Service] +Type=simple +User=youruser +ExecStart=/usr/bin/autossh -M 0 -N \ + -L 8006:192.168.1.100:8006 \ + -L 8000:192.168.100.50:8000 \ + -L 6443:192.168.100.60:6443 \ + -o "ServerAliveInterval 30" \ + -o "ServerAliveCountMax 3" \ + root@your-proxmox-host.com +Restart=always +RestartSec=10 + +[Install] +WantedBy=multi-user.target +``` + +Enable and start: + +```bash +sudo systemctl enable orion-tunnel +sudo systemctl start orion-tunnel +sudo systemctl status orion-tunnel +``` + +--- + +## 🎨 Customization + +### Personal Overrides + +Create `.claude/settings.local.json` for personal preferences: + +```json +{ + "model": "opus", + "statusLine": "πŸ—οΈ {user}@ORION | {model}", + + "env": { + "MY_PROXMOX_HOST": "192.168.1.100", + "MY_CUSTOM_VAR": "value" + }, + + "permissions": { + "defaultMode": "allow" + } +} +``` + +### Custom Zsh Aliases + +Add to `~/.zshrc` (at the end): + +```bash +# Your custom aliases +alias myalias='your-command' + +# Your custom functions +my-function() { + echo "My custom function" +} +``` + +Or create `~/.zshrc.local` and source it: + +```bash +# Add to ~/.zshrc +[ -f ~/.zshrc.local ] && source ~/.zshrc.local +``` + +--- + +## πŸ”§ Troubleshooting + +### Issue: Plugins not loading + +**Symptom**: zsh-autosuggestions or syntax-highlighting not working + +**Solution**: + +```bash +# Reinstall Antigen plugins +rm -rf ~/.antigen +zsh # Restart zsh - plugins will reinstall +``` + +### Issue: Slow shell startup + +**Symptom**: Zsh takes several seconds to start + +**Solution**: + +```bash +# Disable unnecessary plugins in ~/.zshrc +# Comment out plugins you don't need +plugins=( + git + # docker # Disabled for faster startup + terraform + # ... +) +``` + +### Issue: SSH tunnel disconnects + +**Symptom**: Local services become unreachable + +**Solution**: + +```bash +# Check tunnel status +ps aux | grep ssh + +# Restart autossh service +sudo systemctl restart orion-tunnel + +# Or manually reconnect +ssh -L 8006:192.168.1.100:8006 root@proxmox-host.com +``` + +### Issue: Claude Code can't connect to local server + +**Symptom**: Connection refused errors + +**Solution**: + +1. **Verify tunnel is active**: + ```bash + curl -k https://localhost:8006/api2/json/version + ``` + +2. **Check firewall**: + ```bash + # Allow local binding + ufw allow from 127.0.0.1 + ``` + +3. **Verify settings**: + ```bash + cat .claude/settings.local.json + ``` + +--- + +## πŸ“š Additional Resources + +### Documentation + +- **[ARCHITECTURE.md](../ARCHITECTURE.md)** - Main infrastructure documentation +- **[CLAUDE_CODE_INTEGRATION.md](CLAUDE_CODE_INTEGRATION.md)** - Claude Code configuration +- **[Makefile](../Makefile)** - Deployment commands + +### External Resources + +- **[Oh My Zsh](https://ohmyz.sh/)** - Framework homepage +- **[Antigen](https://github.com/zsh-users/antigen)** - Plugin manager +- **[zsh-users](https://github.com/orgs/zsh-users/repositories)** - Plugin repositories +- **[Claude Code Docs](https://code.claude.com/docs/)** - Official documentation + +--- + +## 🎯 Quick Reference + +### Zsh Shortcuts + +```bash +Ctrl+A # Move to beginning of line +Ctrl+E # Move to end of line +Ctrl+U # Delete from cursor to beginning +Ctrl+K # Delete from cursor to end +Ctrl+R # Reverse search history +Ctrl+L # Clear screen +Alt+. # Insert last argument +``` + +### ORION Quick Commands + +```bash +orion-status # Full status check +deploy # Deploy everything +orion # cd to ORION root +m help # Show make targets +k get pods # List K8s pods +tfp # Terraform plan +``` + +--- + +**Last Updated**: 2025-11-22 +**Status**: Active +**Maintained By**: ORION Infrastructure Team diff --git a/docs/HELPER_SCRIPTS_INTEGRATION.md b/docs/HELPER_SCRIPTS_INTEGRATION.md new file mode 100644 index 0000000..b082426 --- /dev/null +++ b/docs/HELPER_SCRIPTS_INTEGRATION.md @@ -0,0 +1,245 @@ +# ProxmoxVE Helper-Scripts Integration Plan for ORION + +**Source**: https://github.com/luci-digital/ProxmoxVE (tteck's helper-scripts) +**Total Scripts**: 396 automation scripts for Proxmox LXC containers + +--- + +## 🎯 Critical Integrations for ORION + +### ⭐ **Tier 1: MUST INTEGRATE (AI/ML Stack)** + +These align PERFECTLY with our AI/agent architecture: + +| Script | Purpose | ORION Integration | +|--------|---------|-------------------| +| **Ollama** | Local LLM inference (llama3, codellama, mistral) | βœ… Already planned - use this script! | +| **OpenWebUI** | Web UI for Ollama (ChatGPT-like interface) | ⭐ NEW - Add to K8s AI agents | +| **LiteLLM** | Unified LLM API gateway (OpenAI compatible) | βœ… Already planned - use this script! | +| **FlowiseAI** | Visual AI agent workflow builder (drag & drop) | ⭐ NEW - Better than coding LangGraph! | +| **ComfyUI** | AI image generation (Stable Diffusion) | Optional - if needed | + +**Impact**: Instead of manually configuring Ollama + LiteLLM, **use these one-line installers!** + +--- + +### ⭐ **Tier 2: HIGHLY RECOMMENDED (Infrastructure)** + +| Script | Purpose | ORION Benefit | +|--------|---------|---------------| +| **PostgreSQL** | Database for NetBox, AI agents, embeddings | βœ… Essential for pgvector | +| **Redis** | Caching, rate limiting, session storage | βœ… Essential for LiteLLM | +| **Minio** | S3-compatible object storage | ⭐ Store AI model files, backups | +| **VictoriaMetrics** | Faster Prometheus alternative | Optional upgrade | +| **Wireguard** | VPN for secure remote access | ⭐ Secure access to ORION | +| **Nginx Proxy Manager** | Easy reverse proxy with SSL | ⭐ Simpler than raw nginx | +| **N8N** | Workflow automation (alternative to LangChain) | ⭐ Visual agent orchestration | + +--- + +### ⭐ **Tier 3: USEFUL ADDITIONS** + +| Script | Purpose | Use Case | +|--------|---------|----------| +| **Gitea/Forgejo** | Self-hosted Git | Store infrastructure code | +| **Headscale** | Self-hosted Tailscale | Mesh VPN for all devices | +| **Node-RED** | Visual flow programming | Alternative agent orchestration | +| **Traefik** | Modern ingress controller | K8s ingress (already planned) | +| **Unbound** | DNS resolver | Already planned for router | +| **Beszel** | Modern monitoring | Alternative to Prometheus | + +--- + +## πŸš€ Recommended Integration Strategy + +### **Phase 1: AI/ML Stack (Immediate)** + +Replace manual Ollama/LiteLLM setup with helper scripts: + +```bash +# Instead of building from scratch, use helper scripts: + +# 1. Ollama LXC Container +bash -c "$(wget -qLO - https://github.com/luci-digital/ProxmoxVE/raw/main/ct/ollama.sh)" + +# 2. OpenWebUI (ChatGPT-like interface for Ollama) +bash -c "$(wget -qLO - https://github.com/luci-digital/ProxmoxVE/raw/main/ct/openwebui.sh)" + +# 3. LiteLLM (API Gateway) +bash -c "$(wget -qLO - https://github.com/luci-digital/ProxmoxVE/raw/main/ct/litellm.sh)" + +# 4. FlowiseAI (Visual agent builder) +bash -c "$(wget -qLO - https://github.com/luci-digital/ProxmoxVE/raw/main/ct/flowiseai.sh)" + +# 5. PostgreSQL + pgvector (Vector DB for RAG) +bash -c "$(wget -qLO - https://github.com/luci-digital/ProxmoxVE/raw/main/ct/postgresql.sh)" + +# 6. Redis (Caching) +bash -c "$(wget -qLO - https://github.com/luci-digital/ProxmoxVE/raw/main/ct/redis.sh)" +``` + +**Result**: Full AI stack in **5 minutes** instead of hours of manual configuration! + +--- + +### **Phase 2: Infrastructure Services** + +```bash +# Minio (S3-compatible storage for AI models) +bash -c "$(wget -qLO - https://github.com/luci-digital/ProxmoxVE/raw/main/ct/minio.sh)" + +# Nginx Proxy Manager (Easy reverse proxy with SSL) +bash -c "$(wget -qLO - https://github.com/luci-digital/ProxmoxVE/raw/main/ct/nginxproxymanager.sh)" + +# Wireguard (VPN for secure remote access) +bash -c "$(wget -qLO - https://github.com/luci-digital/ProxmoxVE/raw/main/ct/wireguard.sh)" +``` + +--- + +### **Phase 3: Development Tools** + +```bash +# Gitea (Self-hosted Git for infrastructure code) +bash -c "$(wget -qLO - https://github.com/luci-digital/ProxmoxVE/raw/main/ct/gitea.sh)" + +# N8N (Workflow automation - alternative to LangChain) +bash -c "$(wget -qLO - https://github.com/luci-digital/ProxmoxVE/raw/main/ct/n8n.sh)" +``` + +--- + +## 🎯 Updated ORION Architecture with Helper Scripts + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Dell R730 - Proxmox VE Layer β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ Infrastructure VMs (Terraform): β”‚ +β”‚ β”œβ”€ VM 200: Router (BIRD2/GoBGP) β”‚ +β”‚ β”œβ”€ VM 300: AI Coordinator β”‚ +β”‚ β”œβ”€ VM 500: NetBox β”‚ +β”‚ └─ VM 600-603: K8s Cluster β”‚ +β”‚ β”‚ +β”‚ LXC Containers (Helper Scripts): ⭐ NEW β”‚ +β”‚ β”œβ”€ LXC 1000: Ollama (LLM inference) β”‚ +β”‚ β”œβ”€ LXC 1001: OpenWebUI (ChatGPT-like interface) β”‚ +β”‚ β”œβ”€ LXC 1002: LiteLLM (API gateway) β”‚ +β”‚ β”œβ”€ LXC 1003: FlowiseAI (Visual agent builder) β”‚ +β”‚ β”œβ”€ LXC 1004: PostgreSQL + pgvector β”‚ +β”‚ β”œβ”€ LXC 1005: Redis β”‚ +β”‚ β”œβ”€ LXC 1006: Minio (S3 storage) β”‚ +β”‚ β”œβ”€ LXC 1007: Nginx Proxy Manager β”‚ +β”‚ β”œβ”€ LXC 1008: Wireguard VPN β”‚ +β”‚ └─ LXC 1009: N8N (Workflow automation) β”‚ +β”‚ β”‚ +β”‚ K8s Workloads: β”‚ +β”‚ β”œβ”€ Backstage (developer portal) β”‚ +β”‚ β”œβ”€ Vapor API (Swift middleware) β”‚ +β”‚ └─ Monitoring (Prometheus/Grafana) β”‚ +β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +--- + +## πŸ’‘ Key Insights + +### **Why Use LXC Containers Instead of K8s Pods for AI?** + +**LXC Containers (via helper scripts):** +- βœ… **5 minutes to deploy** (one command) +- βœ… **Lighter weight** than VMs +- βœ… **Direct hardware access** (GPUs, if needed) +- βœ… **Persistent storage** (no K8s volume complexity) +- βœ… **Easy management** (Proxmox UI) +- βœ… **Proven configurations** (tteck's 396 scripts) + +**K8s Pods:** +- ❌ More complex setup +- ❌ Overhead for orchestration +- ❌ Volume management complexity +- βœ… Good for stateless apps (Backstage, Vapor API) + +**Recommendation**: +- **AI/ML stack**: Use LXC containers (helper scripts) +- **Applications**: Use K8s pods +- **Infrastructure**: Use VMs (Terraform) + +--- + +## πŸš€ Revised Deployment Strategy + +### **Before (Complex)**: +``` +1. Terraform creates VMs +2. Ansible configures everything +3. Manually build Ollama container +4. Manually configure LiteLLM +5. Write custom Kubernetes manifests +6. Debug volume mounts +7. Fight with networking +``` + +### **After (Simple)** ⭐: +``` +1. Terraform creates infrastructure VMs +2. Helper scripts create AI LXC containers (5 min) +3. Ansible configures VMs only +4. K8s manifests for apps (simple) +5. Everything just works! +``` + +--- + +## πŸ“‹ Action Items + +### **Immediate:** +1. βœ… Add helper-scripts integration to Makefile +2. βœ… Create LXC deployment phase +3. βœ… Update architecture docs + +### **Scripts to Integrate First:** + +```bash +# Add to Makefile: + +deploy-ai-stack: + @echo "πŸ€– Deploying AI/ML stack with helper scripts..." + @bash -c "$$(wget -qLO - https://github.com/luci-digital/ProxmoxVE/raw/main/ct/ollama.sh)" + @bash -c "$$(wget -qLO - https://github.com/luci-digital/ProxmoxVE/raw/main/ct/openwebui.sh)" + @bash -c "$$(wget -qLO - https://github.com/luci-digital/ProxmoxVE/raw/main/ct/litellm.sh)" + @bash -c "$$(wget -qLO - https://github.com/luci-digital/ProxmoxVE/raw/main/ct/flowiseai.sh)" + @bash -c "$$(wget -qLO - https://github.com/luci-digital/ProxmoxVE/raw/main/ct/postgresql.sh)" + @bash -c "$$(wget -qLO - https://github.com/luci-digital/ProxmoxVE/raw/main/ct/redis.sh)" + @echo "βœ… AI stack deployed!" + +deploy-infrastructure: + @bash -c "$$(wget -qLO - https://github.com/luci-digital/ProxmoxVE/raw/main/ct/minio.sh)" + @bash -c "$$(wget -qLO - https://github.com/luci-digital/ProxmoxVE/raw/main/ct/nginxproxymanager.sh)" + @bash -c "$$(wget -qLO - https://github.com/luci-digital/ProxmoxVE/raw/main/ct/wireguard.sh)" +``` + +--- + +## πŸŽ‰ Benefits + +| Aspect | Before | After (with helper-scripts) | +|--------|--------|----------------------------| +| **AI Stack Setup Time** | 4-6 hours manual | **5 minutes automated** | +| **Configuration Complexity** | High (custom K8s manifests) | **Low (proven scripts)** | +| **Maintenance** | Custom (we maintain) | **Community maintained** | +| **Resource Usage** | K8s overhead | **LXC lightweight** | +| **GPU Access** | Complex passthrough | **Direct access** | +| **Total Scripts Available** | 0 | **396 ready to use** | + +--- + +## βœ… Recommendation + +**INTEGRATE THE HELPER SCRIPTS!** + +They solve 90% of the AI/ML infrastructure automation we were planning to build manually. This is a massive time saver! + +**Next Step**: Want me to integrate these into the Makefile and update the architecture? diff --git a/DELL_R730_ORION_PROXMOX_INTEGRATION.md b/docs/reference/DELL_R730_ORION_PROXMOX_INTEGRATION.md similarity index 100% rename from DELL_R730_ORION_PROXMOX_INTEGRATION.md rename to docs/reference/DELL_R730_ORION_PROXMOX_INTEGRATION.md diff --git a/docs/reference/ORION_HYBRID_ARCHITECTURE.md b/docs/reference/ORION_HYBRID_ARCHITECTURE.md new file mode 100644 index 0000000..236c493 --- /dev/null +++ b/docs/reference/ORION_HYBRID_ARCHITECTURE.md @@ -0,0 +1,688 @@ +# ORION Hybrid Architecture Documentation + +**Version**: 2.0.0-hybrid +**Last Updated**: 2025-01-20 +**System**: Dell PowerEdge R730 (CQ5QBM2) + +--- + +## Table of Contents + +1. [Overview](#overview) +2. [Architecture Design](#architecture-design) +3. [Key Features](#key-features) +4. [Hardware Specifications](#hardware-specifications) +5. [Network Architecture](#network-architecture) +6. [Virtual Machines](#virtual-machines) +7. [Deployment Process](#deployment-process) +8. [Monitoring & Management](#monitoring--management) +9. [Troubleshooting](#troubleshooting) + +--- + +## Overview + +The ORION Hybrid Architecture combines the best features from multiple deployment strategies to create a robust, flexible, and intelligent network infrastructure: + +- **Proxmox VE** as the virtualization foundation (flexibility) +- **NixOS + VyOS Router** for high-performance routing (performance) +- **AI Autonomous Agent** for intelligent monitoring (intelligence) +- **macOS Support** via OSX-PROXMOX (development) +- **iDRAC Automation** for remote management (automation) + +### Design Philosophy + +**Best of Both Worlds**: +- βœ… Virtualization flexibility from Proxmox +- βœ… Bare-metal routing performance from VyOS +- βœ… Declarative configuration from NixOS +- βœ… AI-powered automation and monitoring +- βœ… macOS development environment +- βœ… Full remote management via iDRAC + +--- + +## Architecture Design + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Dell PowerEdge R730 ORION β”‚ +β”‚ (CQ5QBM2 - 384GB RAM) β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ iDRAC Enterprise (192.168.1.2) β”‚ β”‚ +β”‚ β”‚ Redfish API - Full Remote Management β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Proxmox VE 8.x Hypervisor Layer β”‚ β”‚ +β”‚ β”‚ Management: 192.168.100.10:8006 β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ VM 200 β”‚ β”‚ VM 300 β”‚ β”‚ VM 100 β”‚ β”‚ +β”‚ β”‚ Router β”‚ β”‚ AI Agent β”‚ β”‚ macOS β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ Sequoia β”‚ β”‚ +β”‚ β”‚ NixOS+VyOS β”‚ β”‚ NixOS β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ 8 cores β”‚ β”‚ 4 cores β”‚ β”‚ 12 cores β”‚ β”‚ +β”‚ β”‚ 32GB β”‚ β”‚ 16GB β”‚ β”‚ 64GB β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ Services: β”‚ β”‚ Services: β”‚ β”‚ Purpose: β”‚ β”‚ +β”‚ β”‚ β€’ BGP β”‚ β”‚ β€’ AI Agent β”‚ β”‚ β€’ Dev Env β”‚ β”‚ +β”‚ β”‚ β€’ Firewall β”‚ β”‚ β€’ Prometh. β”‚ β”‚ β€’ Testing β”‚ β”‚ +β”‚ β”‚ β€’ DHCP/DNS β”‚ β”‚ β€’ Grafana β”‚ β”‚ β€’ Build β”‚ β”‚ +β”‚ β”‚ β€’ NAT β”‚ β”‚ β€’ Alerts β”‚ β”‚ β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ β”‚ β”‚ + β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β” β”Œβ”€β”€β”€β–Όβ”€β”€β”€β” β”Œβ”€β”€β”€β–Όβ”€β”€β”€β” + β”‚ WAN β”‚ β”‚ LAN β”‚ β”‚ Guest β”‚ + β”‚ Telus β”‚ β”‚ .100 β”‚ β”‚ .200 β”‚ + β”‚ 10GbE β”‚ β”‚10GbE β”‚ β”‚ 10GbE β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +--- + +## Key Features + +### 1. **Hybrid Virtualization Model** + +- **Proxmox VE 8.x**: Enterprise-grade hypervisor + - Web-based management UI + - Live migration support + - Snapshot and backup capabilities + - LXC container support + +- **NixOS VMs**: Declarative, reproducible configurations + - Atomic updates and rollbacks + - Immutable infrastructure + - Easy version control + +### 2. **High-Performance Routing** + +- **VyOS Router** (VM 200): + - Dedicated routing VM with minimal overhead + - BIRD2 for BGP routing + - nftables for high-performance firewalling + - Hardware-accelerated networking (virtio) + +### 3. **AI-Powered Monitoring** + +- **Autonomous Agent** (VM 300): + - Real-time network health monitoring + - Automatic issue detection + - Self-healing capabilities + - Predictive analysis + +### 4. **macOS Development** + +- **macOS Sequoia** (VM 100): + - Full macOS 15 support via OSX-PROXMOX + - 12 cores / 64GB RAM + - Metal GPU acceleration + - OpenCore bootloader + +### 5. **Full Automation** + +- **iDRAC Redfish API**: + - Remote power management + - Boot configuration + - Hardware monitoring + - Virtual media mounting + +--- + +## Hardware Specifications + +### Dell PowerEdge R730 (CQ5QBM2) + +| Component | Specification | +|-----------|---------------| +| **CPUs** | 2x Intel Xeon E5-2690 v4 (14 cores, 2.6GHz) | +| **Total Cores** | 28 physical / 56 threads | +| **RAM** | 384GB DDR4-2400 (12x 32GB Samsung) | +| **Storage Controller** | PERC H730 Mini (RAID 10) | +| **Network** | 8x NICs (4x 10GbE + 4x 1GbE) | +| **Power** | Dual 750W redundant PSUs | +| **Management** | iDRAC 8 Enterprise | + +### Network Interface Mapping + +| Interface | MAC | Speed | Purpose | +|-----------|-----|-------|---------| +| eno1 | D0:94:66:24:96:7C | 1GbE | Proxmox Management | +| eno2 | D0:94:66:24:96:7D | 1GbE | Reserved | +| eno3 | D0:94:66:24:96:7E | 10GbE | WAN (Telus Fiber) β†’ vmbr0 | +| eno4 | D0:94:66:24:96:80 | 10GbE | LAN (Internal) β†’ vmbr1 | +| eno5 | - | 10GbE | macOS Network β†’ vmbr2 | +| eno6 | - | 10GbE | Storage Network β†’ vmbr3 | +| enp3s0f0 | - | 10GbE | Available (Slot 3) | +| enp3s0f1 | - | 10GbE | Available (Slot 3) | + +--- + +## Network Architecture + +### IP Addressing Scheme + +#### WAN (Telus Fiber) +- **Interface**: vmbr0 (eno3) +- **IPv4**: DHCP from Telus +- **IPv6**: 2602:F674::/48 (prefix delegation) +- **BGP AS**: 394955 +- **Peers**: + - 206.75.1.127 (Primary - AS 6939) + - 206.75.1.47 (Secondary - AS 6939) + - 206.75.1.48 (Tertiary - AS 6939) + +#### LAN (Internal Network) +- **Interface**: vmbr1 (eno4) +- **IPv4**: 192.168.100.0/24 +- **Gateway**: 192.168.100.1 (Router VM) +- **DHCP Range**: 192.168.100.100 - 192.168.100.200 +- **DNS**: 192.168.100.1 (Unbound) +- **IPv6**: 2602:F674:1000::/64 + +#### Guest Network +- **Interface**: vmbr2 +- **IPv4**: 192.168.200.0/24 +- **Gateway**: 192.168.200.1 (Router VM) +- **Isolation**: Restricted to WAN only + +#### Management Network +- **IPv4**: 192.168.1.0/24 +- **Proxmox**: 192.168.1.10 (eno1) +- **iDRAC**: 192.168.1.2 +- **Router**: 192.168.1.1 (eth3) + +### Network Bridges (Proxmox) + +``` +vmbr0: WAN Bridge + - Physical: eno3 (10GbE) + - Purpose: Router VM WAN interface + - VLAN: Aware (for future VLANs) + +vmbr1: LAN Bridge + - Physical: eno4 (10GbE) + - Purpose: Internal network for VMs + - IP: 192.168.100.1/24 + +vmbr2: macOS Bridge + - Physical: eno5 (10GbE) + - Purpose: macOS VM network + +vmbr3: Storage Bridge + - Physical: eno6 (10GbE) + - Purpose: NFS/iSCSI storage network +``` + +--- + +## Virtual Machines + +### VM 200: ORION-Router + +**Operating System**: NixOS 24.11 + VyOS + +**Resources**: +- CPUs: 8 cores (host passthrough) +- RAM: 32GB +- Disk: 50GB +- NICs: 4x virtio (WAN, LAN, Guest, Mgmt) + +**Services**: +- **BIRD2**: BGP routing (AS 394955) +- **VyOS**: Advanced routing and firewall +- **Unbound**: DNS resolver (192.168.100.1) +- **Kea DHCP**: DHCP server +- **nftables**: High-performance firewall +- **Prometheus Node Exporter**: Metrics + +**Network Interfaces**: +- eth0: WAN (vmbr0) - DHCP from Telus +- eth1: LAN (vmbr1) - 192.168.100.1/24 +- eth2: Guest (vmbr2) - 192.168.200.1/24 +- eth3: Mgmt (vmbr1) - 192.168.1.1/24 + +**Configuration**: `vm-configs/router-vm/configuration.nix` + +**Features**: +- Stateful firewall with nftables +- NAT for LAN and Guest networks +- DHCPv6 prefix delegation +- BGP route announcements +- DNS over TLS forwarding +- Automatic failover between BGP peers + +--- + +### VM 300: ORION-AI-Agent + +**Operating System**: NixOS 24.11 + +**Resources**: +- CPUs: 4 cores (host passthrough) +- RAM: 16GB +- Disk: 50GB +- NICs: 1x virtio (LAN) + +**Services**: +- **Autonomous Agent**: Python-based monitoring +- **Prometheus**: Metrics collection (port 9090) +- **Grafana**: Visualization (port 3000) +- **Alert Manager**: Alert routing +- **Node Exporter**: System metrics + +**Network**: +- IP: 192.168.100.20/24 +- Gateway: 192.168.100.1 + +**Configuration**: `vm-configs/ai-agent-vm/configuration.nix` + +**AI Agent Capabilities**: +- Real-time network monitoring +- BGP session health checks +- Bandwidth analysis +- Anomaly detection +- Automatic remediation: + - Restart BGP if all sessions down + - Alert on high CPU/memory + - Detect routing loops +- Hourly status reports + +**Monitoring Targets**: +- Router VM (192.168.100.1:9100) +- AI Agent itself (localhost:9100) +- Proxmox host (192.168.100.10:9100) + +**Dashboards**: http://192.168.100.20:3000 +- Default credentials: admin / orion2025 (change immediately!) + +--- + +### VM 100: HACK-Sequoia-01 + +**Operating System**: macOS Sequoia 15 + +**Resources**: +- CPUs: 12 cores (Haswell-noTSX) +- RAM: 64GB +- Disk: 256GB +- NICs: 1x virtio (macOS network) + +**Configuration**: OpenCore 1.0.4 +- SMBIOS: iMacPro1,1 +- SIP: Enabled +- Secure Boot: Default + +**Purpose**: macOS development environment + +**Setup**: Refer to existing `deploy-orion.sh` for detailed macOS VM creation + +--- + +## Deployment Process + +### Prerequisites + +1. **Hardware**: + - Dell R730 powered on and accessible + - iDRAC configured (IP: 192.168.1.2) + - Network cables connected + +2. **Software**: + - Python 3.x with requests library + - Proxmox VE ISO downloaded + - NixOS minimal ISO downloaded + - SSH access configured + +3. **Network**: + - Management network (192.168.1.0/24) configured + - Internet access for downloads + +### Deployment Steps + +#### Step 1: Run Automated Deployment + +```bash +# Clone repository +git clone +cd luci-macOSX-PROXMOX + +# Install Python dependencies +pip3 install requests + +# Run hybrid deployment +python3 deploy-orion-hybrid.py +``` + +The deployment wizard will guide you through: +1. βœ… Prerequisites check +2. βœ… iDRAC configuration +3. βœ… Proxmox installation +4. βœ… Network bridge setup +5. βœ… Router VM creation +6. βœ… macOS VM creation +7. βœ… AI Agent VM creation +8. βœ… Monitoring setup +9. βœ… Verification + +#### Step 2: Install Proxmox VE + +1. Mount Proxmox ISO via iDRAC virtual media +2. Boot system from CD +3. Follow installer: + - Hostname: `orion-pve.local` + - IP: `192.168.100.10/24` + - Gateway: `192.168.100.1` + - DNS: `1.1.1.1` +4. Access web UI: https://192.168.100.10:8006 + +#### Step 3: Configure Network Bridges + +In Proxmox web UI: +1. Navigate to: Datacenter β†’ Node β†’ System β†’ Network +2. Create bridges: + - vmbr0: eno3 (WAN) + - vmbr1: eno4 (LAN) + - vmbr2: eno5 (macOS) + - vmbr3: eno6 (Storage) +3. Apply configuration and reboot + +#### Step 4: Create Router VM + +```bash +# Create VM +qm create 200 \ + --name ORION-Router \ + --cores 8 \ + --memory 32768 \ + --net0 virtio,bridge=vmbr0 \ + --net1 virtio,bridge=vmbr1 \ + --net2 virtio,bridge=vmbr2 \ + --net3 virtio,bridge=vmbr1 \ + --scsi0 local-lvm:50 + +# Download NixOS ISO +wget -O /var/lib/vz/template/iso/nixos-minimal.iso \ + https://channels.nixos.org/nixos-24.11/latest-nixos-minimal-x86_64-linux.iso + +# Mount ISO and boot +qm set 200 --ide2 local:iso/nixos-minimal.iso,media=cdrom +qm start 200 + +# Open console and install NixOS +# Copy configuration from: vm-configs/router-vm/configuration.nix +``` + +#### Step 5: Create AI Agent VM + +```bash +# Create VM +qm create 300 \ + --name ORION-AI-Agent \ + --cores 4 \ + --memory 16384 \ + --net0 virtio,bridge=vmbr1 \ + --scsi0 local-lvm:50 + +# Mount NixOS ISO and install +# Copy configuration from: vm-configs/ai-agent-vm/configuration.nix +``` + +#### Step 6: Create macOS VM + +Refer to `deploy-orion.sh` for detailed macOS VM setup using OSX-PROXMOX. + +#### Step 7: Verification + +```bash +# Check VM status +qm list + +# Test router connectivity +ping -c 3 192.168.100.1 + +# Test BGP sessions +ssh admin@192.168.100.1 "birdc show protocols" + +# Access Grafana +firefox http://192.168.100.20:3000 + +# Test internet from LAN +ping -c 3 8.8.8.8 +``` + +--- + +## Monitoring & Management + +### Prometheus Metrics + +**Endpoint**: http://192.168.100.20:9090 + +**Targets**: +- Router: 192.168.100.1:9100 +- AI Agent: 192.168.100.20:9100 +- Proxmox: 192.168.100.10:9100 + +**Sample Queries**: +```promql +# WAN bandwidth (Mbps) +rate(node_network_receive_bytes_total{device="eth0",instance="192.168.100.1:9100"}[5m]) * 8 / 1000000 + +# CPU usage +100 - (avg by (instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) + +# Memory usage +(1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100 +``` + +### Grafana Dashboards + +**Access**: http://192.168.100.20:3000 +**Login**: admin / orion2025 + +**Pre-configured Dashboards**: +- ORION Network Overview +- Router Performance +- BGP Session Status +- Bandwidth Analysis +- System Resources + +### AI Agent Status + +```bash +# Check agent status +ssh admin@192.168.100.20 "systemctl status orion-agent" + +# View logs +ssh admin@192.168.100.20 "journalctl -u orion-agent -f" + +# View alerts +ssh admin@192.168.100.20 "tail -f /var/log/orion-agent.log" +``` + +### iDRAC Management + +**Access**: https://192.168.1.2 +**Login**: root / calvin + +**Python CLI**: +```bash +# Power on +python3 deploy-orion-hybrid.py power-on + +# Power off +python3 deploy-orion-hybrid.py power-off + +# Reboot +python3 deploy-orion-hybrid.py reboot + +# Status +python3 deploy-orion-hybrid.py status +``` + +--- + +## Troubleshooting + +### Router VM Issues + +#### BGP Sessions Not Establishing + +```bash +# Check BGP status +ssh admin@192.168.100.1 "birdc show protocols all" + +# Check firewall +ssh admin@192.168.100.1 "nft list ruleset | grep 179" + +# Test connectivity to BGP peers +ssh admin@192.168.100.1 "ping -c 3 206.75.1.127" + +# Restart BIRD +ssh admin@192.168.100.1 "sudo systemctl restart bird2" +``` + +#### DHCP Not Working + +```bash +# Check Kea DHCP status +ssh admin@192.168.100.1 "systemctl status kea-dhcp4" + +# View DHCP leases +ssh admin@192.168.100.1 "cat /var/lib/kea/dhcp4.leases" + +# Restart DHCP +ssh admin@192.168.100.1 "sudo systemctl restart kea-dhcp4" +``` + +#### DNS Not Resolving + +```bash +# Check Unbound status +ssh admin@192.168.100.1 "systemctl status unbound" + +# Test DNS resolution +ssh admin@192.168.100.1 "dig @127.0.0.1 google.com" + +# View Unbound logs +ssh admin@192.168.100.1 "journalctl -u unbound -f" +``` + +### AI Agent Issues + +#### Agent Not Running + +```bash +# Check service status +ssh admin@192.168.100.20 "systemctl status orion-agent" + +# View recent logs +ssh admin@192.168.100.20 "journalctl -u orion-agent --since '10 minutes ago'" + +# Restart agent +ssh admin@192.168.100.20 "sudo systemctl restart orion-agent" +``` + +#### Prometheus Not Collecting Metrics + +```bash +# Check Prometheus targets +curl http://192.168.100.20:9090/api/v1/targets + +# Check Prometheus config +ssh admin@192.168.100.20 "systemctl status prometheus" + +# Restart Prometheus +ssh admin@192.168.100.20 "sudo systemctl restart prometheus" +``` + +### macOS VM Issues + +Refer to OSX-PROXMOX documentation and existing troubleshooting guides. + +### Network Performance Issues + +```bash +# Check interface status on router +ssh admin@192.168.100.1 "ip link show" + +# Monitor bandwidth +ssh admin@192.168.100.1 "iftop -i eth0" + +# Check for errors +ssh admin@192.168.100.1 "ip -s link show eth0" + +# Test throughput +iperf3 -s # on router +iperf3 -c 192.168.100.1 # from client +``` + +--- + +## Maintenance + +### Regular Tasks + +**Daily**: +- Check Grafana dashboards for anomalies +- Review AI agent alerts + +**Weekly**: +- Review BGP session uptime +- Check system resource usage +- Review firewall logs + +**Monthly**: +- Update NixOS VMs: `nixos-rebuild switch --upgrade` +- Update Proxmox: `apt update && apt upgrade` +- Review and rotate logs +- Test backup restore + +### Backup Strategy + +**Proxmox VZ Backup**: +```bash +# Backup all VMs +vzdump --all --mode snapshot --compress zstd + +# Backup specific VM +vzdump 200 --mode snapshot --compress zstd +``` + +**NixOS Configuration Backup**: +```bash +# Configurations are in Git - commit regularly +git add vm-configs/ +git commit -m "Update VM configurations" +git push +``` + +--- + +## Support & Documentation + +- **Main Documentation**: `DELL_R730_ORION_PROXMOX_INTEGRATION.md` +- **Quickstart Guide**: `ORION_QUICKSTART.md` +- **Configuration**: `orion-config.json` +- **Deployment Script**: `deploy-orion-hybrid.py` +- **Legacy Script**: `deploy-orion.sh` + +--- + +## Version History + +- **2.0.0-hybrid** (2025-01-20): Hybrid architecture with NixOS router and AI agent +- **1.0.0** (2025-01-19): Initial Proxmox + pfSense deployment + +--- + +**End of Documentation** diff --git a/ORION_QUICKSTART.md b/docs/reference/ORION_QUICKSTART.md similarity index 100% rename from ORION_QUICKSTART.md rename to docs/reference/ORION_QUICKSTART.md diff --git a/docs/reference/QUICKSTART_HYBRID.md b/docs/reference/QUICKSTART_HYBRID.md new file mode 100644 index 0000000..cd4eb29 --- /dev/null +++ b/docs/reference/QUICKSTART_HYBRID.md @@ -0,0 +1,442 @@ +# ORION Hybrid Deployment - Quick Start Guide + +Get your Dell R730 ORION system up and running in minutes with full automation! + +## What You'll Get + +βœ… Proxmox VE hypervisor with web management +βœ… High-performance NixOS + VyOS router with BGP +βœ… AI-powered autonomous network monitoring +βœ… macOS Sequoia development environment +βœ… Full remote management via iDRAC +βœ… Prometheus + Grafana monitoring dashboards + +## Prerequisites + +Before starting, ensure you have: + +- [x] Dell R730 powered on and network-accessible +- [x] iDRAC configured at 192.168.1.2 +- [x] Management network (192.168.1.0/24) connected +- [x] Internet connection available +- [x] Python 3.x installed on your workstation + +## 5-Minute Quick Start + +### Step 1: Clone Repository + +```bash +git clone https://github.com/luci-digital/luci-macOSX-PROXMOX.git +cd luci-macOSX-PROXMOX +``` + +### Step 2: Install Dependencies + +```bash +pip3 install requests +``` + +### Step 3: Run Automated Deployment + +```bash +python3 deploy-orion-hybrid.py +``` + +The deployment wizard will: +1. βœ… Check prerequisites +2. βœ… Configure iDRAC +3. βœ… Guide you through Proxmox installation +4. βœ… Setup network bridges +5. βœ… Create and configure VMs +6. βœ… Setup monitoring + +### Step 4: Install Proxmox (Manual Step) + +When prompted by the wizard: + +1. Download Proxmox VE ISO: https://www.proxmox.com/en/downloads +2. Open iDRAC web console: https://192.168.1.2 +3. Mount ISO via Virtual Media +4. Reboot system and follow installer: + - Hostname: `orion-pve.local` + - IP: `192.168.100.10/24` + - Gateway: `192.168.100.1` + - DNS: `1.1.1.1` +5. Access Proxmox: https://192.168.100.10:8006 + +### Step 5: Access Your System + +**Proxmox Management**: +- URL: https://192.168.100.10:8006 +- Login: root / (password set during install) + +**Grafana Dashboards**: +- URL: http://192.168.100.20:3000 +- Login: admin / orion2025 (change this!) + +**iDRAC Console**: +- URL: https://192.168.1.2 +- Login: root / calvin + +## Architecture Overview + +``` +Dell R730 ORION +β”œβ”€ Proxmox VE (192.168.100.10) +β”‚ β”œβ”€ VM 200: Router (NixOS + VyOS) +β”‚ β”‚ └─ 192.168.100.1 (Gateway/DNS/DHCP) +β”‚ β”œβ”€ VM 300: AI Agent +β”‚ β”‚ └─ 192.168.100.20 (Monitoring) +β”‚ └─ VM 100: macOS Sequoia +β”‚ └─ 192.168.100.X (Development) +└─ iDRAC (192.168.1.2) +``` + +## Network Configuration + +### WAN (Internet) +- Interface: 10GbE (eno3/vmbr0) +- Provider: Telus Fiber +- IPv4: DHCP +- IPv6: 2602:F674::/48 +- BGP AS: 394955 + +### LAN (Internal) +- Interface: 10GbE (eno4/vmbr1) +- Network: 192.168.100.0/24 +- Gateway: 192.168.100.1 (Router VM) +- DHCP: .100 - .200 + +## Essential Commands + +### iDRAC Control + +```bash +# Check system status +python3 deploy-orion-hybrid.py status + +# Power on +python3 deploy-orion-hybrid.py power-on + +# Reboot +python3 deploy-orion-hybrid.py reboot +``` + +### VM Management (Proxmox) + +```bash +# List VMs +qm list + +# Start router +qm start 200 + +# Stop router (graceful) +qm shutdown 200 + +# Console access +qm console 200 +``` + +### Router Management + +```bash +# SSH to router +ssh admin@192.168.100.1 + +# Check BGP status +birdc show protocols + +# Check firewall +nft list ruleset + +# View DHCP leases +cat /var/lib/kea/dhcp4.leases +``` + +### Monitoring + +```bash +# Access Grafana +firefox http://192.168.100.20:3000 + +# Query Prometheus +curl 'http://192.168.100.20:9090/api/v1/query?query=up' + +# Check AI agent +ssh admin@192.168.100.20 "systemctl status orion-agent" +``` + +## VM Creation Guide + +### Create Router VM (200) + +```bash +# Create VM in Proxmox +qm create 200 \ + --name ORION-Router \ + --cores 8 \ + --memory 32768 \ + --net0 virtio,bridge=vmbr0 \ + --net1 virtio,bridge=vmbr1 \ + --net2 virtio,bridge=vmbr2 \ + --net3 virtio,bridge=vmbr1 \ + --scsi0 local-lvm:50 \ + --boot order=scsi0 + +# Download NixOS ISO (if not already done) +wget -P /var/lib/vz/template/iso/ \ + https://channels.nixos.org/nixos-24.11/latest-nixos-minimal-x86_64-linux.iso + +# Attach ISO +qm set 200 --ide2 local:iso/nixos-minimal-x86_64-linux.iso,media=cdrom + +# Start VM +qm start 200 + +# Open console +qm console 200 +``` + +In NixOS installer: +```bash +# Partition disk +parted /dev/sda -- mklabel gpt +parted /dev/sda -- mkpart ESP fat32 1MiB 512MiB +parted /dev/sda -- set 1 esp on +parted /dev/sda -- mkpart primary 512MiB 100% + +# Format +mkfs.fat -F 32 -n boot /dev/sda1 +mkfs.ext4 -L nixos /dev/sda2 + +# Mount +mount /dev/disk/by-label/nixos /mnt +mkdir -p /mnt/boot +mount /dev/disk/by-label/boot /mnt/boot + +# Generate config +nixos-generate-config --root /mnt + +# Download our config (from another machine) +# Upload vm-configs/router-vm/configuration.nix to /mnt/etc/nixos/ + +# Install +nixos-install + +# Reboot +reboot +``` + +### Create AI Agent VM (300) + +```bash +# Create VM +qm create 300 \ + --name ORION-AI-Agent \ + --cores 4 \ + --memory 16384 \ + --net0 virtio,bridge=vmbr1 \ + --scsi0 local-lvm:50 \ + --boot order=scsi0 + +# Attach NixOS ISO +qm set 300 --ide2 local:iso/nixos-minimal-x86_64-linux.iso,media=cdrom + +# Start and install (same process as router) +qm start 300 + +# Use configuration from: vm-configs/ai-agent-vm/ +``` + +### Create macOS VM (100) + +Refer to the existing `deploy-orion.sh` script for detailed macOS VM setup. + +## Network Bridge Setup + +In Proxmox web UI (System β†’ Network): + +**vmbr0** (WAN): +- Bridge ports: eno3 +- Comment: WAN - Telus Fiber + +**vmbr1** (LAN): +- Bridge ports: eno4 +- IPv4: 192.168.100.1/24 +- Comment: LAN - Internal Network + +**vmbr2** (Guest): +- Bridge ports: eno5 +- Comment: Guest Network + +**vmbr3** (Storage): +- Bridge ports: eno6 +- Comment: Storage Network + +Apply configuration and reboot Proxmox if needed. + +## Verification Checklist + +After deployment, verify everything works: + +```bash +# βœ“ iDRAC accessible +curl -k https://192.168.1.2 + +# βœ“ Proxmox web UI accessible +curl -k https://192.168.100.10:8006 + +# βœ“ Router responding +ping -c 3 192.168.100.1 + +# βœ“ DNS working +dig @192.168.100.1 google.com + +# βœ“ BGP sessions up +ssh admin@192.168.100.1 "birdc show protocols" | grep Established + +# βœ“ AI agent running +ssh admin@192.168.100.20 "systemctl is-active orion-agent" + +# βœ“ Prometheus collecting metrics +curl http://192.168.100.20:9090/api/v1/targets | jq '.data.activeTargets[] | select(.health == "up")' + +# βœ“ Grafana accessible +curl http://192.168.100.20:3000/api/health + +# βœ“ Internet connectivity +ping -c 3 8.8.8.8 +``` + +## Troubleshooting + +### Router Not Accessible + +```bash +# Check VM is running +qm status 200 + +# Check console +qm console 200 + +# Verify network config in Proxmox +cat /etc/network/interfaces +``` + +### BGP Sessions Down + +```bash +# SSH to router +ssh admin@192.168.100.1 + +# Check BIRD status +birdc show protocols all + +# Check WAN interface has IP +ip addr show eth0 + +# Test connectivity to BGP peers +ping -c 3 206.75.1.127 + +# Restart BIRD +sudo systemctl restart bird2 +``` + +### No Internet from LAN + +```bash +# Check NAT is configured +ssh admin@192.168.100.1 "nft list table ip nat" + +# Check routing +ssh admin@192.168.100.1 "ip route show" + +# Check DNS +dig @192.168.100.1 google.com + +# Test from Proxmox host +ping -c 3 8.8.8.8 +``` + +### Monitoring Not Working + +```bash +# Check Prometheus targets +curl http://192.168.100.20:9090/api/v1/targets | jq + +# Check if router exporter is running +ssh admin@192.168.100.1 "systemctl status prometheus-node-exporter" + +# Check AI agent logs +ssh admin@192.168.100.20 "journalctl -u orion-agent -n 50" + +# Restart services +ssh admin@192.168.100.20 "sudo systemctl restart prometheus grafana" +``` + +## Next Steps + +Once your system is running: + +1. **Secure Your System**: + - Change default passwords + - Configure SSH keys + - Review firewall rules + +2. **Customize Configuration**: + - Edit `vm-configs/router-vm/configuration.nix` for router changes + - Edit `vm-configs/ai-agent-vm/configuration.nix` for monitoring changes + - Rebuild with: `nixos-rebuild switch` + +3. **Add More VMs**: + - Create VMs in Proxmox web UI + - Attach to vmbr1 for LAN access + - Configure DHCP or static IPs + +4. **Setup Backups**: + - Configure Proxmox backup schedule + - Export VM configurations to Git + +5. **Explore Monitoring**: + - Create custom Grafana dashboards + - Setup alert notifications + - Configure AI agent behaviors + +## Resource Allocation + +| Component | Cores | RAM | Purpose | +|-----------|-------|-----|---------| +| Proxmox Host | 4 | 16GB | Hypervisor | +| Router VM | 8 | 32GB | Routing/BGP/Firewall | +| AI Agent VM | 4 | 16GB | Monitoring | +| macOS VM | 12 | 64GB | Development | +| Available | 28 | 256GB | Future VMs/containers | +| **Total** | **56** | **384GB** | | + +## Useful Links + +- **Proxmox Documentation**: https://pve.proxmox.com/pve-docs/ +- **NixOS Manual**: https://nixos.org/manual/nixos/stable/ +- **VyOS Documentation**: https://docs.vyos.io/ +- **BIRD Routing**: https://bird.network.cz/ +- **Prometheus**: https://prometheus.io/docs/ +- **Grafana**: https://grafana.com/docs/ + +## Support + +For detailed documentation: +- Full architecture: `ORION_HYBRID_ARCHITECTURE.md` +- VM configurations: `vm-configs/README.md` +- Original Proxmox setup: `DELL_R730_ORION_PROXMOX_INTEGRATION.md` + +For issues: +- Check system logs: `journalctl -xe` +- Review VM console output +- Consult troubleshooting sections + +--- + +**Ready to deploy? Run `python3 deploy-orion-hybrid.py` to get started!** + +Last Updated: 2025-01-20 diff --git a/orion-config.json b/orion-config.json index 1f42704..6d76608 100644 --- a/orion-config.json +++ b/orion-config.json @@ -169,7 +169,8 @@ "router": { "id": 200, "name": "ORION-Router", - "os": "pfSense CE 2.7.2", + "os": "NixOS 24.11 + VyOS", + "description": "High-performance router with VyOS, BGP, and nftables firewall", "resources": { "cpu": { "cores": 8, @@ -185,30 +186,79 @@ "id": "net0", "bridge": "vmbr0", "model": "virtio", - "purpose": "WAN" + "purpose": "WAN (Telus Fiber)", + "mac": "auto" }, { "id": "net1", "bridge": "vmbr1", "model": "virtio", - "purpose": "LAN" + "purpose": "LAN (192.168.100.0/24)", + "mac": "auto" }, { "id": "net2", "bridge": "vmbr2", "model": "virtio", - "purpose": "OPT1" + "purpose": "Guest Network (192.168.200.0/24)", + "mac": "auto" }, { "id": "net3", - "bridge": "vmbr3", + "bridge": "vmbr1", "model": "virtio", - "purpose": "OPT2" + "purpose": "Management (192.168.1.0/24)", + "mac": "auto" } ], + "services": [ + "BIRD2 BGP (AS 394955)", + "VyOS Routing", + "Unbound DNS (192.168.100.1)", + "Kea DHCP Server", + "nftables Firewall", + "Prometheus Node Exporter" + ], "autostart": true, "startupOrder": 1, - "startupDelay": 30 + "startupDelay": 30, + "configPath": "vm-configs/router-vm/configuration.nix" + }, + "aiAgent": { + "id": 300, + "name": "ORION-AI-Agent", + "os": "NixOS 24.11", + "description": "Autonomous network monitoring and management agent", + "resources": { + "cpu": { + "cores": 4, + "type": "host", + "sockets": 1, + "numa": false + }, + "memory": "16GB", + "storage": "50GB" + }, + "network": [ + { + "id": "net0", + "bridge": "vmbr1", + "model": "virtio", + "purpose": "LAN (192.168.100.20)", + "mac": "auto" + } + ], + "services": [ + "Autonomous Network Agent (Python)", + "Prometheus Server (port 9090)", + "Grafana Dashboard (port 3000)", + "Alert Manager", + "Prometheus Node Exporter" + ], + "autostart": true, + "startupOrder": 2, + "startupDelay": 15, + "configPath": "vm-configs/ai-agent-vm/configuration.nix" }, "macOS": { "id": 100, @@ -251,7 +301,12 @@ "routerVM": { "cpuCores": 8, "memory": "32GB", - "purpose": "Network routing, BGP, firewall" + "purpose": "NixOS + VyOS routing, BGP, firewall, DHCP, DNS" + }, + "aiAgentVM": { + "cpuCores": 4, + "memory": "16GB", + "purpose": "Autonomous monitoring, Prometheus, Grafana" }, "macOSPrimary": { "cpuCores": 12, @@ -264,13 +319,14 @@ "purpose": "macOS Sonoma testing (optional)" }, "developmentVMs": { - "cpuCores": 24, - "memory": "240GB", + "cpuCores": 20, + "memory": "224GB", "purpose": "Linux/Windows VMs, containers, CI/CD" }, "totalAllocated": { "cpuCores": 56, - "memory": "384GB" + "memory": "384GB", + "note": "Includes Router VM (8), AI Agent VM (4), macOS Primary (12), Proxmox (4), Development (20+)" } }, "monitoring": { @@ -331,10 +387,24 @@ ] }, "deployment": { - "version": "1.0.0", + "version": "2.0.0-hybrid", + "architecture": "Proxmox + NixOS/VyOS Router + AI Agent + macOS", "deployedDate": "", - "deployedBy": "ORION Automation Script", - "lastModified": "2025-01-19", - "status": "pending" + "deployedBy": "ORION Hybrid Deployment System", + "lastModified": "2025-01-20", + "status": "pending", + "features": [ + "Full iDRAC Redfish API automation", + "Proxmox VE 8.x hypervisor", + "NixOS 24.11 + VyOS router VM (replaces pfSense)", + "Autonomous AI network agent", + "macOS Sequoia support via OSX-PROXMOX", + "BGP routing with BIRD2 (AS 394955)", + "Prometheus + Grafana monitoring", + "Declarative NixOS configurations", + "Self-healing network automation" + ], + "deploymentScript": "deploy-orion-hybrid.py", + "legacyScript": "deploy-orion.sh" } } diff --git a/router-configs/bird2/bird6.conf b/router-configs/bird2/bird6.conf new file mode 100644 index 0000000..e41d4d6 --- /dev/null +++ b/router-configs/bird2/bird6.conf @@ -0,0 +1,264 @@ +# BIRD2 IPv6 Configuration for ORION Router (AS394955) +# Dell R730 - Router VM 200 +# IPv6 Prefix: 2602:F674::/48 +# Generated: 2025-01-22 + +log syslog all; +debug protocols { states, routes, filters, interfaces }; + +# Router ID (use IPv4 address as ID for both IPv4 and IPv6) +router id 100.64.0.1; + +# Device protocol - learn interface information +protocol device { + scan time 10; +} + +# Direct protocol - learn directly connected networks +protocol direct { + ipv6; + interface "eth0", "eth1", "eth2", "eth3"; +} + +# Kernel protocol - sync routes with kernel routing table +protocol kernel kernel6 { + ipv6 { + import none; + export all; + }; + learn; + persist; + scan time 20; + metric 100; +} + +# Static routes +protocol static static6 { + ipv6; + + # Announce our prefix (blackhole to prevent loops) + route 2602:F674::/48 reject; + + # Specific subnets (will be directly connected) + # These are learned via the direct protocol, but we keep them for reference + # route 2602:F674:1000::/64 via "eth1"; # LAN + # route 2602:F674:2000::/64 via "eth2"; # Guest + # route 2602:F674:3000::/64 via "eth3"; # Management +} + +# ============================================================================ +# FILTER DEFINITIONS +# ============================================================================ + +# Outbound filter - what we announce to Telus +filter bgp_out_ipv6 { + # Only announce our allocated prefix and more specific subnets + if net ~ [ 2602:F674::/48{48,64} ] then { + # Prepend our AS to the path + bgp_path.prepend(394955); + + # Set communities (optional - adjust based on Telus requirements) + # bgp_community.add((394955, 100)); # Example community + + accept; + } + + # Reject everything else + reject; +} + +# Inbound filter - what we accept from Telus +filter bgp_in_ipv6 { + # Accept default route + if net = ::/0 then { + accept; + } + + # Accept global unicast addresses (2000::/3) + if net ~ [ 2000::/3{0,64} ] then { + accept; + } + + # Reject our own prefix (should never receive this) + if net ~ [ 2602:F674::/48+ ] then { + print "Rejecting our own prefix from peer: ", net; + reject; + } + + # Reject bogon prefixes + if net ~ [ + ::/0{0,7}, # Too short + ::/8+, # Loopback, etc. + 100::/8+, # Discard + 2001::/32+, # TEREDO + 2001:2::/48+, # Benchmarking + 2001:10::/28+, # ORCHID + 2001:db8::/32+, # Documentation + 2002::/16+, # 6to4 + 3ffe::/16+, # Old 6bone + fc00::/7+, # ULA + fe80::/10+, # Link-local + fec0::/10+, # Old site-local + ff00::/8+ # Multicast + ] then { + print "Rejecting bogon prefix: ", net; + reject; + } + + # Accept everything else + accept; +} + +# ============================================================================ +# BGP TEMPLATE FOR TELUS PEERS +# ============================================================================ + +template bgp telus_ipv6 { + local as 394955; + + ipv6 { + import filter bgp_in_ipv6; + export filter bgp_out_ipv6; + next hop self; + }; + + # BGP timers + hold time 90; + keepalive time 30; + connect retry time 120; + connect delay time 5; + error wait time 60,300; + + # Enable graceful restart + graceful restart on; + graceful restart time 120; + + # Path selection + path metric 1; + + # Disable MED comparison for multiple paths + igp metric on; +} + +# ============================================================================ +# TELUS BGP PEERS (IPv6) +# ============================================================================ + +# Note: Replace these IPv6 addresses with actual Telus gateway addresses +# The addresses below are examples based on your IPv6 prefix allocation + +# Telus BGP Peer 1 (Primary) +protocol bgp telus_peer1_v6 from telus_ipv6 { + description "Telus Gateway 1 - IPv6 (Primary)"; + + # TODO: Replace with actual Telus IPv6 gateway address + # This is a placeholder - get actual address from Telus + neighbor fe80::1 % 'eth0' as 6939; + # Or if they provide global address: + # neighbor 2602:F674:0000::ffff as 6939; + + source address 2602:F674:0000::1; + + ipv6 { + import filter { + # Prefer this peer (highest local preference) + bgp_local_pref = 150; + + # Apply inbound filter + if bgp_in_ipv6() then accept; + reject; + }; + export filter bgp_out_ipv6; + }; + + # Prefer routes from this peer + preference 100; +} + +# Telus BGP Peer 2 (Secondary) +protocol bgp telus_peer2_v6 from telus_ipv6 { + description "Telus Gateway 2 - IPv6 (Secondary)"; + + # TODO: Replace with actual Telus IPv6 gateway address + neighbor fe80::2 % 'eth0' as 6939; + # Or: neighbor 2602:F674:0000::fffe as 6939; + + source address 2602:F674:0000::1; + + ipv6 { + import filter { + # Lower preference than peer1 + bgp_local_pref = 100; + + if bgp_in_ipv6() then accept; + reject; + }; + export filter bgp_out_ipv6; + }; + + # Lower preference than peer 1 + preference 90; +} + +# Telus BGP Peer 3 (Tertiary) +protocol bgp telus_peer3_v6 from telus_ipv6 { + description "Telus Gateway 3 - IPv6 (Tertiary)"; + + # TODO: Replace with actual Telus IPv6 gateway address + neighbor fe80::3 % 'eth0' as 6939; + # Or: neighbor 2602:F674:0000::fffd as 6939; + + source address 2602:F674:0000::1; + + ipv6 { + import filter { + # Lowest preference + bgp_local_pref = 50; + + if bgp_in_ipv6() then accept; + reject; + }; + export filter bgp_out_ipv6; + }; + + # Lowest preference + preference 80; +} + +# ============================================================================ +# BFD (Bidirectional Forwarding Detection) - Optional +# ============================================================================ +# Uncomment if Telus supports BFD for faster failure detection + +# protocol bfd { +# interface "eth0" { +# min rx interval 100 ms; +# min tx interval 100 ms; +# idle tx interval 300 ms; +# multiplier 5; +# }; +# } + +# ============================================================================ +# NOTES +# ============================================================================ +# +# 1. Update the neighbor addresses with actual Telus IPv6 gateway addresses +# These should be provided by Telus during BGP setup +# +# 2. If using link-local addresses (fe80::), you must specify the interface +# with % 'eth0' syntax +# +# 3. Verify BGP session status with: +# birdc6 show protocols +# birdc6 show protocols all telus_peer1_v6 +# +# 4. Check received routes: +# birdc6 show route protocol telus_peer1_v6 +# +# 5. Check announced routes: +# birdc6 show route export telus_peer1_v6 +# +# 6. Test filters: +# birdc6 eval 2602:F674::/48 +# diff --git a/router-configs/network/radvd.conf b/router-configs/network/radvd.conf new file mode 100644 index 0000000..9749c3d --- /dev/null +++ b/router-configs/network/radvd.conf @@ -0,0 +1,168 @@ +# Router Advertisement Daemon Configuration +# ORION Router VM 200 - IPv6 SLAAC +# Provides automatic IPv6 configuration for LAN clients + +# ============================================================================ +# LAN Interface (eth1) - 2602:F674:1000::/64 +# ============================================================================ +interface eth1 { + # Enable router advertisements + AdvSendAdvert on; + + # Minimum time between RAs (seconds) + MinRtrAdvInterval 3; + + # Maximum time between RAs (seconds) + MaxRtrAdvInterval 10; + + # Don't use DHCPv6 for address assignment (use SLAAC) + AdvManagedFlag off; + + # Use DHCPv6 for other configuration (DNS, NTP, etc.) + AdvOtherConfigFlag on; + + # Router lifetime (0 = not a default router, >0 = default router) + AdvDefaultLifetime 1800; + + # Preference for this router (low, medium, high) + AdvDefaultPreference high; + + # Link MTU + AdvLinkMTU 1500; + + # Reachable time (milliseconds) + AdvReachableTime 30000; + + # Retrans timer (milliseconds) + AdvRetransTimer 1000; + + # Current hop limit + AdvCurHopLimit 64; + + # Prefix for LAN + prefix 2602:F674:1000::/64 { + # Prefix is on-link + AdvOnLink on; + + # Clients can use SLAAC + AdvAutonomous on; + + # Include router address in RA + AdvRouterAddr on; + + # Valid lifetime (seconds) - how long prefix is valid + AdvValidLifetime 86400; # 24 hours + + # Preferred lifetime (seconds) - how long to prefer this prefix + AdvPreferredLifetime 43200; # 12 hours + }; + + # Recursive DNS Servers (Cloudflare) + RDNSS 2606:4700:4700::1111 2606:4700:4700::1001 { + AdvRDNSSLifetime 300; + }; + + # DNS Search List + DNSSL orion.local { + AdvDNSSLLifetime 300; + }; + + # Route Information (optional - for more specific routes) + # route 2602:F674::/48 { + # AdvRouteLifetime 1800; + # AdvRoutePreference high; + # }; +}; + +# ============================================================================ +# Guest Network Interface (eth2) - 2602:F674:2000::/64 +# ============================================================================ +interface eth2 { + AdvSendAdvert on; + + MinRtrAdvInterval 3; + MaxRtrAdvInterval 10; + + AdvManagedFlag off; + AdvOtherConfigFlag on; + + AdvDefaultLifetime 1800; + AdvDefaultPreference medium; # Lower than LAN + + AdvLinkMTU 1500; + + prefix 2602:F674:2000::/64 { + AdvOnLink on; + AdvAutonomous on; + AdvRouterAddr on; + AdvValidLifetime 86400; + AdvPreferredLifetime 43200; + }; + + # Use public DNS for guest network (no local DNS) + RDNSS 2606:4700:4700::1111 2606:4700:4700::1001 { + AdvRDNSSLifetime 300; + }; + + DNSSL guest.orion.local { + AdvDNSSLLifetime 300; + }; +}; + +# ============================================================================ +# Management Network Interface (eth3) - 2602:F674:3000::/64 +# ============================================================================ +interface eth3 { + AdvSendAdvert on; + + MinRtrAdvInterval 3; + MaxRtrAdvInterval 10; + + AdvManagedFlag off; + AdvOtherConfigFlag on; + + AdvDefaultLifetime 1800; + AdvDefaultPreference high; + + AdvLinkMTU 1500; + + prefix 2602:F674:3000::/64 { + AdvOnLink on; + AdvAutonomous on; + AdvRouterAddr on; + AdvValidLifetime 86400; + AdvPreferredLifetime 43200; + }; + + RDNSS 2606:4700:4700::1111 2606:4700:4700::1001 { + AdvRDNSSLifetime 300; + }; + + DNSSL mgmt.orion.local { + AdvDNSSLLifetime 300; + }; +}; + +# ============================================================================ +# NOTES +# ============================================================================ +# +# Test configuration: +# radvd -c /etc/radvd.conf -C +# +# Start daemon: +# systemctl start radvd +# +# Check status: +# systemctl status radvd +# +# Monitor RAs on client: +# rdisc6 eth0 +# tcpdump -i eth0 -n icmp6 +# +# Verify clients receive addresses: +# ip -6 addr show +# +# Expected client address format: +# 2602:f674:1000::/64 +# diff --git a/shell-config/.zshrc b/shell-config/.zshrc new file mode 100644 index 0000000..a05ff54 --- /dev/null +++ b/shell-config/.zshrc @@ -0,0 +1,252 @@ +# ORION Infrastructure - Zsh Configuration +# Optimized for infrastructure development with Oh My Zsh + Antigen + +# ============================================================================ +# Oh My Zsh Base Configuration +# ============================================================================ + +# Path to your Oh My Zsh installation +export ZSH="$HOME/.oh-my-zsh" + +# Theme +ZSH_THEME="agnoster" # Better theme for infrastructure work + +# Update behavior +zstyle ':omz:update' mode auto +zstyle ':omz:update' frequency 7 + +# Completion waiting dots +COMPLETION_WAITING_DOTS="true" + +# Command execution timestamp +HIST_STAMPS="yyyy-mm-dd" + +# Plugins from Oh My Zsh +plugins=( + git + docker + terraform + ansible + kubectl + helm + sudo + command-not-found + history + z + colored-man-pages + extract + web-search +) + +# Load Oh My Zsh +source $ZSH/oh-my-zsh.sh + +# ============================================================================ +# Antigen Configuration (zsh-users plugins) +# ============================================================================ + +# Load Antigen +source ~/antigen.zsh + +# Load oh-my-zsh library +antigen use oh-my-zsh + +# zsh-users plugins (https://github.com/orgs/zsh-users/repositories) +antigen bundle zsh-users/zsh-syntax-highlighting # Fish-like syntax highlighting +antigen bundle zsh-users/zsh-autosuggestions # Fish-like autosuggestions +antigen bundle zsh-users/zsh-completions # Additional completions +antigen bundle zsh-users/zsh-history-substring-search # Better history search + +# Apply Antigen configuration +antigen apply + +# ============================================================================ +# zsh-users Plugin Configuration +# ============================================================================ + +# zsh-autosuggestions +ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE="fg=#6c757d" +ZSH_AUTOSUGGEST_STRATEGY=(history completion) +ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE=20 + +# zsh-syntax-highlighting +typeset -A ZSH_HIGHLIGHT_STYLES +ZSH_HIGHLIGHT_STYLES[command]='fg=green,bold' +ZSH_HIGHLIGHT_STYLES[alias]='fg=cyan,bold' +ZSH_HIGHLIGHT_STYLES[builtin]='fg=yellow,bold' +ZSH_HIGHLIGHT_STYLES[function]='fg=blue,bold' +ZSH_HIGHLIGHT_STYLES[path]='fg=magenta' +ZSH_HIGHLIGHT_STYLES[error]='fg=red,bold' + +# zsh-history-substring-search (bind keys) +bindkey '^[[A' history-substring-search-up +bindkey '^[[B' history-substring-search-down +bindkey '^P' history-substring-search-up +bindkey '^N' history-substring-search-down + +# ============================================================================ +# Environment Variables for ORION +# ============================================================================ + +# ORION project root +export ORION_ROOT="/home/user/luci-macOSX-PROXMOX" + +# Terraform +export TF_LOG="INFO" +export TF_LOG_PATH="/tmp/terraform.log" + +# Ansible +export ANSIBLE_STDOUT_CALLBACK="yaml" +export ANSIBLE_FORCE_COLOR=true + +# Kubernetes +export KUBECONFIG="$HOME/.kube/config" + +# ============================================================================ +# Aliases for ORION Infrastructure +# ============================================================================ + +# Navigation +alias orion='cd $ORION_ROOT' +alias tf='cd $ORION_ROOT/terraform' +alias ans='cd $ORION_ROOT/ansible' +alias k8s='cd $ORION_ROOT/kubernetes' + +# Terraform shortcuts +alias tfi='terraform init' +alias tfp='terraform plan' +alias tfa='terraform apply' +alias tfd='terraform destroy' +alias tfo='terraform output' +alias tfs='terraform show' + +# Ansible shortcuts +alias ap='ansible-playbook' +alias ai='ansible-inventory' +alias ag='ansible-galaxy' + +# Kubectl shortcuts +alias k='kubectl' +alias kgp='kubectl get pods' +alias kgs='kubectl get svc' +alias kgn='kubectl get nodes' +alias kd='kubectl describe' +alias kl='kubectl logs' +alias ke='kubectl exec -it' + +# Docker shortcuts +alias d='docker' +alias dc='docker-compose' +alias dps='docker ps' +alias dim='docker images' + +# Make shortcuts +alias m='make' +alias mh='make help' +alias mdeploy='make deploy-full' +alias mverify='make verify' + +# Git shortcuts (enhanced) +alias gs='git status' +alias ga='git add' +alias gc='git commit' +alias gp='git push' +alias gl='git log --oneline --graph --decorate' +alias gd='git diff' + +# System shortcuts +alias ll='ls -lah' +alias la='ls -A' +alias l='ls -CF' +alias ..='cd ..' +alias ...='cd ../..' +alias ....='cd ../../..' + +# ============================================================================ +# Functions for ORION Infrastructure +# ============================================================================ + +# Quick deploy function +deploy() { + echo "πŸš€ Deploying ORION infrastructure..." + cd $ORION_ROOT + make deploy-full +} + +# Quick status check +orion-status() { + echo "πŸ“Š ORION Infrastructure Status" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + cd $ORION_ROOT + echo "\nπŸ“ Git Status:" + git status --short + echo "\nπŸ—οΈ Terraform Status:" + cd terraform && terraform show -json 2>/dev/null | jq -r '.values.root_module.resources[] | select(.type == "proxmox_vm_qemu") | "\(.values.name) (VM \(.values.vmid))"' || echo "No Terraform state" + echo "\n☸️ Kubernetes Status (if running):" + kubectl get nodes 2>/dev/null || echo "K8s cluster not accessible" +} + +# SSH to VMs +ssh-router() { + ssh root@192.168.100.1 +} + +ssh-coordinator() { + ssh root@192.168.100.30 +} + +ssh-netbox() { + ssh root@192.168.100.50 +} + +ssh-k8s-master() { + ssh root@192.168.100.60 +} + +# Proxmox helper +proxmox-vms() { + echo "πŸ“¦ Proxmox VMs:" + qm list 2>/dev/null || echo "Not connected to Proxmox host" +} + +# LXC helper +proxmox-lxc() { + echo "πŸ“¦ Proxmox LXC Containers:" + pct list 2>/dev/null || echo "Not connected to Proxmox host" +} + +# ============================================================================ +# User Configuration +# ============================================================================ + +# Preferred editor +export EDITOR='nano' +export VISUAL='nano' + +# Language environment +export LANG=en_US.UTF-8 + +# Compilation flags +export ARCHFLAGS="-arch x86_64" + +# History settings +HISTSIZE=10000 +SAVEHIST=10000 +setopt HIST_IGNORE_ALL_DUPS +setopt HIST_FIND_NO_DUPS +setopt SHARE_HISTORY + +# ============================================================================ +# Welcome Message +# ============================================================================ + +echo "╔═══════════════════════════════════════════════════════════════╗" +echo "β•‘ πŸš€ ORION Infrastructure Development Shell β•‘" +echo "β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•" +echo "" +echo "πŸ“˜ Main docs: ARCHITECTURE.md" +echo "πŸ”§ Deploy: make deploy-full or deploy" +echo "πŸ“Š Status: orion-status" +echo "πŸ’‘ Quick nav: orion, tf, ans, k8s" +echo "⚑ Shortcuts: m (make), k (kubectl), tf* (terraform)" +echo "" diff --git a/shell-config/README.md b/shell-config/README.md new file mode 100644 index 0000000..35858fa --- /dev/null +++ b/shell-config/README.md @@ -0,0 +1,131 @@ +# ORION Shell Configuration + +**Zsh + Oh My Zsh + Antigen + zsh-users plugins for infrastructure development** + +--- + +## πŸš€ Quick Start + +```bash +# Run the installation script +./install-zsh.sh + +# Start zsh +zsh + +# Or set as default shell (requires logout) +chsh -s $(which zsh) +``` + +--- + +## πŸ“¦ What's Included + +- **Zsh 5.9** - Modern shell +- **Oh My Zsh** - Framework with 14+ infrastructure plugins +- **Antigen** - Plugin manager +- **zsh-users plugins**: + - `zsh-syntax-highlighting` - Fish-like syntax highlighting + - `zsh-autosuggestions` - Fish-like autosuggestions + - `zsh-completions` - Additional completions + - `zsh-history-substring-search` - Better history search + +--- + +## πŸ“ Files + +``` +shell-config/ +β”œβ”€β”€ .zshrc # Complete Zsh configuration +β”œβ”€β”€ antigen.zsh # Antigen plugin manager +β”œβ”€β”€ install-zsh.sh # Automated installation script +└── README.md # This file +``` + +--- + +## 🎯 Features + +### Infrastructure Aliases + +```bash +# Navigation +orion, tf, ans, k8s + +# Terraform +tfi, tfp, tfa, tfd, tfo, tfs + +# Kubernetes +k, kgp, kgs, kgn, kd, kl, ke + +# Make +m, mh, mdeploy, mverify +``` + +### Custom Functions + +```bash +deploy() # Quick deploy ORION stack +orion-status() # Complete infrastructure status +ssh-router() # SSH to router VM +ssh-coordinator() # SSH to AI coordinator +ssh-netbox() # SSH to NetBox +ssh-k8s-master() # SSH to K8s master +proxmox-vms() # List Proxmox VMs +proxmox-lxc() # List LXC containers +``` + +--- + +## πŸ“š Documentation + +See **[docs/DEVELOPMENT_ENVIRONMENT.md](../docs/DEVELOPMENT_ENVIRONMENT.md)** for complete documentation including: + +- Detailed installation guide +- Plugin configuration +- Claude Code integration +- SSH tunneling for remote development +- Customization options +- Troubleshooting + +--- + +## πŸ”§ Manual Installation + +If you prefer manual installation: + +```bash +# 1. Install Zsh +sudo apt-get install zsh git curl wget + +# 2. Install Oh My Zsh +sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" + +# 3. Install Antigen +curl -L git.io/antigen > ~/antigen.zsh + +# 4. Copy configuration +cp .zshrc ~/.zshrc +cp antigen.zsh ~/antigen.zsh + +# 5. Start zsh +zsh +``` + +--- + +## πŸ’‘ Quick Tips + +**Autosuggestions**: Type a few letters, press `β†’` to accept + +**Syntax Highlighting**: Green = valid command, Red = invalid + +**History Search**: Press `↑` to search history by substring + +**Quick Deploy**: Just type `deploy` + +**Status Check**: Type `orion-status` for complete overview + +--- + +**Last Updated**: 2025-11-22 diff --git a/shell-config/antigen.zsh b/shell-config/antigen.zsh new file mode 100644 index 0000000..e813207 --- /dev/null +++ b/shell-config/antigen.zsh @@ -0,0 +1,2057 @@ +###################################################################### +# This file was autogenerated by `make`. Do not edit it directly! +###################################################################### +# Antigen: A simple plugin manager for zsh + # Authors: Shrikant Sharat Kandula + # and Contributors + # Homepage: http://antigen.sharats.me + # License: MIT License +zmodload zsh/parameter +autoload -U is-at-least + +# While boot.zsh is part of the ext/cache functionallity it may be disabled +# with ANTIGEN_CACHE flag, and it's always compiled with antigen.zsh +if [[ $ANTIGEN_CACHE != false ]]; then + ANTIGEN_CACHE="${ANTIGEN_CACHE:-${ADOTDIR:-$HOME/.antigen}/init.zsh}" + ANTIGEN_RSRC="${ANTIGEN_RSRC:-${ADOTDIR:-$HOME/.antigen}/.resources}" + + # It may not be necessary to check ANTIGEN_AUTO_CONFIG. + if [[ $ANTIGEN_AUTO_CONFIG != false && -f $ANTIGEN_RSRC ]]; then + # Check the list of files for configuration changes (uses -nt comp) + ANTIGEN_CHECK_FILES=$(cat $ANTIGEN_RSRC 2> /dev/null) + ANTIGEN_CHECK_FILES=(${(@f)ANTIGEN_CHECK_FILES}) + + for config in $ANTIGEN_CHECK_FILES; do + if [[ "$config" -nt "$config.zwc" ]]; then + # Flag configuration file as newer + { zcompile "$config" } &! + # Kill cache file in order to force full loading (see a few lines below) + [[ -f "$ANTIGEN_CACHE" ]] && rm -f "$ANTIGEN_CACHE" + fi + done + fi + + # If there is a cache file do load from it + if [[ -f $ANTIGEN_CACHE && ! $_ANTIGEN_CACHE_LOADED == true ]]; then + # Wrap antigen in order to defer cache source until `antigen-apply` + antigen() { + if [[ $1 == "apply" ]]; then + source "$ANTIGEN_CACHE" + # Handle `antigen-init` command properly + elif [[ $1 == "init" ]]; then + source "$2" + fi + } + # Do not continue loading antigen as cache bundle takes care of it. + return 0 + fi +fi +[[ -z "$_ANTIGEN_INSTALL_DIR" ]] && _ANTIGEN_INSTALL_DIR=${0:A:h} + +# Each line in this string has the following entries separated by a space +# character. +# , , , +[[ $_ANTIGEN_CACHE_LOADED != true ]] && typeset -aU _ANTIGEN_BUNDLE_RECORD + +# Do not load anything if git is not available. +if (( ! $+commands[git] )); then + echo 'Antigen: Please install git to use Antigen.' >&2 + return 1 +fi + +# Used to defer compinit/compdef +typeset -a __deferred_compdefs +compdef () { __deferred_compdefs=($__deferred_compdefs "$*") } + +# A syntax sugar to avoid the `-` when calling antigen commands. With this +# function, you can write `antigen-bundle` as `antigen bundle` and so on. +antigen () { + local cmd="$1" + if [[ -z "$cmd" ]]; then + echo 'Antigen: Please give a command to run.' >&2 + return 1 + fi + shift + + if (( $+functions[antigen-$cmd] )); then + "antigen-$cmd" "$@" + return $? + else + echo "Antigen: Unknown command: $cmd" >&2 + return 1 + fi +} +# Returns the bundle's git revision +# +# Usage +# -antigen-bundle-rev bundle-name [is_local_clone] +# +# Returns +# Bundle rev-parse output (branch name or short ref name) +-antigen-bundle-rev () { + local bundle=$1 + local is_local_clone=$2 + + local bundle_path=$bundle + # Get bunde path inside $ADOTDIR if bundle was effectively cloned + if [[ "$is_local_clone" == "true" ]]; then + bundle_path=$(-antigen-get-clone-dir $bundle) + fi + + local ref + ref=$(git --git-dir="$bundle_path/.git" rev-parse --abbrev-ref '@' 2>/dev/null) + + # Avoid 'HEAD' when in detached mode + if [[ $ref == "HEAD" ]]; then + ref=$(git --git-dir="$bundle_path/.git" describe --tags --exact-match 2>/dev/null \ + || git --git-dir="$bundle_path/.git" rev-parse --short '@' 2>/dev/null || "-") + fi + echo $ref +} +# Usage: +# -antigen-bundle-short-name "https://github.com/user/repo.git[|*]" "[branch/name]" +# Returns: +# user/repo@branch/name +-antigen-bundle-short-name () { + local bundle_name="${1%|*}" + local bundle_branch="$2" + local match mbegin mend MATCH MBEGIN MEND + + [[ "$bundle_name" =~ '.*/(.*/.*).*$' ]] && bundle_name=$match[1] + bundle_name="${bundle_name%.git*}" + + if [[ -n $bundle_branch ]]; then + bundle_name="$bundle_name@$bundle_branch" + fi + + echo $bundle_name +} +# Echo the bundle specs as in the record. The first line is not echoed since it +# is a blank line. +-antigen-echo-record () { + echo ${(j:\n:)_ANTIGEN_BUNDLE_RECORD} +} +# Filters _ANTIGEN_BUNDLE_RECORD for $1 +# +# Usage +# -antigen-find-bundle example/bundle +# +# Returns +# String if bundle is found +-antigen-find-bundle () { + echo $(-antigen-find-record $1 | cut -d' ' -f1) +} + +# Filters _ANTIGEN_BUNDLE_RECORD for $1 +# +# Usage +# -antigen-find-record example/bundle +# +# Returns +# String if record is found +-antigen-find-record () { + local bundle=$1 + + if [[ $# -eq 0 ]]; then + return 1 + fi + + local record=${bundle/\|/\\\|} + echo "${_ANTIGEN_BUNDLE_RECORD[(r)*$record*]}" +} +# Returns bundle names from _ANTIGEN_BUNDLE_RECORD +# +# Usage +# -antigen-get-bundles [--short|--simple|--long] +# +# Returns +# List of bundles installed +-antigen-get-bundles () { + local mode revision url bundle_name bundle_entry loc no_local_clone + local record bundle make_local_clone + mode=${1:-"--short"} + + for record in $_ANTIGEN_BUNDLE_RECORD; do + bundle=(${(@s/ /)record}) + url=$bundle[1] + loc=$bundle[2] + make_local_clone=$bundle[4] + + bundle_name=$(-antigen-bundle-short-name $url) + + case "$mode" in + --short) + # Only check revision for bundle with a requested branch + if [[ $url == *\|* ]]; then + revision=$(-antigen-bundle-rev $url $make_local_clone) + else + revision="master" + fi + + if [[ $loc != '/' ]]; then + bundle_name="$bundle_name ~ $loc" + fi + echo "$bundle_name @ $revision" + ;; + --simple) + echo "$bundle_name" + ;; + --long) + echo "$record" + ;; + esac + done +} +# Usage: +# -antigen-get-clone-dir "https://github.com/zsh-users/zsh-syntax-highlighting.git[|feature/branch]" +# Returns: +# $ANTIGEN_BUNDLES/zsh-users/zsh-syntax-highlighting[-feature-branch] +-antigen-get-clone-dir () { + local bundle="$1" + local url="${bundle%|*}" + local branch match mbegin mend MATCH MBEGIN MEND + [[ "$bundle" =~ "\|" ]] && branch="${bundle#*|}" + + # Takes a repo url and mangles it, giving the path that this url will be + # cloned to. Doesn't actually clone anything. + local clone_dir="$ANTIGEN_BUNDLES" + + url=$(-antigen-bundle-short-name $url) + + # Suffix with branch/tag name + [[ -n "$branch" ]] && url="$url-${branch//\//-}" + url=${url//\*/x} + + echo "$clone_dir/$url" +} +# Returns bundles flagged as make_local_clone +# +# Usage +# -antigen-cloned-bundles +# +# Returns +# Bundle metadata +-antigen-get-cloned-bundles() { + -antigen-echo-record | + awk '$4 == "true" {print $1}' | + sort -u +} +# Returns a list of themes from a default library (omz) +# +# Usage +# -antigen-get-themes +# +# Returns +# List of themes by name +-antigen-get-themes () { + local library='robbyrussell/oh-my-zsh' + local bundle=$(-antigen-find-bundle $library) + + if [[ -n "$bundle" ]]; then + local dir=$(-antigen-get-clone-dir $ANTIGEN_DEFAULT_REPO_URL) + echo $(ls $dir/themes/ | grep '.zsh-theme$' | sed 's/.zsh-theme//') + fi + + return 0 +} + +# This function check ZSH_EVAL_CONTEXT to determine if running in interactive shell. +# +# Usage +# -antigen-interactive-mode +# +# Returns +# Either true or false depending if we are running in interactive mode +-antigen-interactive-mode () { + WARN "-antigen-interactive-mode: $ZSH_EVAL_CONTEXT \$_ANTIGEN_INTERACTIVE = $_ANTIGEN_INTERACTIVE" + if [[ $_ANTIGEN_INTERACTIVE != "" ]]; then + [[ $_ANTIGEN_INTERACTIVE == true ]]; + return + fi + + [[ "$ZSH_EVAL_CONTEXT" == toplevel* || "$ZSH_EVAL_CONTEXT" == cmdarg* ]]; +} +# Parses and retrieves a remote branch given a branch name. +# +# If the branch name contains '*' it will retrieve remote branches +# and try to match against tags and heads, returning the latest matching. +# +# Usage +# -antigen-parse-branch https://github.com/user/repo.git x.y.z +# +# Returns +# Branch name +-antigen-parse-branch () { + local url="$1" branch="$2" branches + + local match mbegin mend MATCH MBEGIN MEND + + if [[ "$branch" =~ '\*' ]]; then + branches=$(git ls-remote --tags -q "$url" "$branch"|cut -d'/' -f3|sort -n|tail -1) + # There is no --refs flag in git 1.8 and below, this way we + # emulate this flag -- also git 1.8 ref order is undefined. + branch=${${branches#*/*/}%^*} # Why you are like this? + fi + + echo $branch +} +-antigen-update-repos () { + local repo bundle url target + local log=/tmp/antigen-v2-migrate.log + + echo "It seems you have bundles cloned with Antigen v1.x." + echo "We'll try to convert directory structure to v2." + echo + + echo -n "Moving bundles to '\$ADOTDIR/bundles'... " + + # Migrate old repos -> bundles + local errors=0 + for repo in $ADOTDIR/repos/*; do + bundle=${repo/$ADOTDIR\/repos\//} + bundle=${bundle//-SLASH-/\/} + bundle=${bundle//-COLON-/\:} + bundle=${bundle//-STAR-/\*} + url=${bundle//-PIPE-/\|} + target=$(-antigen-get-clone-dir $url) + mkdir -p "${target:A:h}" + echo " ---> ${repo/$ADOTDIR\/} -> ${target/$ADOTDIR\/}" | tee > $log + mv "$repo" "$target" &> $log + if [[ $? != 0 ]]; then + echo "Failed to migrate '$repo'!." + errors+=1 + fi + done + + if [[ $errors == 0 ]]; then + echo "Done." + else + echo "An error ocurred!" + fi + echo + + if [[ "$(ls -A $ADOTDIR/repos | wc -l | xargs)" == 0 ]]; then + echo "You can safely remove \$ADOTDIR/repos." + else + echo "Some bundles couldn't be migrated. See \$ADOTDIR/repos." + fi + + echo + if [[ $errors == 0 ]]; then + echo "Bundles migrated successfuly." + rm $log + else + echo "Some errors occured. Review migration log in '$log'." + fi + antigen-reset +} +# Ensure that a clone exists for the given repo url and branch. If the first +# argument is `update` and if a clone already exists for the given repo +# and branch, it is pull-ed, i.e., updated. +# +# This function expects three arguments in order: +# - 'url=' +# - 'update=true|false' +# - 'verbose=true|false' +# +# Returns true|false Whether cloning/pulling was succesful +-antigen-ensure-repo () { + # Argument defaults. Previously using ${1:?"missing url argument"} format + # but it seems to mess up with cram + if (( $# < 1 )); then + echo "Antigen: Missing url argument." + return 1 + fi + + # The url. No sane default for this, so just empty. + local url=$1 + # Check if we have to update. + local update=${2:-false} + # Verbose output. + local verbose=${3:-false} + + shift $# + + # Get the clone's directory as per the given repo url and branch. + local clone_dir=$(-antigen-get-clone-dir $url) + if [[ -d "$clone_dir" && $update == false ]]; then + return true + fi + + # A temporary function wrapping the `git` command with repeated arguments. + --plugin-git () { + (\cd -q "$clone_dir" && eval ${ANTIGEN_CLONE_ENV} git --git-dir="$clone_dir/.git" --no-pager "$@" &>>! $ANTIGEN_LOG) + } + + local success=false + + # If its a specific branch that we want, checkout that branch. + local branch="master" # TODO FIX THIS + if [[ $url == *\|* ]]; then + branch="$(-antigen-parse-branch ${url%|*} ${url#*|})" + fi + + if [[ ! -d $clone_dir ]]; then + eval ${ANTIGEN_CLONE_ENV} git clone ${=ANTIGEN_CLONE_OPTS} --branch "$branch" -- "${url%|*}" "$clone_dir" &>> $ANTIGEN_LOG + success=$? + elif $update; then + # Save current revision. + local old_rev="$(--plugin-git rev-parse HEAD)" + # Pull changes if update requested. + --plugin-git checkout "$branch" + --plugin-git pull origin "$branch" + success=$? + + # Update submodules. + --plugin-git submodule update ${=ANTIGEN_SUBMODULE_OPTS} + # Get the new revision. + local new_rev="$(--plugin-git rev-parse HEAD)" + fi + + if [[ -n $old_rev && $old_rev != $new_rev ]]; then + echo Updated from $old_rev[0,7] to $new_rev[0,7]. + if $verbose; then + --plugin-git log --oneline --reverse --no-merges --stat '@{1}..' + fi + fi + + # Remove the temporary git wrapper function. + unfunction -- --plugin-git + + return $success +} +# Helper function: Same as `$1=$2`, but will only happen if the name +# specified by `$1` is not already set. +-antigen-set-default () { + local arg_name="$1" + local arg_value="$2" + eval "test -z \"\$$arg_name\" && typeset -g $arg_name='$arg_value'" +} + +-antigen-env-setup () { + typeset -gU fpath path + + # Pre-startup initializations. + -antigen-set-default ANTIGEN_OMZ_REPO_URL \ + https://github.com/robbyrussell/oh-my-zsh.git + -antigen-set-default ANTIGEN_PREZTO_REPO_URL \ + https://github.com/sorin-ionescu/prezto.git + -antigen-set-default ANTIGEN_DEFAULT_REPO_URL $ANTIGEN_OMZ_REPO_URL + + # Default Antigen directory. + -antigen-set-default ADOTDIR $HOME/.antigen + [[ ! -d $ADOTDIR ]] && mkdir -p $ADOTDIR + + # Defaults bundles directory. + -antigen-set-default ANTIGEN_BUNDLES $ADOTDIR/bundles + + # If there is no bundles directory, create it. + if [[ ! -d $ANTIGEN_BUNDLES ]]; then + mkdir -p $ANTIGEN_BUNDLES + # Check for v1 repos directory, transform it to v2 format. + [[ -d $ADOTDIR/repos ]] && -antigen-update-repos + fi + + -antigen-set-default ANTIGEN_COMPDUMP "${ADOTDIR:-$HOME}/.zcompdump" + -antigen-set-default ANTIGEN_LOG /dev/null + + # CLONE_OPTS uses ${=CLONE_OPTS} expansion so don't use spaces + # for arguments that can be passed as `--key=value`. + -antigen-set-default ANTIGEN_CLONE_ENV "GIT_TERMINAL_PROMPT=0" + -antigen-set-default ANTIGEN_CLONE_OPTS "--single-branch --recursive --depth=1" + -antigen-set-default ANTIGEN_SUBMODULE_OPTS "--recursive --depth=1" + + # Complain when a bundle is already installed. + -antigen-set-default _ANTIGEN_WARN_DUPLICATES true + + # Compatibility with oh-my-zsh themes. + -antigen-set-default _ANTIGEN_THEME_COMPAT true + + # Add default built-in extensions to load at start up + -antigen-set-default _ANTIGEN_BUILTIN_EXTENSIONS 'lock parallel defer cache' + + # Setup antigen's own completion. + if -antigen-interactive-mode; then + TRACE "Gonna create compdump file @ env-setup" COMPDUMP + autoload -Uz compinit + compinit -d "$ANTIGEN_COMPDUMP" + compdef _antigen antigen + else + (( $+functions[antigen-ext-init] )) && antigen-ext-init + fi +} +# Load a given bundle by sourcing it. +# +# The function also modifies fpath to add the bundle path. +# +# Usage +# -antigen-load "bundle-url" ["location"] ["make_local_clone"] ["btype"] +# +# Returns +# Integer. 0 if success 1 if an error ocurred. +-antigen-load () { + local bundle list + typeset -A bundle; bundle=($@) + + typeset -Ua list; list=() + local location="${bundle[dir]}/${bundle[loc]}" + + # Prioritize location when given. + if [[ -f "${location}" ]]; then + list=(${location}) + else + # Directory locations must be suffixed with slash + location="$location/" + + # Prioritize theme with antigen-theme + if [[ ${bundle[btype]} == "theme" ]]; then + list=(${location}*.zsh-theme(N[1])) + fi + + # Common frameworks + if [[ $#list == 0 ]]; then + # dot-plugin, init and functions support (omz, prezto) + # Support prezto function loading. See https://github.com/zsh-users/antigen/pull/428 + list=(${location}*.plugin.zsh(N[1]) ${location}init.zsh(N[1]) ${location}/functions(N[1])) + fi + + # Default to zsh and sh + if [[ $#list == 0 ]]; then + list=(${location}*.zsh(N) ${location}*.sh(N)) + fi + fi + + -antigen-load-env ${(kv)bundle} + + # If there is any sourceable try to load it + if ! -antigen-load-source "${list[@]}" && [[ ! -d ${location} ]]; then + return 1 + fi + + return 0 +} + +-antigen-load-env () { + typeset -A bundle; bundle=($@) + local location=${bundle[dir]}/${bundle[loc]} + + # Load to path if there is no sourceable + if [[ -d ${location} ]]; then + PATH="$PATH:${location:A}" + fpath+=("${location:A}") + return + fi + + PATH="$PATH:${location:A:h}" + fpath+=("${location:A:h}") +} + +-antigen-load-source () { + typeset -a list + list=($@) + local src match mbegin mend MATCH MBEGIN MEND + + # Return error when we're given an empty list + if [[ $#list == 0 ]]; then + return 1 + fi + + # Using a for rather than `source $list` as we need to check for zsh-themes + # In order to create antigen-compat file. This is only needed for interactive-mode + # theme switching, for static loading (cache) there is no need. + for src in $list; do + if [[ $_ANTIGEN_THEME_COMPAT == true && -f "$src" && "$src" == *.zsh-theme* ]]; then + local compat="${src:A}.antigen-compat" + echo "# Generated by Antigen. Do not edit!" >! "$compat" + cat $src | sed -Ee '/\{$/,/^\}/!{ + s/^local // + }' >>! "$compat" + src="$compat" + fi + + if ! source "$src" 2>/dev/null; then + return 1 + fi + done +} +# Usage: +# -antigen-parse-args output_assoc_arr +-antigen-parse-args () { + local argkey key value index=0 args + local match mbegin mend MATCH MBEGIN MEND + + local var=$1 + shift + + # Bundle spec arguments' default values. + #setopt XTRACE VERBOSE + builtin typeset -A args + args[url]="$ANTIGEN_DEFAULT_REPO_URL" + #unsetopt XTRACE VERBOSE + args[loc]=/ + args[make_local_clone]=true + args[btype]=plugin + #args[branch]= # commented out as it may cause assoc array kv mismatch + + while [[ $# -gt 0 ]]; do + argkey="${1%\=*}" + key="${argkey//--/}" + value="${1#*=}" + + case "$argkey" in + --url|--loc|--branch|--btype) + if [[ "$value" == "$argkey" ]]; then + printf "Required argument for '%s' not provided.\n" $key >&2 + else + args[$key]="$value" + fi + ;; + --no-local-clone) + args[make_local_clone]=false + ;; + --*) + printf "Unknown argument '%s'.\n" $key >&2 + ;; + *) + value=$key + case $index in + 0) + key=url + local domain="" + local url_path=$value + # Full url with protocol or ssh github url (github.com:org/repo) + if [[ "$value" =~ "://" || "$value" =~ ":" ]]; then + if [[ "$value" =~ [@.][^/:]+[:]?[0-9]*[:/]?(.*)@?$ ]]; then + url_path=$match[1] + domain=${value/$url_path/} + fi + fi + + if [[ "$url_path" =~ '@' ]]; then + args[branch]="${url_path#*@}" + value="$domain${url_path%@*}" + else + value="$domain$url_path" + fi + ;; + 1) key=loc ;; + esac + let index+=1 + args[$key]="$value" + ;; + esac + + shift + done + + # Check if url is just the plugin name. Super short syntax. + if [[ "${args[url]}" != */* ]]; then + case "$ANTIGEN_DEFAULT_REPO_URL" in + "$ANTIGEN_OMZ_REPO_URL") + args[loc]="plugins/${args[url]}" + ;; + "$ANTIGEN_PREZTO_REPO_URL") + args[loc]="modules/${args[url]}" + ;; + *) + args[loc]="${args[url]}" + ;; + esac + args[url]="$ANTIGEN_DEFAULT_REPO_URL" + fi + + # Resolve the url. + # Expand short github url syntax: `username/reponame`. + local url="${args[url]}" + if [[ $url != git://* && + $url != https://* && + $url != http://* && + $url != ssh://* && + $url != /* && + $url != *github.com:*/* + ]]; then + url="https://github.com/${url%.git}.git" + fi + args[url]="$url" + + # Ignore local clone if url given is not a git directory + if [[ ${args[url]} == /* && ! -d ${args[url]}/.git ]]; then + args[make_local_clone]=false + fi + + # Add the branch information to the url if we need to create a local clone. + # Format url in bundle-metadata format: url[|branch] + if [[ ! -z "${args[branch]}" && ${args[make_local_clone]} == true ]]; then + args[url]="${args[url]}|${args[branch]}" + fi + + # Add the theme extension to `loc`, if this is a theme, but only + # if it's especified, ie, --loc=theme-name, in case when it's not + # specified antige-load-list will look for *.zsh-theme files + if [[ ${args[btype]} == "theme" && + ${args[loc]} != "/" && ${args[loc]} != *.zsh-theme ]]; then + args[loc]="${args[loc]}.zsh-theme" + fi + + local name="${args[url]%|*}" + local branch="${args[branch]}" + + # Extract bundle name. + if [[ "$name" =~ '.*/(.*/.*).*$' ]]; then + name="${match[1]}" + fi + name="${name%.git*}" + + # Format bundle name with optional branch. + if [[ -n "${branch}" ]]; then + args[name]="${name}@${branch}" + else + args[name]="${name}" + fi + + # Format bundle path. + if [[ ${args[make_local_clone]} == true ]]; then + local bpath="$name" + # Suffix with branch/tag name + if [[ -n "$branch" ]]; then + # bpath is in the form of repo/name@version => repo/name-version + # Replace / with - in bundle branch. + local bbranch=${branch//\//-} + # If branch/tag is semver-like do replace * by x. + bbranch=${bbranch//\*/x} + bpath="${name}-${bbranch}" + fi + + bpath="$ANTIGEN_BUNDLES/$bpath" + args[dir]="${(qq)bpath}" + else + # if it's local then path is just the "url" argument, loc remains the same + args[dir]=${args[url]} + fi + + # Escape url and branch (may contain semver-like and pipe characters) + args[url]="${(qq)args[url]}" + if [[ -n "${args[branch]}" ]]; then + args[branch]="${(qq)args[branch]}" + fi + + # Escape bundle name (may contain semver-like characters) + args[name]="${(qq)args[name]}" + + eval "${var}=(${(kv)args})" + + return 0 +} +# Updates revert-info data with git hash. +# +# This does process only cloned bundles. +# +# Usage +# -antigen-revert-info +# +# Returns +# Nothing. Generates/updates $ADOTDIR/revert-info. +-antigen-revert-info() { + local url + # Update your bundles, i.e., `git pull` in all the plugin repos. + date >! $ADOTDIR/revert-info + + -antigen-get-cloned-bundles | while read url; do + local clone_dir="$(-antigen-get-clone-dir "$url")" + if [[ -d "$clone_dir" ]]; then + (echo -n "$clone_dir:" + \cd -q "$clone_dir" + git rev-parse HEAD) >> $ADOTDIR/revert-info + fi + done +} +-antigen-use-oh-my-zsh () { + typeset -g ZSH ZSH_CACHE_DIR + ANTIGEN_DEFAULT_REPO_URL=$ANTIGEN_OMZ_REPO_URL + if [[ -z "$ZSH" ]]; then + ZSH="$(-antigen-get-clone-dir "$ANTIGEN_DEFAULT_REPO_URL")" + fi + if [[ -z "$ZSH_CACHE_DIR" ]]; then + ZSH_CACHE_DIR="$ZSH/cache/" + fi + antigen-bundle --loc=lib +} +-antigen-use-prezto () { + ANTIGEN_DEFAULT_REPO_URL=$ANTIGEN_PREZTO_REPO_URL + antigen-bundle "$ANTIGEN_PREZTO_REPO_URL" +} +# Initialize completion +antigen-apply () { + LOG "Called antigen-apply" + + # Load the compinit module. This will readefine the `compdef` function to + # the one that actually initializes completions. + TRACE "Gonna create compdump file @ apply" COMPDUMP + autoload -Uz compinit + compinit -d "$ANTIGEN_COMPDUMP" + + # Apply all `compinit`s that have been deferred. + local cdef + for cdef in "${__deferred_compdefs[@]}"; do + compdef "$cdef" + done + + { zcompile "$ANTIGEN_COMPDUMP" } &! + + unset __deferred_compdefs +} +# Syntaxes +# antigen-bundle [=/] +# Keyword only arguments: +# branch - The branch of the repo to use for this bundle. +antigen-bundle () { + TRACE "Called antigen-bundle with $@" BUNDLE + if [[ -z "$1" ]]; then + printf "Antigen: Must provide a bundle url or name.\n" >&2 + return 1 + fi + + builtin typeset -A bundle; -antigen-parse-args 'bundle' ${=@} + if [[ -z ${bundle[btype]} ]]; then + bundle[btype]=bundle + fi + + local record="${bundle[url]} ${bundle[loc]} ${bundle[btype]} ${bundle[make_local_clone]}" + if [[ $_ANTIGEN_WARN_DUPLICATES == true && ! ${_ANTIGEN_BUNDLE_RECORD[(I)$record]} == 0 ]]; then + printf "Seems %s is already installed!\n" ${bundle[name]} + return 1 + fi + + # Clone bundle if we haven't done do already. + if [[ ! -d "${bundle[dir]}" ]]; then + if ! -antigen-bundle-install ${(kv)bundle}; then + return 1 + fi + fi + + # Load the plugin. + if ! -antigen-load ${(kv)bundle}; then + TRACE "-antigen-load failed to load ${bundle[name]}" BUNDLE + printf "Antigen: Failed to load %s.\n" ${bundle[btype]} >&2 + return 1 + fi + + # Only add it to the record if it could be installed and loaded. + _ANTIGEN_BUNDLE_RECORD+=("$record") +} + +# +# Usage: +# -antigen-bundle-install +# Returns: +# 1 if it fails to install bundle +-antigen-bundle-install () { + typeset -A bundle; bundle=($@) + + # Ensure a clone exists for this repo, if needed. + # Get the clone's directory as per the given repo url and branch. + local bpath="${bundle[dir]}" + # Clone if it doesn't already exist. + local start=$(date +'%s') + + printf "Installing %s... " "${bundle[name]}" + + if ! -antigen-ensure-repo "${bundle[url]}"; then + # Return immediately if there is an error cloning + TRACE "-antigen-bundle-instal failed to clone ${bundle[url]}" BUNDLE + printf "Error! Activate logging and try again.\n" >&2 + return 1 + fi + + local took=$(( $(date +'%s') - $start )) + printf "Done. Took %ds.\n" $took +} +antigen-bundles () { + # Bulk add many bundles at one go. Empty lines and lines starting with a `#` + # are ignored. Everything else is given to `antigen-bundle` as is, no + # quoting rules applied. + local line + setopt localoptions no_extended_glob # See https://github.com/zsh-users/antigen/issues/456 + grep '^[[:space:]]*[^[:space:]#]' | while read line; do + antigen-bundle ${=line%#*} + done +} +# Cleanup unused repositories. +antigen-cleanup () { + local force=false + if [[ $1 == --force ]]; then + force=true + fi + + if [[ ! -d "$ANTIGEN_BUNDLES" || -z "$(\ls -A "$ANTIGEN_BUNDLES")" ]]; then + echo "You don't have any bundles." + return 0 + fi + + # Find directores in ANTIGEN_BUNDLES, that are not in the bundles record. + typeset -a unused_clones clones + + local url record clone + for record in $(-antigen-get-cloned-bundles); do + url=${record% /*} + clones+=("$(-antigen-get-clone-dir $url)") + done + + for clone in $ANTIGEN_BUNDLES/*/*(/); do + if [[ $clones[(I)$clone] == 0 ]]; then + unused_clones+=($clone) + fi + done + + if [[ -z $unused_clones ]]; then + echo "You don't have any unidentified bundles." + return 0 + fi + + echo 'You have clones for the following repos, but are not used.' + echo "\n${(j:\n:)unused_clones}" + + if $force || (echo -n '\nDelete them all? [y/N] '; read -q); then + echo + echo + for clone in $unused_clones; do + echo -n "Deleting clone \"$clone\"..." + \rm -rf "$clone" + + echo ' done.' + done + else + echo + echo "Nothing deleted." + fi +} +antigen-help () { + antigen-version + + cat < [args] + +Commands: + apply Must be called in the zshrc after all calls to 'antigen bundle'. + bundle Install and load a plugin. + cache-gen Generate Antigen's cache with currently loaded bundles. + cleanup Remove clones of repos not used by any loaded plugins. + init Use caching to quickly load bundles. + list List currently loaded plugins. + purge Remove a bundle from the filesystem. + reset Clean the generated cache. + restore Restore plugin state from a snapshot file. + revert Revert plugins to their state prior to the last time 'antigen + update' was run. + selfupdate Update antigen. + snapshot Create a snapshot of all active plugin repos and save it to a + snapshot file. + update Update plugins. + use Load a supported zsh pre-packaged framework. + +For further details and complete documentation, visit the project's page at +'http://antigen.sharats.me'. +EOF +} +# Antigen command to load antigen configuration +# +# This method is slighlty more performing than using various antigen-* methods. +# +# Usage +# Referencing an antigen configuration file: +# +# antigen-init "/path/to/antigenrc" +# +# or using HEREDOCS: +# +# antigen-init <&2 + return 1 + fi + fi + + # Otherwise we expect it to be a heredoc + grep '^[[:space:]]*[^[:space:]#]' | while read -r line; do + eval $line + done +} +# List instaled bundles either in long (record), short or simple format. +# +# Usage +# antigen-list [--short|--long|--simple] +# +# Returns +# List of bundles +antigen-list () { + local format=$1 + + # List all currently installed bundles. + if [[ -z $_ANTIGEN_BUNDLE_RECORD ]]; then + echo "You don't have any bundles." >&2 + return 1 + fi + + -antigen-get-bundles $format +} +# Remove a bundle from filesystem +# +# Usage +# antigen-purge example/bundle [--force] +# +# Returns +# Nothing. Removes bundle from filesystem. +antigen-purge () { + local bundle=$1 + local force=$2 + + if [[ $# -eq 0 ]]; then + echo "Antigen: Missing argument." >&2 + return 1 + fi + + if -antigen-purge-bundle $bundle $force; then + antigen-reset + else + return $? + fi + + return 0 +} + +# Remove a bundle from filesystem +# +# Usage +# antigen-purge example/bundle [--force] +# +# Returns +# Nothing. Removes bundle from filesystem. +-antigen-purge-bundle () { + local bundle=$1 + local force=$2 + local clone_dir="" + + local record="" + local url="" + local make_local_clone="" + + if [[ $# -eq 0 ]]; then + echo "Antigen: Missing argument." >&2 + return 1 + fi + + # local keyword doesn't work on zsh <= 5.0.0 + record=$(-antigen-find-record $bundle) + + if [[ ! -n "$record" ]]; then + echo "Bundle not found in record. Try 'antigen bundle $bundle' first." >&2 + return 1 + fi + + url="$(echo "$record" | cut -d' ' -f1)" + make_local_clone=$(echo "$record" | cut -d' ' -f4) + + if [[ $make_local_clone == "false" ]]; then + echo "Bundle has no local clone. Will not be removed." >&2 + return 1 + fi + + clone_dir=$(-antigen-get-clone-dir "$url") + if [[ $force == "--force" ]] || read -q "?Remove '$clone_dir'? (y/n) "; then + # Need empty line after read -q + [[ ! -n $force ]] && echo "" || echo "Removing '$clone_dir'."; + rm -rf "$clone_dir" + return $? + fi + + return 1 +} +# Removes cache payload and metadata if available +# +# Usage +# antigen-reset +# +# Returns +# Nothing +antigen-reset () { + [[ -f "$ANTIGEN_CACHE" ]] && rm -f "$ANTIGEN_CACHE" "$ANTIGEN_CACHE.zwc" 1> /dev/null + [[ -f "$ANTIGEN_RSRC" ]] && rm -f "$ANTIGEN_RSRC" 1> /dev/null + [[ -f "$ANTIGEN_COMPDUMP" ]] && rm -f "$ANTIGEN_COMPDUMP" "$ANTIGEN_COMPDUMP.zwc" 1> /dev/null + [[ -f "$ANTIGEN_LOCK" ]] && rm -f "$ANTIGEN_LOCK" 1> /dev/null + echo 'Done. Please open a new shell to see the changes.' +} +antigen-restore () { + local line + if [[ $# == 0 ]]; then + echo 'Please provide a snapshot file to restore from.' >&2 + return 1 + fi + + local snapshot_file="$1" + + # TODO: Before doing anything with the snapshot file, verify its checksum. + # If it fails, notify this to the user and confirm if restore should + # proceed. + + echo -n "Restoring from $snapshot_file..." + + sed -n '1!p' "$snapshot_file" | + while read line; do + local version_hash="${line%% *}" + local url="${line##* }" + local clone_dir="$(-antigen-get-clone-dir "$url")" + + if [[ ! -d $clone_dir ]]; then + git clone "$url" "$clone_dir" &> /dev/null + fi + + (\cd -q "$clone_dir" && git checkout $version_hash) &> /dev/null + done + + echo ' done.' + echo 'Please open a new shell to get the restored changes.' +} +# Reads $ADORDIR/revert-info and restores bundles' revision +antigen-revert () { + local line + if [[ -f $ADOTDIR/revert-info ]]; then + cat $ADOTDIR/revert-info | sed -n '1!p' | while read line; do + local dir="$(echo "$line" | cut -d: -f1)" + git --git-dir="$dir/.git" --work-tree="$dir" \ + checkout "$(echo "$line" | cut -d: -f2)" 2> /dev/null + done + + echo "Reverted to state before running -update on $( + cat $ADOTDIR/revert-info | sed -n '1p')." + + else + echo 'No revert information available. Cannot revert.' >&2 + return 1 + fi +} +# Update (with `git pull`) antigen itself. +# TODO: Once update is finished, show a summary of the new commits, as a kind of +# "what's new" message. +antigen-selfupdate () { + (\cd -q $_ANTIGEN_INSTALL_DIR + if [[ ! ( -d .git || -f .git ) ]]; then + echo "Your copy of antigen doesn't appear to be a git clone. " \ + "The 'selfupdate' command cannot work in this case." + return 1 + fi + local head="$(git rev-parse --abbrev-ref HEAD)" + if [[ $head == "HEAD" ]]; then + # If current head is detached HEAD, checkout to master branch. + git checkout master + fi + git pull + + # TODO Should be transparently hooked by zcache + antigen-reset &>> /dev/null + ) +} +antigen-snapshot () { + local snapshot_file="${1:-antigen-shapshot}" + local urls url dir version_hash snapshot_content + local -a bundles + + # The snapshot content lines are pairs of repo-url and git version hash, in + # the form: + # + urls=$(-antigen-echo-record | awk '$4 == "true" {print $1}' | sort -u) + for url in ${(f)urls}; do + dir="$(-antigen-get-clone-dir "$url")" + version_hash="$(\cd -q "$dir" && git rev-parse HEAD)" + bundles+=("$version_hash $url"); + done + snapshot_content=${(j:\n:)bundles} + + { + # The first line in the snapshot file is for metadata, in the form: + # key='value'; key='value'; key='value'; + # Where `key`s are valid shell variable names. + + # Snapshot version. Has no relation to antigen version. If the snapshot + # file format changes, this number can be incremented. + echo -n "version='1';" + + # Snapshot creation date+time. + echo -n " created_on='$(date)';" + + # Add a checksum with the md5 checksum of all the snapshot lines. + chksum() { (md5sum; test $? = 127 && md5) 2>/dev/null | cut -d' ' -f1 } + local checksum="$(echo "$snapshot_content" | chksum)" + unset -f chksum; + echo -n " checksum='${checksum%% *}';" + + # A newline after the metadata and then the snapshot lines. + echo "\n$snapshot_content" + + } > "$snapshot_file" +} +# Loads a given theme. +# +# Shares the same syntax as antigen-bundle command. +# +# Usage +# antigen-theme zsh/theme[.zsh-theme] +# +# Returns +# 0 if everything was succesfully +antigen-theme () { + local name=$1 result=0 record + local match mbegin mend MATCH MBEGIN MEND + + if [[ -z "$1" ]]; then + printf "Antigen: Must provide a theme url or name.\n" >&2 + return 1 + fi + + -antigen-theme-reset-hooks + + record=$(-antigen-find-record "theme") + if [[ "$1" != */* && "$1" != --* ]]; then + # The first argument is just a name of the plugin, to be picked up from + # the default repo. + antigen-bundle --loc=themes/$name --btype=theme + + else + antigen-bundle "$@" --btype=theme + + fi + result=$? + + # Remove a theme from the record if the following conditions apply: + # - there was no error in bundling the given theme + # - there is a theme registered + # - registered theme is not the same as the current one + if [[ $result == 0 && -n $record ]]; then + # http://zsh-workers.zsh.narkive.com/QwfCWpW8/what-s-wrong-with-this-expression + if [[ "$record" =~ "$@" ]]; then + return $result + else + _ANTIGEN_BUNDLE_RECORD[$_ANTIGEN_BUNDLE_RECORD[(I)$record]]=() + fi + fi + + return $result +} + +-antigen-theme-reset-hooks () { + # This is only needed on interactive mode + autoload -U add-zsh-hook is-at-least + local hook + + # Clear out prompts + PROMPT="" + if [[ -n $RPROMPT ]]; then + RPROMPT="" + fi + + for hook in chpwd precmd preexec periodic; do + add-zsh-hook -D "${hook}" "prompt_*" + # common in omz themes + add-zsh-hook -D "${hook}" "*_${hook}" + add-zsh-hook -d "${hook}" "vcs_info" + done +} +# Updates the bundles or a single bundle. +# +# Usage +# antigen-update [example/bundle] +# +# Returns +# Nothing. Performs a `git pull`. +antigen-update () { + local bundle=$1 url + + # Clear log + :> $ANTIGEN_LOG + + # Update revert-info data + -antigen-revert-info + + # If no argument is given we update all bundles + if [[ $# -eq 0 ]]; then + # Here we're ignoring all non cloned bundles (ie, --no-local-clone) + -antigen-get-cloned-bundles | while read url; do + -antigen-update-bundle $url + done + # TODO next minor version + # antigen-reset + else + if -antigen-update-bundle $bundle; then + # TODO next minor version + # antigen-reset + else + return $? + fi + fi +} + +# Updates a bundle performing a `git pull`. +# +# Usage +# -antigen-update-bundle example/bundle +# +# Returns +# Nothing. Performs a `git pull`. +-antigen-update-bundle () { + local bundle="$1" + local record="" + local url="" + local make_local_clone="" + local start=$(date +'%s') + + if [[ $# -eq 0 ]]; then + printf "Antigen: Missing argument.\n" >&2 + return 1 + fi + + record=$(-antigen-find-record $bundle) + if [[ ! -n "$record" ]]; then + printf "Bundle not found in record. Try 'antigen bundle %s' first.\n" $bundle >&2 + return 1 + fi + + url="$(echo "$record" | cut -d' ' -f1)" + make_local_clone=$(echo "$record" | cut -d' ' -f4) + + local branch="master" + if [[ $url == *\|* ]]; then + branch="$(-antigen-parse-branch ${url%|*} ${url#*|})" + fi + + printf "Updating %s... " $(-antigen-bundle-short-name "$url" "$branch") + + if [[ $make_local_clone == "false" ]]; then + printf "Bundle has no local clone. Will not be updated.\n" >&2 + return 1 + fi + + # update=true verbose=false + if ! -antigen-ensure-repo "$url" true false; then + printf "Error! Activate logging and try again.\n" >&2 + return 1 + fi + + local took=$(( $(date +'%s') - $start )) + printf "Done. Took %ds.\n" $took +} +antigen-use () { + if [[ $1 == oh-my-zsh ]]; then + -antigen-use-oh-my-zsh + elif [[ $1 == prezto ]]; then + -antigen-use-prezto + elif [[ $1 != "" ]]; then + ANTIGEN_DEFAULT_REPO_URL=$1 + antigen-bundle $@ + else + echo 'Usage: antigen-use ' >&2 + echo 'Where is any one of the following:' >&2 + echo ' * oh-my-zsh' >&2 + echo ' * prezto' >&2 + echo ' is the full url.' >&2 + return 1 + fi +} +antigen-version () { + local version="v2.2.2" + local extensions revision="" + if [[ -d $_ANTIGEN_INSTALL_DIR/.git ]]; then + revision=" ($(git --git-dir=$_ANTIGEN_INSTALL_DIR/.git rev-parse --short '@'))" + fi + + printf "Antigen %s%s\n" $version $revision + if (( $+functions[antigen-ext] )); then + typeset -a extensions; extensions=($(antigen-ext-list)) + if [[ $#extensions -gt 0 ]]; then + printf "Extensions loaded: %s\n" ${(j:, :)extensions} + fi + fi +} +typeset -Ag _ANTIGEN_HOOKS; _ANTIGEN_HOOKS=() +typeset -Ag _ANTIGEN_HOOKS_META; _ANTIGEN_HOOKS_META=() +typeset -g _ANTIGEN_HOOK_PREFIX="-antigen-hook-" +typeset -g _ANTIGEN_EXTENSIONS; _ANTIGEN_EXTENSIONS=() + +# -antigen-add-hook antigen-apply antigen-apply-hook replace +# - Replaces hooked function with hook, do not call hooked function +# - Return -1 to stop calling further hooks +# -antigen-add-hook antigen-apply antigen-apply-hook pre (pre-call) +# - By default it will call hooked function +# -antigen-add-hook antigen-pply antigen-apply-hook post (post-call) +# - Calls antigen-apply and then calls hook function +# Usage: +# -antigen-add-hook antigen-apply antigen-apply-hook ["replace"|"pre"|"post"] ["once"|"repeat"] +antigen-add-hook () { + local target="$1" hook="$2" type="$3" mode="${4:-repeat}" + + if (( ! $+functions[$target] )); then + printf "Antigen: Function %s doesn't exist.\n" $target + return 1 + fi + + if (( ! $+functions[$hook] )); then + printf "Antigen: Function %s doesn't exist.\n" $hook + return 1 + fi + + if [[ "${_ANTIGEN_HOOKS[$target]}" == "" ]]; then + _ANTIGEN_HOOKS[$target]="${hook}" + else + _ANTIGEN_HOOKS[$target]="${_ANTIGEN_HOOKS[$target]}:${hook}" + fi + + _ANTIGEN_HOOKS_META[$hook]="target $target type $type mode $mode called 0" + + # Do shadow for this function if there is none already + local hook_function="${_ANTIGEN_HOOK_PREFIX}$target" + if (( ! $+functions[$hook_function] )); then + # Preserve hooked function + eval "function ${_ANTIGEN_HOOK_PREFIX}$(functions -- $target)" + + # Create hook, call hook-handler to further process hook functions + eval "function $target () { + noglob -antigen-hook-handler $target \$@ + return \$? + }" + fi + + return 0 +} + +# Private function to handle multiple hooks in a central point. +-antigen-hook-handler () { + local target="$1" args hook called + local hooks meta + shift + typeset -a args; args=(${@}) + + typeset -a pre_hooks replace_hooks post_hooks; + typeset -a hooks; hooks=(${(s|:|)_ANTIGEN_HOOKS[$target]}) + + typeset -A meta; + for hook in $hooks; do + meta=(${(s: :)_ANTIGEN_HOOKS_META[$hook]}) + if [[ ${meta[mode]} == "once" && ${meta[called]} == 1 ]]; then + WARN "Ignoring hook due to mode ${meta[mode]}: $hook" + continue + fi + + let called=${meta[called]}+1 + meta[called]=$called + _ANTIGEN_HOOKS_META[$hook]="${(kv)meta}" + WARN "Updated meta: "${(kv)meta} + + case "${meta[type]}" in + "pre") + pre_hooks+=($hook) + ;; + "replace") + replace_hooks+=($hook) + ;; + "post") + post_hooks+=($hook) + ;; + esac + done + + WARN "Processing hooks: ${hooks}" + + for hook in $pre_hooks; do + WARN "Pre hook:" $hook $args + noglob $hook $args + [[ $? == -1 ]] && WARN "$hook shortcircuited" && return $ret + done + + # A replace hook will return inmediately + local replace_hook=0 ret=0 + for hook in $replace_hooks; do + replace_hook=1 + # Should not be needed if `antigen-remove-hook` removed unneeded hooks. + if (( $+functions[$hook] )); then + WARN "Replace hook:" $hook $args + noglob $hook $args + [[ $? == -1 ]] && WARN "$hook shortcircuited" && return $ret + fi + done + + if [[ $replace_hook == 0 ]]; then + WARN "${_ANTIGEN_HOOK_PREFIX}$target $args" + noglob ${_ANTIGEN_HOOK_PREFIX}$target $args + ret=$? + else + WARN "Replaced hooked function." + fi + + for hook in $post_hooks; do + WARN "Post hook:" $hook $args + noglob $hook $args + [[ $? == -1 ]] && WARN "$hook shortcircuited" && return $ret + done + + LOG "Return from hook ${target} with ${ret}" + + return $ret +} + +# Usage: +# -antigen-remove-hook antigen-apply-hook +antigen-remove-hook () { + local hook="$1" + typeset -A meta; meta=(${(s: :)_ANTIGEN_HOOKS_META[$hook]}) + local target="${meta[target]}" + local -a hooks; hooks=(${(s|:|)_ANTIGEN_HOOKS[$target]}) + + # Remove registered hook + if [[ $#hooks > 0 ]]; then + hooks[$hooks[(I)$hook]]=() + fi + _ANTIGEN_HOOKS[${target}]="${(j|:|)hooks}" + + if [[ $#hooks == 0 ]]; then + # Destroy base hook + eval "function $(functions -- ${_ANTIGEN_HOOK_PREFIX}$target | sed s/${_ANTIGEN_HOOK_PREFIX}//)" + if (( $+functions[${_ANTIGEN_HOOK_PREFIX}$target] )); then + unfunction -- "${_ANTIGEN_HOOK_PREFIX}$target" + fi + fi + + unfunction -- $hook 2> /dev/null +} + +# Remove all defined hooks. +-antigen-reset-hooks () { + local target + + for target in ${(k)_ANTIGEN_HOOKS}; do + # Release all hooked functions + eval "function $(functions -- ${_ANTIGEN_HOOK_PREFIX}$target | sed s/${_ANTIGEN_HOOK_PREFIX}//)" + unfunction -- "${_ANTIGEN_HOOK_PREFIX}$target" 2> /dev/null + done + + _ANTIGEN_HOOKS=() + _ANTIGEN_HOOKS_META=() + _ANTIGEN_EXTENSIONS=() +} + +# Initializes an extension +# Usage: +# antigen-ext ext-name +antigen-ext () { + local ext=$1 + local func="-antigen-$ext-init" + if (( $+functions[$func] && $_ANTIGEN_EXTENSIONS[(I)$ext] == 0 )); then + eval $func + local ret=$? + WARN "$func return code was $ret" + if (( $ret == 0 )); then + LOG "LOADED EXTENSION $ext" EXT + -antigen-$ext-execute && _ANTIGEN_EXTENSIONS+=($ext) + else + WARN "IGNORING EXTENSION $func" EXT + return 1 + fi + + else + printf "Antigen: No extension defined or already loaded: %s\n" $func >&2 + return 1 + fi +} + +# List installed extensions +# Usage: +# antigen ext-list +antigen-ext-list () { + echo $_ANTIGEN_EXTENSIONS +} + +# Initializes built-in extensions +# Usage: +# antigen-ext-init +antigen-ext-init () { + # Initialize extensions. unless in interactive mode. + local ext + for ext in ${(s/ /)_ANTIGEN_BUILTIN_EXTENSIONS}; do + # Check if extension is loaded before intializing it + (( $+functions[-antigen-$ext-init] )) && antigen-ext $ext + done +} +# Initialize defer lib +-antigen-defer-init () { + typeset -ga _DEFERRED_BUNDLE; _DEFERRED_BUNDLE=() + if -antigen-interactive-mode; then + return 1 + fi +} + +-antigen-defer-execute () { + # Hooks antigen-bundle in order to defer its execution. + antigen-bundle-defer () { + _DEFERRED_BUNDLE+=("${(j: :)${@}}") + return -1 # Stop right there + } + antigen-add-hook antigen-bundle antigen-bundle-defer replace + + # Hooks antigen-apply in order to release hooked functions + antigen-apply-defer () { + WARN "Defer pre-apply" DEFER PRE-APPLY + antigen-remove-hook antigen-bundle-defer + + # Process all deferred bundles. + local bundle + for bundle in ${_DEFERRED_BUNDLE[@]}; do + LOG "Processing deferred bundle: ${bundle}" DEFER + antigen-bundle $bundle + done + + unset _DEFERRED_BUNDLE + } + antigen-add-hook antigen-apply antigen-apply-defer pre once +} +# Initialize lock lib +-antigen-lock-init () { + # Default lock path. + -antigen-set-default ANTIGEN_LOCK $ADOTDIR/.lock + typeset -g _ANTIGEN_LOCK_PROCESS=false + + # Use env variable to determine if we should load this extension + -antigen-set-default ANTIGEN_MUTEX true + # Set ANTIGEN_MUTEX to false to avoid loading this extension + if [[ $ANTIGEN_MUTEX == true ]]; then + return 0; + fi + + # Do not use mutex + return 1; +} + +-antigen-lock-execute () { + # Hook antigen command in order to check/create a lock file. + # This hook is only run once then releases itself. + antigen-lock () { + LOG "antigen-lock called" + # If there is a lock set up then we won't process anything. + if [[ -f $ANTIGEN_LOCK ]]; then + # Set up flag do the message is not repeated for each antigen-* command + [[ $_ANTIGEN_LOCK_PROCESS == false ]] && printf "Antigen: Another process in running.\n" + _ANTIGEN_LOCK_PROCESS=true + # Do not further process hooks. For this hook to properly work it + # should be registered first. + return -1 + fi + + WARN "Creating antigen-lock file at $ANTIGEN_LOCK" + touch $ANTIGEN_LOCK + } + antigen-add-hook antigen antigen-lock pre once + + # Hook antigen-apply in order to release .lock file. + antigen-apply-lock () { + WARN "Freeing antigen-lock file at $ANTIGEN_LOCK" + unset _ANTIGEN_LOCK_PROCESS + rm -f $ANTIGEN_LOCK &> /dev/null + } + antigen-add-hook antigen-apply antigen-apply-lock post once +} +# Initialize parallel lib +-antigen-parallel-init () { + WARN "Init parallel extension" PARALLEL + typeset -ga _PARALLEL_BUNDLE; _PARALLEL_BUNDLE=() + if -antigen-interactive-mode; then + return 1 + fi +} + +-antigen-parallel-execute() { + WARN "Exec parallel extension" PARALLEL + # Install bundles in parallel + antigen-bundle-parallel-execute () { + WARN "Parallel antigen-bundle-parallel-execute" PARALLEL + typeset -a pids; pids=() + local args pid + + WARN "Gonna install in parallel ${#_PARALLEL_BUNDLE} bundles." PARALLEL + # Do ensure-repo in parallel + WARN "${_PARALLEL_BUNDLE}" PARALLEL + typeset -Ua repositories # Used to keep track of cloned repositories to avoid + # trying to clone it multiple times. + for args in ${_PARALLEL_BUNDLE}; do + typeset -A bundle; -antigen-parse-args 'bundle' ${=args} + + if [[ ! -d ${bundle[dir]} && $repositories[(I)${bundle[url]}] == 0 ]]; then + WARN "Install in parallel ${bundle[name]}." PARALLEL + echo "Installing ${bundle[name]}!..." + # $bundle[url]'s format is "url|branch" as to create "$ANTIGEN_BUNDLES/bundle/name-branch", + # this way you may require multiple branches from the same repository. + -antigen-ensure-repo "${bundle[url]}" > /dev/null &! + pids+=($!) + else + WARN "Bundle ${bundle[name]} already cloned locally." PARALLEL + fi + + repositories+=(${bundle[url]}) + done + + # Wait for all background processes to end + while [[ $#pids > 0 ]]; do + for pid in $pids; do + # `ps` may diplay an error message such "Signal 18 (CONT) caught by ps + # (procps-ng version 3.3.9).", see https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=732410 + if [[ $(ps -o pid= -p $pid 2>/dev/null) == "" ]]; then + pids[$pids[(I)$pid]]=() + fi + done + sleep .5 + done + + builtin local bundle &> /dev/null + for bundle in ${_PARALLEL_BUNDLE[@]}; do + antigen-bundle $bundle + done + + + WARN "Parallel install done" PARALLEL + } + + # Hooks antigen-apply in order to release hooked functions + antigen-apply-parallel () { + WARN "Parallel pre-apply" PARALLEL PRE-APPLY + #antigen-remove-hook antigen-pre-apply-parallel + # Hooks antigen-bundle in order to parallel its execution. + antigen-bundle-parallel () { + TRACE "antigen-bundle-parallel: $@" PARALLEL + _PARALLEL_BUNDLE+=("${(j: :)${@}}") + } + antigen-add-hook antigen-bundle antigen-bundle-parallel replace + } + antigen-add-hook antigen-apply antigen-apply-parallel pre once + + antigen-apply-parallel-execute () { + WARN "Parallel replace-apply" PARALLEL REPLACE-APPLY + antigen-remove-hook antigen-bundle-parallel + # Process all parallel bundles. + antigen-bundle-parallel-execute + + unset _PARALLEL_BUNDLE + antigen-remove-hook antigen-apply-parallel-execute + antigen-apply + } + antigen-add-hook antigen-apply antigen-apply-parallel-execute replace once +} +typeset -ga _ZCACHE_BUNDLE_SOURCE _ZCACHE_CAPTURE_BUNDLE +typeset -g _ZCACHE_CAPTURE_PREFIX + +# Generates cache from listed bundles. +# +# Iterates over _ANTIGEN_BUNDLE_RECORD and join all needed sources into one, +# if this is done through -antigen-load-list. +# Result is stored in ANTIGEN_CACHE. +# +# _ANTIGEN_BUNDLE_RECORD and fpath is stored in cache. +# +# Usage +# -zcache-generate-cache +# +# Returns +# Nothing. Generates ANTIGEN_CACHE +-antigen-cache-generate () { + local -aU _fpath _PATH _sources + local record + + LOG "Gonna generate cache for $_ZCACHE_BUNDLE_SOURCE" + for record in $_ZCACHE_BUNDLE_SOURCE; do + record=${record:A} + # LOG "Caching $record" + if [[ -f $record ]]; then + # Adding $'\n' as a suffix as j:\n: doesn't work inside a heredoc. + if [[ $_ANTIGEN_THEME_COMPAT == true && "$record" == *.zsh-theme* ]]; then + local compat="${record:A}.antigen-compat" + echo "# Generated by Antigen. Do not edit!" >! "$compat" + cat $record | sed -Ee '/\{$/,/^\}/!{ + s/^local // + }' >>! "$compat" + record="$compat" + fi + _sources+=("source '${record}';"$'\n') + elif [[ -d $record ]]; then + _PATH+=("${record}") + _fpath+=("${record}") + fi + done + +cat > $ANTIGEN_CACHE <! "$ANTIGEN_RSRC" + for rsrc in $ANTIGEN_CHECK_FILES; do + zcompile $rsrc + done + } &! + + return true +} + +# Initializes caching mechanism. +# +# Hooks `antigen-bundle` and `antigen-apply` in order to defer bundle install +# and load. All bundles are loaded from generated cache rather than dynamically +# as these are bundled. +# +# Usage +# -antigen-cache-init +# Returns +# Nothing +-antigen-cache-init () { + if -antigen-interactive-mode; then + return 1 + fi + + _ZCACHE_CAPTURE_PREFIX=${_ZCACHE_CAPTURE_PREFIX:-"--zcache-"} + _ZCACHE_BUNDLE_SOURCE=(); _ZCACHE_CAPTURE_BUNDLE=() + + # Cache auto config files to check for changes (.zshrc, .antigenrc etc) + -antigen-set-default ANTIGEN_AUTO_CONFIG true + + # Default cache path. + -antigen-set-default ANTIGEN_CACHE $ADOTDIR/init.zsh + -antigen-set-default ANTIGEN_RSRC $ADOTDIR/.resources + if [[ $ANTIGEN_CACHE == false ]]; then + return 1 + fi + + return 0 +} + +-antigen-cache-execute () { + # Main function. Deferred antigen-apply. + antigen-apply-cached () { + # TRACE "APPLYING CACHE" EXT + # Auto determine check_files + # There always should be 5 steps from original source as the correct way is to use + # `antigen` wrapper not `antigen-apply` directly and it's called by an extension. + LOG "TRACE: ${funcfiletrace}" + if [[ $ANTIGEN_AUTO_CONFIG == true && $#ANTIGEN_CHECK_FILES -eq 0 ]]; then + ANTIGEN_CHECK_FILES+=(~/.zshrc) + if [[ $#funcfiletrace -ge 6 ]]; then + ANTIGEN_CHECK_FILES+=("${${funcfiletrace[6]%:*}##* }") + fi + fi + + # Generate and compile cache + -antigen-cache-generate + [[ -f "$ANTIGEN_CACHE" ]] && source "$ANTIGEN_CACHE"; + + # Commented out in order to have a working `cache-gen` command + #unset _ZCACHE_BUNDLE_SOURCE + unset _ZCACHE_CAPTURE_BUNDLE _ZCACHE_CAPTURE_FUNCTIONS + + # Release all hooked functions + antigen-remove-hook -antigen-load-env-cached + antigen-remove-hook -antigen-load-source-cached + antigen-remove-hook antigen-bundle-cached + } + + antigen-add-hook antigen-apply antigen-apply-cached post once + + # Defer antigen-bundle. + antigen-bundle-cached () { + _ZCACHE_CAPTURE_BUNDLE+=("${(j: :)${@}}") + } + antigen-add-hook antigen-bundle antigen-bundle-cached pre + + # Defer loading. + -antigen-load-env-cached () { + local bundle + typeset -A bundle; bundle=($@) + local location=${bundle[dir]}/${bundle[loc]} + + # Load to path if there is no sourceable + if [[ ${bundle[loc]} == "/" ]]; then + _ZCACHE_BUNDLE_SOURCE+=("${location}") + return + fi + + _ZCACHE_BUNDLE_SOURCE+=("${location}") + } + antigen-add-hook -antigen-load-env -antigen-load-env-cached replace + + # Defer sourcing. + -antigen-load-source-cached () { + _ZCACHE_BUNDLE_SOURCE+=($@) + } + antigen-add-hook -antigen-load-source -antigen-load-source-cached replace + + return 0 +} + +# Generate static-cache file at $ANTIGEN_CACHE using currently loaded +# bundles from $_ANTIGEN_BUNDLE_RECORD +# +# Usage +# antigen-cache-gen +# +# Returns +# Nothing +antigen-cache-gen () { + -antigen-cache-generate +} +#compdef _antigen +# Setup antigen's autocompletion +_antigen () { + local -a _1st_arguments + _1st_arguments=( + 'apply:Load all bundle completions' + 'bundle:Install and load the given plugin' + 'bundles:Bulk define bundles' + 'cleanup:Clean up the clones of repos which are not used by any bundles currently loaded' + 'cache-gen:Generate cache' + 'init:Load Antigen configuration from file' + 'list:List out the currently loaded bundles' + 'purge:Remove a cloned bundle from filesystem' + 'reset:Clears cache' + 'restore:Restore the bundles state as specified in the snapshot' + 'revert:Revert the state of all bundles to how they were before the last antigen update' + 'selfupdate:Update antigen itself' + 'snapshot:Create a snapshot of all the active clones' + 'theme:Switch the prompt theme' + 'update:Update all bundles' + 'use:Load any (supported) zsh pre-packaged framework' + ); + + _1st_arguments+=( + 'help:Show this message' + 'version:Display Antigen version' + ) + + __bundle() { + _arguments \ + '--loc[Path to the location ]' \ + '--url[Path to the repository ]' \ + '--branch[Git branch name]' \ + '--no-local-clone[Do not create a clone]' + } + __list() { + _arguments \ + '--simple[Show only bundle name]' \ + '--short[Show only bundle name and branch]' \ + '--long[Show bundle records]' + } + + + __cleanup() { + _arguments \ + '--force[Do not ask for confirmation]' + } + + _arguments '*:: :->command' + + if (( CURRENT == 1 )); then + _describe -t commands "antigen command" _1st_arguments + return + fi + + local -a _command_args + case "$words[1]" in + bundle) + __bundle + ;; + use) + compadd "$@" "oh-my-zsh" "prezto" + ;; + cleanup) + __cleanup + ;; + (update|purge) + compadd $(type -f \-antigen-get-bundles &> /dev/null || antigen &> /dev/null; -antigen-get-bundles --simple 2> /dev/null) + ;; + theme) + compadd $(type -f \-antigen-get-themes &> /dev/null || antigen &> /dev/null; -antigen-get-themes 2> /dev/null) + ;; + list) + __list + ;; + esac +} +zmodload zsh/datetime +ANTIGEN_DEBUG_LOG=${ANTIGEN_DEBUG_LOG:-${ADOTDIR:-$HOME/.antigen}/debug.log} +LOG () { + local PREFIX="[LOG][${EPOCHREALTIME}]" + echo "${PREFIX} ${funcfiletrace[1]}\n${PREFIX} $@" >> $ANTIGEN_DEBUG_LOG +} + +ERR () { + local PREFIX="[ERR][${EPOCHREALTIME}]" + echo "${PREFIX} ${funcfiletrace[1]}\n${PREFIX} $@" >> $ANTIGEN_DEBUG_LOG +} + +WARN () { + local PREFIX="[WRN][${EPOCHREALTIME}]" + echo "${PREFIX} ${funcfiletrace[1]}\n${PREFIX} $@" >> $ANTIGEN_DEBUG_LOG +} + +TRACE () { + local PREFIX="[TRA][${EPOCHREALTIME}]" + echo "${PREFIX} ${funcfiletrace[1]}\n${PREFIX} $@\n${PREFIX} ${(j:\n:)funcstack}" >> $ANTIGEN_DEBUG_LOG +} +-antigen-env-setup diff --git a/shell-config/install-zsh.sh b/shell-config/install-zsh.sh new file mode 100755 index 0000000..c5e9fb2 --- /dev/null +++ b/shell-config/install-zsh.sh @@ -0,0 +1,108 @@ +#!/bin/bash +# ORION Infrastructure - Zsh Setup Script +# Installs Oh My Zsh + Antigen + zsh-users plugins + +set -e + +echo "╔═══════════════════════════════════════════════════════════════╗" +echo "β•‘ πŸš€ ORION Infrastructure - Zsh Setup β•‘" +echo "β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•" +echo "" + +# Check if running as root +if [ "$EUID" -ne 0 ]; then + SUDO="sudo" +else + SUDO="" +fi + +# 1. Install Zsh +echo "πŸ“¦ Installing Zsh..." +if ! command -v zsh &> /dev/null; then + if command -v apt-get &> /dev/null; then + $SUDO apt-get update && $SUDO apt-get install -y zsh git curl wget jq + elif command -v yum &> /dev/null; then + $SUDO yum install -y zsh git curl wget jq + elif command -v dnf &> /dev/null; then + $SUDO dnf install -y zsh git curl wget jq + else + echo "❌ Unsupported package manager. Please install zsh manually." + exit 1 + fi +else + echo "βœ… Zsh already installed: $(zsh --version)" +fi + +# 2. Install Oh My Zsh +echo "" +echo "πŸ“¦ Installing Oh My Zsh..." +if [ ! -d "$HOME/.oh-my-zsh" ]; then + sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended + echo "βœ… Oh My Zsh installed" +else + echo "βœ… Oh My Zsh already installed" +fi + +# 3. Install Antigen +echo "" +echo "πŸ“¦ Installing Antigen..." +if [ ! -f "$HOME/antigen.zsh" ]; then + curl -L git.io/antigen > "$HOME/antigen.zsh" + echo "βœ… Antigen installed" +else + echo "βœ… Antigen already installed" +fi + +# 4. Backup existing .zshrc +if [ -f "$HOME/.zshrc" ]; then + echo "" + echo "πŸ“ Backing up existing .zshrc to .zshrc.backup.$(date +%Y%m%d_%H%M%S)" + cp "$HOME/.zshrc" "$HOME/.zshrc.backup.$(date +%Y%m%d_%H%M%S)" +fi + +# 5. Install ORION .zshrc +echo "" +echo "πŸ“ Installing ORION .zshrc configuration..." +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cp "$SCRIPT_DIR/.zshrc" "$HOME/.zshrc" +cp "$SCRIPT_DIR/antigen.zsh" "$HOME/antigen.zsh" +echo "βœ… Configuration installed" + +# 6. Change default shell to zsh (optional) +echo "" +read -p "⚠️ Change default shell to zsh? (requires logout to take effect) [y/N]: " -n 1 -r +echo +if [[ $REPLY =~ ^[Yy]$ ]]; then + if command -v chsh &> /dev/null; then + $SUDO chsh -s $(which zsh) $USER + echo "βœ… Default shell changed to zsh (restart your session)" + else + echo "⚠️ chsh command not found. Add 'exec zsh' to your .bashrc to auto-switch" + fi +fi + +echo "" +echo "╔═══════════════════════════════════════════════════════════════╗" +echo "β•‘ βœ… Installation Complete! β•‘" +echo "β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•" +echo "" +echo "🎯 Next steps:" +echo " 1. Start zsh: zsh" +echo " 2. Or logout and login again if you changed default shell" +echo " 3. Plugins will auto-install on first run" +echo "" +echo "πŸ“š Included features:" +echo " βœ… Oh My Zsh with 14+ plugins" +echo " βœ… Antigen plugin manager" +echo " βœ… zsh-users/zsh-syntax-highlighting" +echo " βœ… zsh-users/zsh-autosuggestions" +echo " βœ… zsh-users/zsh-completions" +echo " βœ… zsh-users/zsh-history-substring-search" +echo " βœ… Custom ORION aliases and functions" +echo "" +echo "πŸ’‘ Try these commands:" +echo " orion-status # Check ORION infrastructure status" +echo " deploy # Quick deploy" +echo " orion # cd to ORION root" +echo " tf, ans, k8s # Navigate to directories" +echo "" diff --git a/terraform/README.md b/terraform/README.md new file mode 100644 index 0000000..d7d1fbc --- /dev/null +++ b/terraform/README.md @@ -0,0 +1,222 @@ +# ORION Terraform Infrastructure + +Infrastructure as Code for the ORION Dell R730 Proxmox environment. + +## πŸš€ Quick Start + +### Prerequisites + +1. **Terraform** installed (>= 1.6.0) + ```bash + # Install Terraform + wget https://releases.hashicorp.com/terraform/1.7.0/terraform_1.7.0_linux_amd64.zip + unzip terraform_1.7.0_linux_amd64.zip + sudo mv terraform /usr/local/bin/ + ``` + +2. **Proxmox API Token** created + ```bash + # On Proxmox host, create API token: + pveum user add terraform@pam + pveum role add TerraformRole -privs "VM.Allocate VM.Clone VM.Config.CDROM VM.Config.CPU VM.Config.Cloudinit VM.Config.Disk VM.Config.HWType VM.Config.Memory VM.Config.Network VM.Config.Options VM.Monitor VM.Audit VM.PowerMgmt Datastore.AllocateSpace Datastore.Audit Pool.Allocate Sys.Audit Sys.Console Sys.Modify" + pveum aclmod / -user terraform@pam -role TerraformRole + pveum user token add terraform@pam terraform-token --privsep=0 + + # Save the token ID and secret that are displayed + ``` + +3. **Cloud-init template** in Proxmox + ```bash + # Create Ubuntu 24.04 cloud-init template + # (See detailed instructions in docs/proxmox-cloud-init-template.md) + ``` + +### Setup + +1. **Copy and configure variables:** + ```bash + cp terraform.tfvars.example terraform.tfvars + nano terraform.tfvars + + # Update: + # - proxmox_api_token_id + # - proxmox_api_token_secret + # - vm_ssh_keys + ``` + +2. **Initialize Terraform:** + ```bash + terraform init + ``` + +3. **Plan deployment:** + ```bash + terraform plan + ``` + +4. **Apply configuration:** + ```bash + terraform apply + ``` + +## πŸ“ Directory Structure + +``` +terraform/ +β”œβ”€β”€ providers.tf # Provider configuration +β”œβ”€β”€ variables.tf # Variable definitions +β”œβ”€β”€ main.tf # Main infrastructure (to be created) +β”œβ”€β”€ outputs.tf # Output values (to be created) +β”œβ”€β”€ terraform.tfvars.example # Example variables +β”œβ”€β”€ terraform.tfvars # Actual variables (gitignored) +β”œβ”€β”€ modules/ +β”‚ β”œβ”€β”€ proxmox-vm/ # Reusable VM module (to be created) +β”‚ β”œβ”€β”€ k8s-cluster/ # K8s cluster module (to be created) +β”‚ └── networking/ # Network module (to be created) +└── environments/ + β”œβ”€β”€ dev/ # Development environment + β”œβ”€β”€ staging/ # Staging environment + └── production/ # Production environment +``` + +## 🎯 What Gets Deployed + +When you run `terraform apply`, the following VMs will be created: + +### NetBox (VM 500) +- **Purpose**: IP Address Management and network documentation +- **Resources**: 4 cores, 8GB RAM, 100GB disk +- **IP**: 192.168.100.50 +- **Services**: NetBox web UI, PostgreSQL, Redis + +### Kubernetes Cluster (VMs 600-603) +- **Master** (VM 600): 4 cores, 8GB RAM +- **Workers** (VMs 601-603): 4 cores, 16GB RAM each +- **IP Range**: 192.168.100.60-63 + +## πŸ”§ Common Operations + +### Check Current State +```bash +terraform show +terraform state list +``` + +### View Planned Changes +```bash +terraform plan +``` + +### Apply Changes +```bash +terraform apply + +# Or auto-approve (skip confirmation) +terraform apply -auto-approve +``` + +### Destroy Infrastructure +```bash +# Destroy specific resource +terraform destroy -target=module.netbox_vm + +# Destroy everything +terraform destroy +``` + +### Update a Single VM +```bash +# Taint a resource to force recreation +terraform taint module.netbox_vm.proxmox_vm_qemu.vm +terraform apply +``` + +### Import Existing VM +```bash +# Import an existing VM into Terraform state +terraform import module.router_vm.proxmox_vm_qemu.vm orion-pve/qemu/200 +``` + +## πŸ“Š Outputs + +After applying, Terraform will output useful information: + +```bash +terraform output + +# Example outputs: +# netbox_ip = "192.168.100.50" +# netbox_url = "http://192.168.100.50:8000" +# k8s_master_ip = "192.168.100.60" +# k8s_worker_ips = ["192.168.100.61", "192.168.100.62", "192.168.100.63"] +``` + +## πŸ” Security + +- **Never commit** `terraform.tfvars` or `*.tfstate` files +- **Use API tokens** instead of passwords +- **Encrypt state** if using remote backend +- **Limit token permissions** to minimum required + +## πŸ› Troubleshooting + +### "Error acquiring the state lock" +```bash +# Force unlock (use with caution) +terraform force-unlock +``` + +### "Error creating VM: timeout while waiting" +```bash +# Increase timeout in provider configuration +# Or check Proxmox host resources +``` + +### "Template not found" +```bash +# Ensure cloud-init template exists: +qm list | grep template + +# Or create it (see docs) +``` + +### API Token Permission Denied +```bash +# Verify token permissions: +pveum user token permissions terraform@pam terraform-token +``` + +## πŸ”„ Integration with Ansible + +After Terraform creates VMs, use Ansible to configure them: + +```bash +# Generate Ansible inventory from Terraform outputs +terraform output -json > ../ansible/inventory/terraform.json + +# Run Ansible playbooks +cd ../ansible +ansible-playbook -i inventory/hosts.yml playbooks/site.yml +``` + +## πŸ“š Next Steps + +1. **Create main.tf** - Define your infrastructure +2. **Customize modules** - Tailor VM configurations +3. **Set up remote state** - Use S3 or Consul backend +4. **Integrate with CI/CD** - Automate deployments +5. **Add monitoring** - Track infrastructure changes + +## πŸ“– Documentation + +- [Terraform Proxmox Provider](https://registry.terraform.io/providers/Telmate/proxmox/latest/docs) +- [Main Architecture](../INFRASTRUCTURE_AS_CODE_ARCHITECTURE.md) +- [ORION Overview](../README.md) + +## ⚠️ Important Notes + +- Always run `terraform plan` before `apply` +- Review changes carefully before confirming +- Keep state files secure and backed up +- Test in dev environment first +- Document any manual changes outside Terraform 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 +} diff --git a/terraform/providers.tf b/terraform/providers.tf new file mode 100644 index 0000000..c3c82a2 --- /dev/null +++ b/terraform/providers.tf @@ -0,0 +1,67 @@ +# Terraform Proxmox Provider Configuration +# ORION Infrastructure as Code + +terraform { + required_version = ">= 1.6.0" + + required_providers { + proxmox = { + source = "telmate/proxmox" + version = "~> 2.9.14" + } + } + + # Backend configuration for state management + # Uncomment and configure based on your needs + + # Option 1: Local backend (default) + # backend "local" { + # path = "terraform.tfstate" + # } + + # Option 2: S3-compatible backend (MinIO, AWS S3, etc.) + # backend "s3" { + # bucket = "orion-terraform-state" + # key = "infrastructure/terraform.tfstate" + # region = "us-east-1" + # endpoint = "https://minio.orion.local" + # skip_credentials_validation = true + # skip_metadata_api_check = true + # force_path_style = true + # } + + # Option 3: Consul backend + # backend "consul" { + # address = "192.168.100.1:8500" + # scheme = "http" + # path = "orion/terraform/state" + # } +} + +# Proxmox Provider +provider "proxmox" { + pm_api_url = var.proxmox_api_url + pm_api_token_id = var.proxmox_api_token_id + pm_api_token_secret = var.proxmox_api_token_secret + + # Or use username/password (less secure) + # pm_user = var.proxmox_user + # pm_password = var.proxmox_password + + # TLS verification + pm_tls_insecure = var.proxmox_tls_insecure + + # Logging + pm_log_enable = true + pm_log_file = "terraform-plugin-proxmox.log" + pm_log_levels = { + _default = "debug" + _capturelog = "" + } + + # Timeout for API calls + pm_timeout = 600 + + # Parallel operations + pm_parallel = 2 +} diff --git a/terraform/terraform.tfvars.example b/terraform/terraform.tfvars.example new file mode 100644 index 0000000..d221f6f --- /dev/null +++ b/terraform/terraform.tfvars.example @@ -0,0 +1,84 @@ +# Terraform Variables - ORION Infrastructure +# Copy this file to terraform.tfvars and fill in your values +# DO NOT commit terraform.tfvars to git (it's in .gitignore) + +# ============================================================================= +# Proxmox Connection (REQUIRED) +# ============================================================================= + +# Method 1: API Token (Recommended - more secure) +proxmox_api_token_id = "terraform@pam!terraform-token" +proxmox_api_token_secret = "your-token-secret-here" + +# Method 2: Username/Password (Less secure - not recommended) +# proxmox_user = "root@pam" +# proxmox_password = "your-password-here" + +# Proxmox settings +proxmox_api_url = "https://192.168.100.10:8006/api2/json" +proxmox_node = "orion-pve" +proxmox_tls_insecure = true # Set to false if using valid SSL cert + +# ============================================================================= +# Network Configuration +# ============================================================================= + +network_gateway = "192.168.100.1" +network_dns = ["1.1.1.1", "8.8.8.8"] +network_domain = "orion.local" + +# ============================================================================= +# SSH Access +# ============================================================================= + +vm_ssh_keys = [ + "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC... user@workstation", + # Add more SSH public keys here +] + +# ============================================================================= +# Storage +# ============================================================================= + +vm_storage_pool = "local-lvm" +vm_iso_storage = "local" + +# ============================================================================= +# NetBox VM +# ============================================================================= + +enable_netbox = true + +netbox_vm_id = 500 +netbox_cores = 4 +netbox_memory = 8192 +netbox_disk_size = "100G" +netbox_ip_address = "192.168.100.50" + +# ============================================================================= +# Kubernetes Cluster +# ============================================================================= + +enable_k8s_cluster = true + +k8s_master_count = 1 +k8s_worker_count = 3 +k8s_master_cores = 4 +k8s_master_memory = 8192 +k8s_worker_cores = 4 +k8s_worker_memory = 16384 +k8s_disk_size = "100G" + +k8s_master_vm_id = 600 +k8s_worker_vm_id_start = 601 +k8s_ip_range_start = "192.168.100.60" + +# ============================================================================= +# General Settings +# ============================================================================= + +environment = "production" +auto_start = true +enable_monitoring = true + +tags = ["terraform", "orion", "iac"] diff --git a/terraform/variables.tf b/terraform/variables.tf new file mode 100644 index 0000000..c29d03c --- /dev/null +++ b/terraform/variables.tf @@ -0,0 +1,250 @@ +# Terraform Variables for ORION Infrastructure +# Define all input variables here + +# ============================================================================= +# Proxmox Connection +# ============================================================================= + +variable "proxmox_api_url" { + description = "Proxmox API URL" + type = string + default = "https://192.168.100.10:8006/api2/json" +} + +variable "proxmox_api_token_id" { + description = "Proxmox API token ID" + type = string + sensitive = true +} + +variable "proxmox_api_token_secret" { + description = "Proxmox API token secret" + type = string + sensitive = true +} + +variable "proxmox_tls_insecure" { + description = "Skip TLS verification (use for self-signed certs)" + type = bool + default = true +} + +variable "proxmox_node" { + description = "Proxmox node name" + type = string + default = "orion-pve" +} + +# ============================================================================= +# Network Configuration +# ============================================================================= + +variable "network_gateway" { + description = "Default gateway for VMs" + type = string + default = "192.168.100.1" +} + +variable "network_dns" { + description = "DNS servers for VMs" + type = list(string) + default = ["1.1.1.1", "8.8.8.8"] +} + +variable "network_domain" { + description = "DNS domain for VMs" + type = string + default = "orion.local" +} + +variable "network_vlan_id" { + description = "VLAN ID (0 = no VLAN)" + type = number + default = 0 +} + +# ============================================================================= +# VM Defaults +# ============================================================================= + +variable "vm_default_user" { + description = "Default username for cloud-init" + type = string + default = "ubuntu" +} + +variable "vm_ssh_keys" { + description = "SSH public keys for VM access" + type = list(string) + default = [] +} + +variable "vm_storage_pool" { + description = "Storage pool for VM disks" + type = string + default = "local-lvm" +} + +variable "vm_iso_storage" { + description = "Storage for ISO files" + type = string + default = "local" +} + +# ============================================================================= +# NetBox VM Configuration +# ============================================================================= + +variable "netbox_vm_id" { + description = "VM ID for NetBox" + type = number + default = 500 +} + +variable "netbox_cores" { + description = "CPU cores for NetBox VM" + type = number + default = 4 +} + +variable "netbox_memory" { + description = "Memory (MB) for NetBox VM" + type = number + default = 8192 +} + +variable "netbox_disk_size" { + description = "Disk size (GB) for NetBox VM" + type = string + default = "100G" +} + +variable "netbox_ip_address" { + description = "IP address for NetBox" + type = string + default = "192.168.100.50" +} + +variable "netbox_cidr" { + description = "CIDR notation for NetBox IP" + type = number + default = 24 +} + +# ============================================================================= +# K8s Cluster Configuration +# ============================================================================= + +variable "k8s_master_vm_id" { + description = "Starting VM ID for K8s master nodes" + type = number + default = 600 +} + +variable "k8s_worker_vm_id_start" { + description = "Starting VM ID for K8s worker nodes" + type = number + default = 601 +} + +variable "k8s_master_count" { + description = "Number of K8s master nodes" + type = number + default = 1 +} + +variable "k8s_worker_count" { + description = "Number of K8s worker nodes" + type = number + default = 3 +} + +variable "k8s_master_cores" { + description = "CPU cores for K8s master nodes" + type = number + default = 4 +} + +variable "k8s_master_memory" { + description = "Memory (MB) for K8s master nodes" + type = number + default = 8192 +} + +variable "k8s_worker_cores" { + description = "CPU cores for K8s worker nodes" + type = number + default = 4 +} + +variable "k8s_worker_memory" { + description = "Memory (MB) for K8s worker nodes" + type = number + default = 16384 +} + +variable "k8s_disk_size" { + description = "Disk size for K8s nodes" + type = string + default = "100G" +} + +variable "k8s_ip_range_start" { + description = "Starting IP for K8s cluster" + type = string + default = "192.168.100.60" +} + +# ============================================================================= +# Tags and Metadata +# ============================================================================= + +variable "tags" { + description = "Tags to apply to all resources" + type = list(string) + default = ["terraform", "orion", "iac"] +} + +variable "environment" { + description = "Environment name (dev, staging, production)" + type = string + default = "production" +} + +# ============================================================================= +# Cloud-init Template +# ============================================================================= + +variable "cloud_init_template" { + description = "Cloud-init template name (must exist in Proxmox)" + type = string + default = "ubuntu-2404-cloudinit-template" +} + +# ============================================================================= +# Feature Flags +# ============================================================================= + +variable "enable_netbox" { + description = "Deploy NetBox VM" + type = bool + default = true +} + +variable "enable_k8s_cluster" { + description = "Deploy K8s cluster" + type = bool + default = true +} + +variable "enable_monitoring" { + description = "Install monitoring agents on VMs" + type = bool + default = true +} + +variable "auto_start" { + description = "Auto-start VMs on Proxmox boot" + type = bool + default = true +} diff --git a/vm-configs/README.md b/vm-configs/README.md new file mode 100644 index 0000000..e450fbe --- /dev/null +++ b/vm-configs/README.md @@ -0,0 +1,328 @@ +# ORION VM Configurations + +This directory contains NixOS configuration files for ORION virtual machines. + +## Directory Structure + +``` +vm-configs/ +β”œβ”€β”€ router-vm/ +β”‚ └── configuration.nix # NixOS + VyOS router configuration +└── ai-agent-vm/ + β”œβ”€β”€ configuration.nix # AI agent system configuration + └── autonomous_agent.py # AI monitoring agent +``` + +## VM Overview + +### Router VM (VM 200) + +**Purpose**: High-performance network router with BGP, firewall, DHCP, and DNS + +**Services**: +- BIRD2 BGP (AS 394955) +- VyOS routing +- Unbound DNS (DNS over TLS) +- Kea DHCP +- nftables firewall +- Prometheus node exporter + +**Network Interfaces**: +- eth0: WAN (DHCP from Telus) +- eth1: LAN (192.168.100.1/24) +- eth2: Guest (192.168.200.1/24) +- eth3: Management (192.168.1.1/24) + +**Configuration**: `router-vm/configuration.nix` + +### AI Agent VM (VM 300) + +**Purpose**: Autonomous network monitoring and management + +**Services**: +- Autonomous monitoring agent (Python) +- Prometheus server (port 9090) +- Grafana dashboards (port 3000) +- Alert manager +- Prometheus node exporter + +**Network**: +- eth0: LAN (192.168.100.20/24) + +**Configuration**: `ai-agent-vm/configuration.nix` + +## Installation + +### 1. Install NixOS Base System + +Boot VM from NixOS ISO and partition disks: + +```bash +# Partition disk +parted /dev/sda -- mklabel gpt +parted /dev/sda -- mkpart ESP fat32 1MiB 512MiB +parted /dev/sda -- set 1 esp on +parted /dev/sda -- mkpart primary 512MiB 100% + +# Format +mkfs.fat -F 32 -n boot /dev/sda1 +mkfs.ext4 -L nixos /dev/sda2 + +# Mount +mount /dev/disk/by-label/nixos /mnt +mkdir -p /mnt/boot +mount /dev/disk/by-label/boot /mnt/boot + +# Generate hardware config +nixos-generate-config --root /mnt +``` + +### 2. Copy Configuration + +For **Router VM**: +```bash +# Copy configuration from this repository +scp vm-configs/router-vm/configuration.nix nixos@VM_IP:/tmp/ +ssh nixos@VM_IP "sudo cp /tmp/configuration.nix /mnt/etc/nixos/" +``` + +For **AI Agent VM**: +```bash +# Copy both configuration and agent script +scp vm-configs/ai-agent-vm/configuration.nix nixos@VM_IP:/tmp/ +scp vm-configs/ai-agent-vm/autonomous_agent.py nixos@VM_IP:/tmp/ +ssh nixos@VM_IP "sudo cp /tmp/configuration.nix /mnt/etc/nixos/" +``` + +### 3. Install NixOS + +```bash +# Run installation +nixos-install + +# Set root password when prompted + +# Reboot +reboot +``` + +### 4. Post-Installation + +After first boot: + +```bash +# SSH into the VM +ssh admin@ + +# Update system (if needed) +sudo nixos-rebuild switch + +# Check services +systemctl status bird2 # Router VM only +systemctl status orion-agent # AI Agent VM only +systemctl status prometheus # AI Agent VM only +systemctl status grafana # AI Agent VM only +``` + +## Configuration Management + +### Updating Configurations + +Configurations are declarative - edit the `.nix` files and rebuild: + +```bash +# Edit configuration +vim /etc/nixos/configuration.nix + +# Test configuration (don't activate) +sudo nixos-rebuild test + +# Apply configuration +sudo nixos-rebuild switch + +# Rollback if needed +sudo nixos-rebuild --rollback +``` + +### Version Control + +Keep configurations in Git: + +```bash +# After making changes +cd /path/to/luci-macOSX-PROXMOX +git add vm-configs/ +git commit -m "Update VM configurations" +git push +``` + +## Customization + +### Router VM + +**Add BGP peer**: +Edit `router-vm/configuration.nix`: +```nix +protocol bgp new_peer { + local as 394955; + neighbor as ; + + ipv4 { + import all; + export where source = RTS_STATIC; + }; +} +``` + +**Add firewall rule**: +```nix +# In nftables.ruleset +iif eth1 tcp dport accept +``` + +**Change network ranges**: +```nix +networking.interfaces.eth1.ipv4.addresses = [{ + address = "192.168.X.1"; + prefixLength = 24; +}]; +``` + +### AI Agent VM + +**Adjust monitoring interval**: +Edit `ai-agent-vm/autonomous_agent.py`: +```python +self.check_interval = 60 # seconds +``` + +**Add monitoring targets**: +Edit `ai-agent-vm/configuration.nix`: +```nix +services.prometheus.scrapeConfigs = [ + { + job_name = "new-target"; + static_configs = [{ + targets = [ "IP:PORT" ]; + }]; + } +]; +``` + +**Change Grafana password**: +```nix +services.grafana.settings.security.admin_password = "NEW_PASSWORD"; +``` + +## Troubleshooting + +### Router VM + +**BGP not working**: +```bash +# Check BIRD status +birdc show protocols + +# Check BIRD logs +journalctl -u bird2 -f + +# Reload BIRD config +birdc configure +``` + +**Firewall blocking traffic**: +```bash +# View rules +nft list ruleset + +# Check counters +nft list ruleset -a + +# Temporarily disable (for testing only!) +systemctl stop nftables +``` + +### AI Agent VM + +**Agent not collecting metrics**: +```bash +# Check agent logs +journalctl -u orion-agent -f + +# Check if Prometheus is scraping +curl http://localhost:9090/api/v1/targets + +# Manually test router connectivity +curl http://192.168.100.1:9100/metrics +``` + +**Grafana not accessible**: +```bash +# Check Grafana status +systemctl status grafana + +# Check firewall +nft list ruleset | grep 3000 + +# View Grafana logs +journalctl -u grafana -f +``` + +## Network Diagram + +``` +Internet (Telus) + β”‚ + β”‚ WAN (eth0) - DHCP + β”‚ +β”Œβ”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Router VM (200) β”‚ +β”‚ 192.168.100.1 β”‚ +β”‚ β”‚ +β”‚ β€’ BGP (AS 394955) β”‚ +β”‚ β€’ Firewall (nftables) β”‚ +β”‚ β€’ DHCP Server β”‚ +β”‚ β€’ DNS (Unbound) β”‚ +β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ LAN (eth1) + β”‚ 192.168.100.0/24 + β”‚ + β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ β”‚ β”‚ β”‚ +β”Œβ”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β” +β”‚ AI Agent β”‚ β”‚ macOS β”‚ β”‚ Proxmox β”‚ β”‚ Clients β”‚ +β”‚ (300) β”‚ β”‚ (100) β”‚ β”‚ Host β”‚ β”‚ DHCP β”‚ +β”‚ .100.20 β”‚ β”‚ .100.X β”‚ β”‚ .100.10 β”‚ β”‚ .100.100+β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +## Security Notes + +1. **SSH Keys**: Add your public keys to configuration: + ```nix + users.users.admin.openssh.authorizedKeys.keys = [ + "ssh-rsa AAAAB3... your-key-here" + ]; + ``` + +2. **Firewall**: Default deny policy - only explicitly allowed traffic passes + +3. **Updates**: Automatic weekly updates enabled: + ```nix + system.autoUpgrade.enable = true; + ``` + +4. **Change Default Passwords**: + - Grafana: admin / orion2025 β†’ Change immediately! + - SSH: Disable password auth, use keys only + +## Support + +For issues or questions: +1. Check the main documentation: `../ORION_HYBRID_ARCHITECTURE.md` +2. Review NixOS manual: https://nixos.org/manual/nixos/stable/ +3. Check service logs: `journalctl -u -f` + +--- + +**Last Updated**: 2025-01-20 diff --git a/vm-configs/ai-agent-vm/autonomous_agent.py b/vm-configs/ai-agent-vm/autonomous_agent.py new file mode 100755 index 0000000..ccc1846 --- /dev/null +++ b/vm-configs/ai-agent-vm/autonomous_agent.py @@ -0,0 +1,442 @@ +#!/usr/bin/env python3 +""" +ORION Autonomous Network Agent +Monitors and manages network infrastructure with AI intelligence + +Features: +- Real-time network monitoring via Prometheus metrics +- Autonomous issue detection and remediation +- BGP session health monitoring +- Bandwidth analysis and reporting +- Automated alert generation +- Self-healing capabilities +""" + +import time +import requests +import json +import logging +import subprocess +from datetime import datetime +from typing import Dict, List, Any, Optional +from dataclasses import dataclass +from enum import Enum + +# Configure logging +logging.basicConfig( + level=logging.INFO, + format='%(asctime)s [%(levelname)s] %(message)s', + handlers=[ + logging.FileHandler('/var/log/orion-agent.log'), + logging.StreamHandler() + ] +) +logger = logging.getLogger(__name__) + + +class AlertSeverity(Enum): + """Alert severity levels""" + INFO = "info" + WARNING = "warning" + CRITICAL = "critical" + + +@dataclass +class NetworkMetrics: + """Network metrics snapshot""" + timestamp: datetime + wan_bandwidth_mbps: float + lan_bandwidth_mbps: float + bgp_sessions_up: int + bgp_sessions_total: int + packet_loss_percent: float + latency_ms: float + active_connections: int + cpu_usage_percent: float + memory_usage_percent: float + + +@dataclass +class Alert: + """Network alert""" + severity: AlertSeverity + title: str + message: str + timestamp: datetime + resolved: bool = False + + +class PrometheusClient: + """Client for querying Prometheus metrics""" + + def __init__(self, url: str = "http://localhost:9090"): + self.url = url + self.session = requests.Session() + + def query(self, query: str) -> Optional[Dict]: + """Execute PromQL query""" + try: + response = self.session.get( + f"{self.url}/api/v1/query", + params={"query": query}, + timeout=10 + ) + response.raise_for_status() + data = response.json() + + if data["status"] == "success": + return data["data"] + return None + except Exception as e: + logger.error(f"Prometheus query failed: {e}") + return None + + def query_range(self, query: str, start: int, end: int, step: str = "15s") -> Optional[Dict]: + """Execute PromQL range query""" + try: + response = self.session.get( + f"{self.url}/api/v1/query_range", + params={ + "query": query, + "start": start, + "end": end, + "step": step + }, + timeout=10 + ) + response.raise_for_status() + data = response.json() + + if data["status"] == "success": + return data["data"] + return None + except Exception as e: + logger.error(f"Prometheus range query failed: {e}") + return None + + +class NetworkMonitor: + """Network monitoring and analysis""" + + def __init__(self, router_ip: str = "192.168.100.1"): + self.router_ip = router_ip + self.prometheus = PrometheusClient() + self.alerts: List[Alert] = [] + + def collect_metrics(self) -> NetworkMetrics: + """Collect current network metrics""" + logger.debug("Collecting network metrics...") + + # Query Prometheus for metrics + wan_rx = self._query_metric('rate(node_network_receive_bytes_total{device="eth0"}[5m])') or 0 + lan_rx = self._query_metric('rate(node_network_receive_bytes_total{device="eth1"}[5m])') or 0 + cpu_usage = self._query_metric('100 - (avg by (instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)') or 0 + memory_usage = self._query_metric('(1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100') or 0 + + # Get BGP session status + bgp_sessions = self._check_bgp_sessions() + + # Ping test for latency + latency = self._measure_latency("8.8.8.8") + + metrics = NetworkMetrics( + timestamp=datetime.now(), + wan_bandwidth_mbps=wan_rx * 8 / 1_000_000, # Convert to Mbps + lan_bandwidth_mbps=lan_rx * 8 / 1_000_000, + bgp_sessions_up=bgp_sessions.get("up", 0), + bgp_sessions_total=bgp_sessions.get("total", 3), + packet_loss_percent=0.0, # TODO: implement + latency_ms=latency, + active_connections=self._count_active_connections(), + cpu_usage_percent=cpu_usage, + memory_usage_percent=memory_usage + ) + + logger.info(f"Metrics: WAN={metrics.wan_bandwidth_mbps:.2f}Mbps, " + f"BGP={metrics.bgp_sessions_up}/{metrics.bgp_sessions_total}, " + f"CPU={metrics.cpu_usage_percent:.1f}%, " + f"MEM={metrics.memory_usage_percent:.1f}%") + + return metrics + + def _query_metric(self, query: str) -> Optional[float]: + """Query single metric value from Prometheus""" + result = self.prometheus.query(query) + if result and result.get("result"): + try: + return float(result["result"][0]["value"][1]) + except (IndexError, KeyError, ValueError): + return None + return None + + def _check_bgp_sessions(self) -> Dict[str, int]: + """Check BGP session status via birdc""" + try: + result = subprocess.run( + ["ssh", f"admin@{self.router_ip}", "birdc", "show", "protocols"], + capture_output=True, + text=True, + timeout=10 + ) + + if result.returncode == 0: + output = result.stdout + lines = output.split("\n") + + total = 0 + up = 0 + + for line in lines: + if "BGP" in line and "telus_gw" in line: + total += 1 + if "Established" in line: + up += 1 + + return {"total": total, "up": up} + + except Exception as e: + logger.error(f"BGP check failed: {e}") + + return {"total": 3, "up": 0} + + def _measure_latency(self, host: str) -> float: + """Measure ping latency to host""" + try: + result = subprocess.run( + ["ping", "-c", "3", "-W", "2", host], + capture_output=True, + text=True, + timeout=10 + ) + + if result.returncode == 0: + # Parse avg latency from output + for line in result.stdout.split("\n"): + if "avg" in line or "rtt" in line: + parts = line.split("/") + if len(parts) >= 5: + return float(parts[4]) + + except Exception as e: + logger.error(f"Latency measurement failed: {e}") + + return 0.0 + + def _count_active_connections(self) -> int: + """Count active network connections""" + try: + result = subprocess.run( + ["ss", "-tan", "state", "established"], + capture_output=True, + text=True, + timeout=5 + ) + + if result.returncode == 0: + lines = result.stdout.split("\n") + # Subtract header line + return max(0, len(lines) - 2) + + except Exception as e: + logger.error(f"Connection count failed: {e}") + + return 0 + + def analyze_metrics(self, metrics: NetworkMetrics): + """Analyze metrics and generate alerts""" + + # Check BGP sessions + if metrics.bgp_sessions_up < metrics.bgp_sessions_total: + self._create_alert( + AlertSeverity.CRITICAL, + "BGP Sessions Down", + f"Only {metrics.bgp_sessions_up}/{metrics.bgp_sessions_total} BGP sessions are established" + ) + + # Check high CPU usage + if metrics.cpu_usage_percent > 90: + self._create_alert( + AlertSeverity.WARNING, + "High CPU Usage", + f"CPU usage is {metrics.cpu_usage_percent:.1f}%" + ) + + # Check high memory usage + if metrics.memory_usage_percent > 95: + self._create_alert( + AlertSeverity.CRITICAL, + "Critical Memory Usage", + f"Memory usage is {metrics.memory_usage_percent:.1f}%" + ) + + # Check high latency + if metrics.latency_ms > 100: + self._create_alert( + AlertSeverity.WARNING, + "High Latency", + f"Network latency is {metrics.latency_ms:.1f}ms" + ) + + def _create_alert(self, severity: AlertSeverity, title: str, message: str): + """Create new alert""" + alert = Alert( + severity=severity, + title=title, + message=message, + timestamp=datetime.now() + ) + + # Check if similar alert already exists + for existing in self.alerts: + if existing.title == title and not existing.resolved: + logger.debug(f"Alert already exists: {title}") + return + + self.alerts.append(alert) + logger.warning(f"[{severity.value.upper()}] {title}: {message}") + + # Send notification (TODO: implement email/webhook) + self._send_notification(alert) + + def _send_notification(self, alert: Alert): + """Send alert notification""" + # TODO: Implement email/Slack/webhook notification + logger.info(f"Notification sent for: {alert.title}") + + def auto_remediate(self, metrics: NetworkMetrics): + """Attempt automatic remediation of issues""" + + # Restart BGP if all sessions are down + if metrics.bgp_sessions_up == 0 and metrics.bgp_sessions_total > 0: + logger.warning("All BGP sessions down, attempting restart...") + self._restart_bgp() + + def _restart_bgp(self): + """Restart BGP service""" + try: + logger.info("Restarting BIRD BGP service...") + result = subprocess.run( + ["ssh", f"admin@{self.router_ip}", "sudo", "systemctl", "restart", "bird2"], + capture_output=True, + text=True, + timeout=30 + ) + + if result.returncode == 0: + logger.info("BGP service restarted successfully") + self._create_alert( + AlertSeverity.INFO, + "BGP Service Restarted", + "Automatically restarted BGP service due to all sessions being down" + ) + else: + logger.error(f"BGP restart failed: {result.stderr}") + + except Exception as e: + logger.error(f"BGP restart failed: {e}") + + def generate_report(self, metrics: NetworkMetrics) -> str: + """Generate network status report""" + report = f""" +ORION Network Status Report +Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} + +=== Network Performance === +WAN Bandwidth: {metrics.wan_bandwidth_mbps:.2f} Mbps +LAN Bandwidth: {metrics.lan_bandwidth_mbps:.2f} Mbps +Latency: {metrics.latency_ms:.1f} ms +Packet Loss: {metrics.packet_loss_percent:.2f}% +Active Connections: {metrics.active_connections} + +=== BGP Routing === +Sessions Up: {metrics.bgp_sessions_up}/{metrics.bgp_sessions_total} +AS Number: 394955 + +=== System Resources === +CPU Usage: {metrics.cpu_usage_percent:.1f}% +Memory Usage: {metrics.memory_usage_percent:.1f}% + +=== Active Alerts === +""" + active_alerts = [a for a in self.alerts if not a.resolved] + if active_alerts: + for alert in active_alerts: + report += f"[{alert.severity.value.upper()}] {alert.title}: {alert.message}\n" + else: + report += "No active alerts\n" + + return report + + +class ORIONAgent: + """Main autonomous agent""" + + def __init__(self): + self.monitor = NetworkMonitor() + self.running = False + self.check_interval = 60 # seconds + + def start(self): + """Start the agent""" + logger.info("ORION Autonomous Agent starting...") + logger.info(f"Check interval: {self.check_interval}s") + + self.running = True + + try: + while self.running: + self._run_cycle() + time.sleep(self.check_interval) + + except KeyboardInterrupt: + logger.info("Agent stopped by user") + except Exception as e: + logger.error(f"Agent error: {e}") + raise + finally: + self.stop() + + def stop(self): + """Stop the agent""" + logger.info("ORION Autonomous Agent stopping...") + self.running = False + + def _run_cycle(self): + """Run one monitoring cycle""" + try: + # Collect metrics + metrics = self.monitor.collect_metrics() + + # Analyze for issues + self.monitor.analyze_metrics(metrics) + + # Attempt auto-remediation + self.monitor.auto_remediate(metrics) + + # Generate hourly report + if datetime.now().minute == 0: + report = self.monitor.generate_report(metrics) + logger.info(report) + + except Exception as e: + logger.error(f"Monitoring cycle failed: {e}") + + +def main(): + """Main entry point""" + print(""" +╔═══════════════════════════════════════════════════════════╗ +β•‘ β•‘ +β•‘ ORION Autonomous Network Agent v1.0 β•‘ +β•‘ β•‘ +β•‘ Intelligent monitoring and management for ORION system β•‘ +β•‘ β•‘ +β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β• +""") + + agent = ORIONAgent() + agent.start() + + +if __name__ == "__main__": + main() diff --git a/vm-configs/ai-agent-vm/configuration.nix b/vm-configs/ai-agent-vm/configuration.nix new file mode 100644 index 0000000..15bdb0f --- /dev/null +++ b/vm-configs/ai-agent-vm/configuration.nix @@ -0,0 +1,225 @@ +# NixOS Configuration for ORION AI Agent VM +# Dell R730 - VM 300 +# Purpose: Autonomous network monitoring and management + +{ config, pkgs, ... }: + +{ + imports = [ ./hardware-configuration.nix ]; + + # System + system.stateVersion = "24.11"; + networking.hostName = "orion-ai-agent"; + networking.domain = "lucia-ai.internal"; + + # Boot + boot.loader.grub.enable = true; + boot.loader.grub.device = "/dev/sda"; + + # Network + networking.interfaces.eth0.ipv4.addresses = [{ + address = "192.168.100.20"; + prefixLength = 24; + }]; + + networking.defaultGateway = "192.168.100.1"; + networking.nameservers = [ "192.168.100.1" "1.1.1.1" ]; + + # Firewall + networking.firewall = { + enable = true; + allowedTCPPorts = [ + 22 # SSH + 3000 # Grafana + 9090 # Prometheus + 9100 # Node exporter + ]; + }; + + # Services - Prometheus + services.prometheus = { + enable = true; + port = 9090; + + scrapeConfigs = [ + { + job_name = "orion-router"; + static_configs = [{ + targets = [ "192.168.100.1:9100" ]; + labels = { + alias = "router"; + }; + }]; + } + { + job_name = "orion-ai-agent"; + static_configs = [{ + targets = [ "localhost:9100" ]; + labels = { + alias = "ai-agent"; + }; + }]; + } + { + job_name = "proxmox"; + static_configs = [{ + targets = [ "192.168.100.10:9100" ]; + labels = { + alias = "proxmox-host"; + }; + }]; + } + ]; + + rules = [ + '' + groups: + - name: orion_alerts + interval: 30s + rules: + - alert: HighCPUUsage + expr: 100 - (avg by (instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 90 + for: 5m + labels: + severity: warning + annotations: + summary: "High CPU usage detected" + description: "CPU usage is above 90% for 5 minutes" + + - alert: HighMemoryUsage + expr: (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100 > 95 + for: 5m + labels: + severity: critical + annotations: + summary: "Critical memory usage" + description: "Memory usage is above 95%" + + - alert: RouterDown + expr: up{job="orion-router"} == 0 + for: 1m + labels: + severity: critical + annotations: + summary: "Router is down" + description: "Router is not responding to metrics collection" + '' + ]; + }; + + # Prometheus exporters + services.prometheus.exporters.node = { + enable = true; + enabledCollectors = [ "systemd" ]; + port = 9100; + }; + + # Grafana + services.grafana = { + enable = true; + settings = { + server = { + http_addr = "0.0.0.0"; + http_port = 3000; + }; + security = { + admin_user = "admin"; + admin_password = "orion2025"; # Change this! + }; + }; + + provision = { + enable = true; + datasources.settings.datasources = [{ + name = "Prometheus"; + type = "prometheus"; + url = "http://localhost:9090"; + isDefault = true; + }]; + }; + }; + + # SSH + services.openssh = { + enable = true; + settings.PermitRootLogin = "prohibit-password"; + settings.PasswordAuthentication = false; + }; + + # Autonomous Agent Service + systemd.services.orion-agent = { + description = "ORION Autonomous Network Agent"; + after = [ "network.target" "prometheus.service" ]; + wantedBy = [ "multi-user.target" ]; + + serviceConfig = { + Type = "simple"; + User = "orion-agent"; + Group = "orion-agent"; + ExecStart = "${pkgs.python3}/bin/python3 /opt/orion-agent/autonomous_agent.py"; + Restart = "on-failure"; + RestartSec = "10s"; + + # Security hardening + PrivateTmp = true; + NoNewPrivileges = true; + ProtectSystem = "strict"; + ProtectHome = true; + ReadWritePaths = [ "/var/log" ]; + }; + }; + + # Create orion-agent user + users.users.orion-agent = { + isSystemUser = true; + group = "orion-agent"; + description = "ORION Agent Service User"; + }; + + users.groups.orion-agent = {}; + + # Admin user + users.users.admin = { + isNormalUser = true; + extraGroups = [ "wheel" ]; + openssh.authorizedKeys.keys = [ + # Add your SSH public key here + ]; + }; + + # System packages + environment.systemPackages = with pkgs; [ + vim + wget + curl + htop + git + python3 + python3Packages.requests + python3Packages.prometheus-client + tmux + jq + ]; + + # Python environment for agent + environment.etc."orion-agent/autonomous_agent.py" = { + source = ./autonomous_agent.py; + mode = "0755"; + }; + + # Create /opt/orion-agent directory + systemd.tmpfiles.rules = [ + "d /opt/orion-agent 0755 orion-agent orion-agent -" + "L+ /opt/orion-agent/autonomous_agent.py - - - - /etc/orion-agent/autonomous_agent.py" + ]; + + # Enable sudo without password for wheel + security.sudo.wheelNeedsPassword = false; + + # Automatic system upgrades + system.autoUpgrade = { + enable = true; + allowReboot = false; + dates = "weekly"; + }; +} diff --git a/vm-configs/router-vm/configuration.nix b/vm-configs/router-vm/configuration.nix new file mode 100644 index 0000000..2385e94 --- /dev/null +++ b/vm-configs/router-vm/configuration.nix @@ -0,0 +1,318 @@ +# NixOS Configuration for ORION Router VM +# Dell R730 - VM 200 +# Purpose: High-performance routing with VyOS, BGP, firewall + +{ config, pkgs, ... }: + +{ + imports = [ ./hardware-configuration.nix ]; + + # System + system.stateVersion = "24.11"; + networking.hostName = "orion-router"; + networking.domain = "lucia-ai.internal"; + + # Boot + boot.loader.grub.enable = true; + boot.loader.grub.device = "/dev/sda"; + boot.kernelModules = [ "kvm-intel" ]; + + # Enable IP forwarding + boot.kernel.sysctl = { + "net.ipv4.ip_forward" = 1; + "net.ipv6.conf.all.forwarding" = 1; + "net.ipv4.conf.all.rp_filter" = 0; + "net.ipv4.conf.default.rp_filter" = 0; + }; + + # Network Interfaces + # eth0 = WAN (Telus Fiber) + # eth1 = LAN (Internal 192.168.100.0/24) + # eth2 = Guest (192.168.200.0/24) + # eth3 = Management (192.168.1.0/24) + + networking.interfaces = { + eth0.useDHCP = true; # WAN - get IP from Telus + + eth1.ipv4.addresses = [{ + address = "192.168.100.1"; + prefixLength = 24; + }]; + eth1.ipv6.addresses = [{ + address = "2602:F674:1000::1"; + prefixLength = 64; + }]; + + eth2.ipv4.addresses = [{ + address = "192.168.200.1"; + prefixLength = 24; + }]; + + eth3.ipv4.addresses = [{ + address = "192.168.1.1"; + prefixLength = 24; + }]; + }; + + # Firewall - use nftables + networking.firewall.enable = false; # We'll use nftables directly + networking.nftables.enable = true; + networking.nftables.ruleset = '' + table inet filter { + chain input { + type filter hook input priority 0; policy drop; + + # Accept loopback + iif lo accept + + # Accept established/related + ct state {established, related} accept + + # Accept ICMP + ip protocol icmp accept + ip6 nexthdr icmpv6 accept + + # Accept SSH from LAN + iif eth1 tcp dport 22 accept + iif eth3 tcp dport 22 accept + + # Accept DNS from LAN + iif eth1 udp dport 53 accept + iif eth1 tcp dport 53 accept + + # Accept DHCP + iif eth1 udp dport 67 accept + + # Accept BGP from WAN + iif eth0 tcp dport 179 accept + + # Drop everything else + counter drop + } + + chain forward { + type filter hook forward priority 0; policy drop; + + # Accept established/related + ct state {established, related} accept + + # Allow LAN to WAN + iif eth1 oif eth0 accept + + # Allow Guest to WAN (restricted) + iif eth2 oif eth0 accept + + # Drop everything else + counter drop + } + + chain output { + type filter hook output priority 0; policy accept; + } + } + + table ip nat { + chain postrouting { + type nat hook postrouting priority 100; policy accept; + + # NAT for LAN + oif eth0 ip saddr 192.168.100.0/24 masquerade + + # NAT for Guest + oif eth0 ip saddr 192.168.200.0/24 masquerade + } + } + ''; + + # Services + services.openssh = { + enable = true; + settings.PermitRootLogin = "prohibit-password"; + settings.PasswordAuthentication = false; + }; + + # DHCP Server + services.kea.dhcp4 = { + enable = true; + settings = { + interfaces-config = { + interfaces = [ "eth1" ]; + }; + lease-database = { + type = "memfile"; + persist = true; + name = "/var/lib/kea/dhcp4.leases"; + }; + subnet4 = [{ + id = 1; + subnet = "192.168.100.0/24"; + pools = [{ pool = "192.168.100.100 - 192.168.100.200"; }]; + option-data = [ + { + name = "routers"; + data = "192.168.100.1"; + } + { + name = "domain-name-servers"; + data = "192.168.100.1"; + } + ]; + }]; + }; + }; + + # DNS Server (Unbound) + services.unbound = { + enable = true; + settings = { + server = { + interface = [ "192.168.100.1" "127.0.0.1" ]; + access-control = [ + "192.168.100.0/24 allow" + "127.0.0.0/8 allow" + ]; + + # Forward to Cloudflare/Google + forward-zone = [ + { + name = "."; + forward-addr = [ + "1.1.1.1@853#cloudflare-dns.com" + "1.0.0.1@853#cloudflare-dns.com" + "8.8.8.8@853#dns.google" + "8.8.4.4@853#dns.google" + ]; + forward-tls-upstream = true; + } + ]; + }; + }; + }; + + # BGP with BIRD2 + services.bird2 = { + enable = true; + config = '' + log syslog all; + + router id 192.168.100.1; + + protocol device { + scan time 10; + } + + protocol direct { + ipv4; + ipv6; + } + + protocol kernel { + ipv4 { + import all; + export all; + }; + } + + protocol kernel { + ipv6 { + import all; + export all; + }; + } + + protocol static { + ipv4; + route 192.168.100.0/24 blackhole; + } + + # Telus BGP Peers + protocol bgp telus_gw1 { + local as 394955; + neighbor 206.75.1.127 as 6939; + + ipv4 { + import all; + export where source = RTS_STATIC; + }; + } + + protocol bgp telus_gw2 { + local as 394955; + neighbor 206.75.1.47 as 6939; + + ipv4 { + import all; + export where source = RTS_STATIC; + }; + } + + protocol bgp telus_gw3 { + local as 394955; + neighbor 206.75.1.48 as 6939; + + ipv4 { + import all; + export where source = RTS_STATIC; + }; + } + ''; + }; + + # Monitoring - node exporter for Prometheus + services.prometheus.exporters.node = { + enable = true; + enabledCollectors = [ "systemd" "network" ]; + port = 9100; + openFirewall = true; + }; + + # System packages + environment.systemPackages = with pkgs; [ + vim + wget + curl + htop + iftop + tcpdump + mtr + bind # for dig/nslookup + iproute2 + iptables + nftables + bird2 + python3 + ]; + + # Users + users.users.admin = { + isNormalUser = true; + extraGroups = [ "wheel" ]; # sudo access + openssh.authorizedKeys.keys = [ + # Add your SSH public key here + ]; + }; + + # Enable sudo without password for wheel group + security.sudo.wheelNeedsPassword = false; + + # Automatic system upgrades + system.autoUpgrade = { + enable = true; + allowReboot = false; + dates = "weekly"; + }; + + # Prometheus metrics endpoint + services.prometheus.exporters.blackbox = { + enable = true; + configFile = pkgs.writeText "blackbox.yml" '' + modules: + icmp: + prober: icmp + timeout: 5s + http_2xx: + prober: http + timeout: 5s + ''; + }; +}