terraform { required_providers { proxmox = { source = "bpg/proxmox" version = "~> 0.61.0" } } } # Bare Metal Host Configurations (SSH Provisioning) # We use a null_resource to run imperative commands on the Debian host # that are not currently supported by the bpg/proxmox provider. resource "null_resource" "bare_metal_setup" { triggers = { node = var.node_name data_disk_id = var.data_disk_id pool_name = var.zfs_pool_name } connection { type = "ssh" user = "root" # Assuming running locally on the node during bootstrap, or via SSH if run from a laptop. # We default to local host if run from Control Center, but for flexibility we use the endpoint. host = var.node_name agent = true } provisioner "remote-exec" { inline = [ # Set laptop lid switch to ignore (prevents sleeping when closed) "sed -i 's/^#\\?HandleLidSwitch=.*/HandleLidSwitch=ignore/' /etc/systemd/logind.conf", "systemctl restart systemd-logind", # Format the ZFS pool if it doesn't already exist "zpool list ${var.zfs_pool_name} || zpool create -f ${var.zfs_pool_name} /dev/disk/by-id/${var.data_disk_id}", # Register the ZFS pool in Proxmox if it's not already registered "pvesm status -storage ${var.zfs_pool_name} || pvesm add zfspool ${var.zfs_pool_name} --pool ${var.zfs_pool_name} --content images,rootdir" ] } } # Resource Pools # Creates logical groups for organizing and securing VMs. resource "proxmox_virtual_environment_pool" "core" { pool_id = "core" comment = "Critical, public-facing services (reverse proxy, DNS)" } resource "proxmox_virtual_environment_pool" "production" { pool_id = "production" comment = "Stable services with backup strategies" } resource "proxmox_virtual_environment_pool" "dev" { pool_id = "dev" comment = "Persistent but non-production services, run 24/7" } resource "proxmox_virtual_environment_pool" "staging" { pool_id = "staging" comment = "Ephemeral test VMs managed by Pull-Based PR webhooks" } # API Tokens for Control Center # Creates a restricted user for the Control Center VM to manage the cluster. resource "proxmox_virtual_environment_role" "control_center_role" { role_id = "ControlCenter" privileges = [ "VM.Allocate", "VM.Audit", "VM.Clone", "VM.Config.CDROM", "VM.Config.CPU", "VM.Config.Disk", "VM.Config.HWType", "VM.Config.Memory", "VM.Config.Network", "VM.Config.Options", "VM.Monitor", "VM.PowerMgmt", "Datastore.AllocateSpace", "Datastore.Audit", "SDN.Use" ] } resource "proxmox_virtual_environment_user" "control_center_user" { user_id = "control-center@pve" comment = "Managed by OpenTofu - Used by Control Center for GitOps" } # Grant full VM access to the control center resource "proxmox_virtual_environment_acl" "control_center_vms" { user_id = proxmox_virtual_environment_user.control_center_user.user_id role_id = proxmox_virtual_environment_role.control_center_role.role_id path = "/vms" } # Grant datastore access resource "proxmox_virtual_environment_acl" "control_center_storage" { user_id = proxmox_virtual_environment_user.control_center_user.user_id role_id = proxmox_virtual_environment_role.control_center_role.role_id path = "/storage/${var.zfs_pool_name}" } resource "proxmox_virtual_environment_user_token" "control_center_token" { user_id = proxmox_virtual_environment_user.control_center_user.user_id token_name = "gitops" comment = "Stored only on the Control Center VM" } output "control_center_api_token" { value = proxmox_virtual_environment_user_token.control_center_token.value sensitive = true description = "The secret API token for control-center@pve. This will be injected into the Control Center SOPS config." }