diff --git a/PRDs/terraform-lxc-deployment.md b/PRDs/terraform-lxc-deployment-batch.md similarity index 54% rename from PRDs/terraform-lxc-deployment.md rename to PRDs/terraform-lxc-deployment-batch.md index 6e45c58..4f8dece 100644 --- a/PRDs/terraform-lxc-deployment.md +++ b/PRDs/terraform-lxc-deployment-batch.md @@ -1,12 +1,61 @@ -# Terraform LXC Deployment for Iron Legion — PRD +# Terraform LXC Deployment — Batch/Dynamic Template PRD -**Status:** Phase 1 Complete | **Author:** Artemis | **Date:** 2026-06-04 +**Status:** Batch POC Validated | **Author:** Artemis | **Date:** 2026-06-05 -> **Phase 1 validation:** Single LXC plan/build/destroy completed successfully on MK33 (pve-swarm). All open questions resolved. Phase 2 pending. +> **Goal:** Dynamic LXC factory — one `terraform apply` creates N containers with auto-derived VMID, IPv4, hostname, and naming from a single base input. ## 1. Objective -Deploy Proxmox LXC containers via Terraform using the `bpg/proxmox` provider, running inside a custom Docker container (lazy automator pattern). Support runtime parameterization for bulk LXC creation with auto-incrementing VMID, IPv4, and naming. +Extend the Phase 1 single-LXC proven pipeline into a **parameterized batch generator**. A single variable set (`vmid_base`, `lxc_count`, `subnet_prefix`) drives auto-incrementing VMIDs, auto-derived static IPv4s, and consistent hostnames — no per-container hardcoding. + +## 2. Dynamic Derivation Rules + +### 2.1 Input Variables (User-Supplied) + +| Variable | Example | Description | +|----------|---------|-------------| +| `vmid_base` | `5050` | Starting VMID for first LXC | +| `lxc_count` | `4` | Number of LXCs to create | +| `subnet_prefix` | `192.168` | First two octets of IPv4 (fleet standard) | +| `name_prefix` | `lxc` | Hostname prefix | +| `gateway` | `192.168.18.1` | Default gateway | +| `dns_servers` | `["192.168.7.7", "1.1.1.1"]` | DNS list | + +### 2.2 Auto-Derived Per-LXC (Index `i` from `0` to `lxc_count-1`) + +| Property | Formula | Example (`vmid_base=5050`, `i=2`) | +|----------|---------|----------------------------------| +| **VMID** | `vmid_base + i` | `5052` | +| **IPv4** | `subnet_prefix.${first2(vmid)}.${last2(vmid)}/18` | `192.168.50.52/18` | +| **Hostname** | `${name_prefix}-${vmid}` | `lxc-5052` | +| **Cores** | Fixed | `2` | +| **RAM** | Fixed | `2048` MB | +| **Disk** | Fixed | `8` GB | + +**IP Derivation Detail:** +``` +vmid = 5052 +first2(vmid) = 50 (digits 3-4) +last2(vmid) = 52 (digits 5-6) +IPv4 = 192.168.50.52/18 +``` + +This keeps VMID and IPv4 tightly coupled — **VMID is the single source of truth** for IP assignment. All IPs fall within the fleet `/18` subnet (`192.168.0.0/18`). + +### 2.3 Example Runs + +```bash +# Create 4 LXCs: lxc-5050 → lxc-5053 +# IPs: 192.168.50.50 → 192.168.50.53 +TF_VAR_vmid_base=5050 TF_VAR_lxc_count=4 ./run.sh apply -auto-approve + +# Create 2 LXCs starting at 5100 +# IPs: 192.168.51.00, 192.168.51.01 +TF_VAR_vmid_base=5100 TF_VAR_lxc_count=2 ./run.sh apply -auto-approve + +# Create 7 LXCs at vmid_base=931 (validated POC run) +TF_VAR_vmid_base=931 TF_VAR_lxc_count=7 ./run.sh apply -auto-approve +``` ## 2. Architecture @@ -99,20 +148,28 @@ initialization { - Unprivileged required: `unprivileged = true` + `features { nesting = true }` - Password injection: `user_account.password` required for console login verification -### Phase 2 — Modular + Bulk Creation +### Phase 2 — Modular + Bulk Creation ✅ VALIDATED -**Goal:** Add `count`, `vmid_base`, and auto-derived naming/IP. +**Completed:** 2026-06-05 on MK33 (pve-swarm) -**Deliverables:** -- `modules/lxc/` — reusable LXC module -- `locals.tf` — VMID/IP/name calculation logic -- `main.tf` — uses module with `count = var.lxc_count` +**Results:** +- `modules/lxc/` — reusable LXC module with `proxmox_virtual_environment_container` resource +- `main.tf` — `for_each` over module with `lxc_count` parameterization +- `run.sh` — forwards `TF_VAR_*` environment variables into Docker container -**Example execution:** -```bash -TF_VAR_lxc_count=4 TF_VAR_vmid_base=5050 ./run.sh apply -# Creates: lxc-5050, lxc-5051, lxc-5052, lxc-5053 -``` +**Validated at multiple scales:** + +| Test | Command | Result | +|------|---------|--------| +| 4 LXCs at vmid_base=3550 | `TF_VAR_lxc_count=4 TF_VAR_vmid_base=3550 ./run.sh apply` | ✅ All created; 1 transient 500 error on start (PVE task queue race), container existed and operational despite error | +| 7 LXCs at vmid_base=931 | `TF_VAR_lxc_count=7 TF_VAR_vmid_base=931 ./run.sh apply` | ✅ All 7 created successfully, no errors, ~14–16s per container | +| 7 LXCs destroy | `./run.sh destroy -auto-approve` | ✅ All 7 destroyed cleanly in ~8s each | + +**Key runtime behavior discovered:** +- `terraform.auto.tfvars` outranks `TF_VAR_*` environment variables — dynamic variables must **not** be set in `.tfvars` +- `-auto-approve` required on Dockerized terraform (no interactive TTY for confirmation) +- Parallel creation (default) works at N=7; transient race condition observed at N=4 (PVE task queue, not terraform logic) +- All containers receive SSH key + password via `initialization.user_account` block ## 4. File Structure