🏗️ OpenTofu Resources

Overview
OpenTofu provisions ephemeral Windows VMs from the Packer-built template. This document details the Terraform/OpenTofu configuration in terraform/main.tf.
Configuration Structure
graph TD
subgraph OpenTofu["OpenTofu Configuration"]
direction TB
Provider[Provider Config] --> Resources[VM Resource] --> Clone[Clone Strategy] --> Output[VM IP Output]
end
subgraph ResourceParts["VM Resource Parts"]
Basic[Basic Settings] --> Hardware[CPU/Memory] --> Network[Network Config] --> Init[Cloud-Init/IP]
end
Provider --> Resources
Resources --> ResourceParts
style OpenTofu fill:#e3f2fd
style ResourceParts fill:#e8f5e9
Full Configuration
terraform {
required_providers {
proxmox = {
source = "bpg/proxmox"
version = "0.46.1"
}
}
}
provider "proxmox" {
endpoint = "https://proxmox-host:8006/"
# Credentials injected via Environment Variables in Forgejo
# PM_API_TOKEN_ID and PM_API_TOKEN_SECRET
}
resource "proxmox_virtual_environment_vm" "build_agent" {
name = "ci-win-build-${var.build_id}"
node_name = "la-vmh-07"
clone {
# Packer template VM ID
vm_id = var.template_vm_id
full_clone = false
}
cpu {
cores = 4
type = "host"
}
memory {
dedicated = 8192
}
network_device {
bridge = "vmbr0"
}
initialization {
ip_config {
ipv4 {
address = "dhcp"
}
}
}
}
output "vm_ip" {
value = proxmox_virtual_environment_vm.build_agent.ipv4_addresses[1][0]
description = "IP address of the provisioned VM"
}
Variables
Input Variables
File: terraform/variables.tf
variable "build_id" {
description = "Unique identifier for the build"
type = string
}
variable "template_vm_id" {
description = "VM ID of the Packer-built template"
type = number
default = 9000
}
Usage
export TF_VAR_build_id="123"
export TF_VAR_template_vm_id="9000"
tofu apply -auto-approve
Section Details
Provider Configuration
| Setting |
Value |
Description |
endpoint |
https://proxmox-host:8006/ |
Proxmox API URL |
source |
bpg/proxmox |
Proxmox provider |
version |
0.46.1 |
Provider version |
VM Clone Configuration
| Setting |
Value |
Description |
vm_id |
var.template_vm_id |
Template VM ID to clone |
full_clone |
false |
Fast linked clone |
node_name |
la-vmh-07 |
Target Proxmox node |
Hardware Configuration
| Setting |
Value |
Notes |
cores |
4 |
CPU cores |
type |
host |
Host-passthrough CPU |
dedicated |
8192 |
8 GB dedicated RAM |
Network Configuration
| Setting |
Value |
Notes |
bridge |
vmbr0 |
Default Proxmox bridge |
ip_config |
DHCP |
Automatic IP assignment |
Provisioning Process
flowchart LR
subgraph Process["OpenTofu Process"]
direction TB
Init[tofu init] --> Plan[tofu plan] --> Apply[tofu apply] --> Clone[Clone VM] --> Start[Start VM] --> IP[Get VM IP]
end
subgraph Template["Template"]
T[Template VM] --> |Clone| V[New VM]
end
Apply --> Template
V --> Start
style Process fill:#e3f2fd
style Template fill:#e8f5e9
Output
output "vm_ip" {
value = proxmox_virtual_environment_vm.build_agent.ipv4_addresses[1][0]
}
Usage in pipeline:
VM_IP=$(tofu output -raw vm_ip)
echo "VM_IP=$VM_IP" >> $GITHUB_ENV
Environment Variables
| Secret |
Env Var |
Purpose |
| Proxmox Token ID |
PM_API_TOKEN_ID |
Authentication |
| Proxmox Token Secret |
PM_API_TOKEN_SECRET |
Authentication |
Troubleshooting
| Issue |
Cause |
Solution |
| Clone failed |
Wrong VM ID |
Check template VM ID in Proxmox |
| No IP assigned |
DHCP not working |
Check network bridge |
| Permission denied |
Token lacks privileges |
Add VM.Admin to token |
Next Steps
← Documentation Index | → Variables | ← Packer Autounattend