Terraform - Proxmox Provider Setup

I want to learn more about Infrastructure as a Code and the first tool I wil be testing is terraform. In another article, I have described how to create the terraform container and setup a proxy to help with the troubleshooting in case anything goes wrong and trust me it always does.

1) Creating the Terraform User

Our first step will be to create a terraform role and user to manage our proxmox node. Here I will use the recommeded steps from the terraform proxmox provider.

pveum role add hv1-terraform-role -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"

We will slightly change the terraform example and create a user without the --password flag because we will use tokens for authentication.

pveum user add hv1-terraform@pve

Let's create a new token for the recently created user.

pveum user token add hv1-terraform@pve hv1-terraform-token
┌──────────────┬───────────────────────────────────────┐
│ key          │ value                                 │
╞══════════════╪═══════════════════════════════════════╡
│ full-tokenid │ hv1-terraform@pve!hv1-terraform-token │
├──────────────┼───────────────────────────────────────┤
│ info         │ {"privsep":1}                         │
├──────────────┼───────────────────────────────────────┤
│ value        │ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx  │
└──────────────┴───────────────────────────────────────┘
Make sure to save the token because it is not possible to recover it.

Finally, we will create an access list to allow our user access to the API.

pveum acl modify / --user hv1-terraform@pve --roles hv1-terraform-role

2) Terraform Project Files

Connect to your terraform environment and create a folder and in a new file paste the below:

terraform {
  required_providers {
    proxmox = {
      source = "Telmate/proxmox"
      version = "2.9.9"
    }
  }
}

provider "proxmox" {
        pm_api_url      = "https://192.168.1.100:8006/api2/json"
        pm_proxy_server = "http://192.168.65.20:443"

        pm_log_enable   = true
        pm_log_file     = "tf-plugin-proxmox.log"
        pm_debug        = true
        pm_log_levels   = {
                _default        = "debug"
                _capturelog     = ""
        }
}

resource "proxmox_vm_qemu" "destroy-vm" {
        name            = "TERRAFORM-TEST"
        target_node     = "hv1"
        iso             = "teste.iso"
}

Don't forget to export the environment variables below. They contain the API token ID and secret.

export PM_API_TOKEN_ID="hv1-terraform@pve!hv1-terraform-token"
export PM_API_TOKEN_SECRET="xxxxxxxxxxxxxxxxxxxxxxxxxxx"

3) Initialising the Terraform Project

terraform init
Initializing the backend...

Initializing provider plugins...
- Finding telmate/proxmox versions matching "2.9.9"...
- Installing telmate/proxmox v2.9.9...
- Installed telmate/proxmox v2.9.9 (self-signed, key ID A9EBBE091B35AFCE)

Partner and community providers are signed by their developers.
If you'd like to know more about provider signing, you can read about it here:
https://www.terraform.io/docs/cli/plugins/signing.html

Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see                                                                                                                
any changes that are required for your infrastructure. All Terraform commands                                                                                                                
should now work.                                                                                                                                                                             

If you ever set or change modules or backend configuration for Terraform,                                                                                                                    
rerun this command to reinitialize your working directory. If you forget, other                                                                                                              
commands will detect it and remind you to do so if necessary.

4) Terraform Plan

Terraform plan will list all the changes that will be implemented into the infrastructure.

terraform plan -out connection-test.tfplan
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # proxmox_vm_qemu.destroy-vm will be created
  + resource "proxmox_vm_qemu" "destroy-vm" {
      + additional_wait           = 0
      + agent                     = 0
      + automatic_reboot          = true
      + balloon                   = 0
      + bios                      = "seabios"
      + boot                      = "c"
      + bootdisk                  = (known after apply)
      + clone_wait                = 0
      + cores                     = 1
      + cpu                       = "host"
      + default_ipv4_address      = (known after apply)
      + define_connection_info    = true
      + force_create              = false
      + full_clone                = true
      + guest_agent_ready_timeout = 100
      + hotplug                   = "network,disk,usb"
      + id                        = (known after apply)
      + kvm                       = true
      + memory                    = 512
      + name                      = "TERRAFORM-TEST"
      + nameserver                = (known after apply)
      + numa                      = false
      + onboot                    = false
      + oncreate                  = true
      + preprovision              = true
      + qemu_os                   = "l26"
      + reboot_required           = (known after apply)
      + scsihw                    = (known after apply)
      + searchdomain              = (known after apply)
      + sockets                   = 1
      + ssh_host                  = (known after apply)
      + ssh_port                  = (known after apply)
      + tablet                    = true
      + target_node               = "hv1"
      + unused_disk               = (known after apply)
      + vcpus                     = 0
      + vlan                      = -1
      + vmid                      = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

─────────────────────────────────────────────────────────────── 

Saved the plan to: connection-test.tfplan

To perform exactly these actions, run the following command to apply:
    terraform apply "connection-test.tfplan"

5) Deploying Infrastructure

Terraform apply is used to deploy the infrastructure according to the previously executed plan.

terraform apply "connection-test.tfplan"
proxmox_vm_qemu.destroy-vm: Creating...
╷
│ Error: error creating VM: 400 Parameter verification failed., error status: {"errors":{"ide2":"invalid format - format error\nide2.file: invalid format - unable to parse volume ID 'teste.iso'\n\n"},"data":null} (params: map[agent:0 args: bios:seabios boot:c cores:1 cpu:host description: hotplug:network,disk,usb ide2:teste.iso,media=cdrom kvm:true machine: memory:512 name:TERRAFORM-TEST numa:false onboot:false ostype:l26 sockets:1 tablet:true tags: vmid:109])
│ 
│   with proxmox_vm_qemu.destroy-vm,
│   on main.tf line 24, in resource "proxmox_vm_qemu" "destroy-vm":
│   24: resource "proxmox_vm_qemu" "destroy-vm" {
│ 
╵

Since this config is just a connectivity test. The values feed to proxmox are non-existent therefore the failure response from the server.

Conclusion

With the steps above, we were able to deploy our first VM in our Proxmox Node using the infrastructure as code tool: terraform.

Resources

Terraform Registry
pveum(1)