Create Proxmox VM with Terraform
In this post I will show you how how you can create a Proxmox VMs with Terraform.
To ease the creation of the VMs in Proxmox I will use predefined VM templates. So our first task is create the template. To do this login to one of the proxmox nodes.
# installing libguestfs-tools only required once, prior to first run
sudo apt update -y
sudo apt install libguestfs-tools -y
# download a debian cloud-init disk image:
wget http://cloud.debian.org/images/cloud/bullseye/latest/debian-11-generic-amd64.qcow2
sudo virt-customize -a debian-11-generic-amd64.qcow2 --install qemu-guest-agent
sudo qm create 100200 --name "debian11.vm.shiwaforce.com" --memory 2048 --cores 2 --net0 virtio,bridge=vmbr0
sudo qm importdisk 100200 debian-11-generic-amd64.qcow2 zfs-vm-none
sudo qm set 100200 --scsihw virtio-scsi-pci --scsi0 zfs-vm-none:vm-100200-disk-0
sudo qm set 100200 --boot c --bootdisk scsi0
sudo qm set 100200 --ide2 zfs-vm-none:cloudinit
sudo qm set 100200 --serial0 socket --vga serial0
sudo qm set 100200 --agent enabled=1
sudo qm template 100200
rm debian-11-generic-amd64.qcow2
Determine Authentication Method (use API keys)
The next step is to create a service account in proxmox for authentication and generate an authentication token:
pveum role add TerraformProv -privs "Pool.Allocate VM.Console 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"
pveum user add tfuser@pve
pveum aclmod / -user tfuser@pve -role TerraformProv
pveum user token add tfuser@pve terraform --privsep 0
# Please save the token secret as there isn't any way to fetch it at a later point.
Create teh Terraform config files
mkdir terraform
cd terraform
Create backend config:
nano backend.tf
terraform {
required_providers {
proxmox = {
source = "telmate/proxmox"
version = "2.9.11"
}
}
backend "local" {
}
}
Create provider config:
nano provider.tf
provider "proxmox" {
pm_api_url = "https://proxmox.mydomain.intra:8006/api2/json"
# api token id is in the form of: <username>@pam!<tokenId>
pm_api_token_id = "tfuser@pve!terraform"
# this is the full secret wrapped in quotes.
pm_api_token_secret = var.PROXMOX_API_SECRET
pm_tls_insecure = true
# debug log
# pm_log_enable = true
# pm_log_file = "terraform-plugin-proxmox.log"
# pm_debug = true
# pm_log_levels = {
# _default = "debug"
# _capturelog = ""
# }
}
The auth token will be ised from the PROXMOX_API_SECRET
linux environment variable. Now create the terraform variable file:
nano vars.tf
variable "PROXMOX_API_SECRET" {
type = string
}
variable "ssh_key" {
default = "ssh-rsa AAAAB3NzaC1y..."
}
variable "proxmox_host" {
default = "proxmox"
}
variable "template_name" {
default = "debian11.vm.shiwaforce.com"
}
Create the main Terraform config file vit the resource definitions:
touch main.tf
nano k8s-master.tf
resource "proxmox_vm_qemu" "k8s-master" {
count = 3
name = "k8s0${count.index + 1}.mydomain.intra"
target_node = var.proxmox_host
vmid = "101${count.index + 1}"
clone = var.template_name
os_type = "cloud-init"
cpu = "kvm64"
cores = 2
sockets = 1
memory = 6144
scsihw = "virtio-scsi-pci"
bootdisk = "scsi0"
disk {
slot = 0
size = "50G"
type = "scsi"
storage = "zfs-vm-etc"
iothread = 1
}
network {
model = "virtio"
bridge = "vmbr0"
tag = 101
firewall = false
link_down = false
}
ipconfig0 = "ip=192.168.10.1${count.index + 1}/22,gw=192.168.10.1"
ciuser = "terraform"
sshkeys = <<EOF
${var.ssh_key}
EOF
}
If you created all the files it looks like this:
cd ..
tree .
.
└── terraform
├── backend.tf
├── provider.tf
├── outputs.tf
├── k8s-master.tf
└── vars.tf
1 directory, 5 files
Now we can create the VMs:
export PROXMOX_API_SECRET="9f881350-175c-4a09-a25c-bce726ada447"
# inicialise the terraform modules
terraform init --upgrade
# generate a terraform plan
terraform plan -out k8s-master.tfplan
# deploym the VMs
terraform apply -parallelism=1 -auto-approve k8s-master.tfplan
# cleanup
terraform plan -destroy -out k8s-master.destroy.tfplan
terraform apply k8s-master.destroy.tfplan