Terraform with Proxmox VE


This article documents using Hashicorp’s Terraform to deploy LXC containers on Proxmox VE virtualisation platform.

It is assumed that the Proxmox VE host has been setup, and Terraform has already been installed and configured on a workstation that can access the Proxmox VE host at TCP port 8006.

Summary of procedure

From Proxmox VE host

  1. Add role to Proxmox VE host for Terraform user account
  2. Add user account for Terraform
  3. Assign the newly created role to the new user account
  4. Generate API token for Terraform to authenticate with Proxmox VE

From Terraform workstation

  1. Create environmental variables for the API token ID and its secret
  2. Create Terraform configuration file usually named main.tf
  3. Initialise the Terraform environment
  4. Validate the Terraform configuration file
  5. Check the action plan
  6. Apply the action plan
  7. Optionally destroy the deployment

Detailed commands

From Proxmox VE host

# Add user role
pveum role add TerraformProv -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"

# Add user account
pveum user add terraform-prov@pve --password userpassword

# Assign new role to the new account
pveum aclmod / -user terraform-prov@pve -role TerraformProv

# Generate API token for the new account
pveum user token add terraform-prov@pve terraform-api-token --privsep 0

Note

When generating API token, make sure you save the secret straightway, because if you don’t there is no way to retrieve it later on.

From Terraform workstation

# Initialise terraform environment
terraform init

# validate terraform configuration file
terraform validate

# check the action plan (aka dry run)
terraform plan

# actually making changes
terraform apply

# destroy the environment
terraform destroy


My main.tf file for creating a test LXC container

terraform {
  required_providers {
    proxmox = {
      source  = "telmate/proxmox"
      version = "2.9.6"
    }
  }
}

provider "proxmox" {
  pm_api_url = "https://pve-host.example.com:8006/api2/json"
  pm_tls_insecure = true
  pm_log_enable = true
  pm_log_file   = "terraform-plugin-proxmox.log"
  pm_debug      = true
  pm_log_levels = {
    _default    = "debug"
    _capturelog = ""
  }
}

resource "proxmox_lxc" "terraform-test" {
  target_node  = "pve2"
  hostname     = "lxc-terraform-test"
  ostemplate   = "zfs-storage:vztmpl/debian-10-turnkey-core_16.0-1_amd64.tar.gz"
  password     = "password"
  unprivileged = true

  // Terraform will crash without rootfs defined
  rootfs {
    storage = "zfs-nvme"
    size    = "8G"
  }

  network {
    name   = "eth0"
    bridge = "vmbr0"
    ip     = "dhcp"
  }
}

Areas worth paying attention to

LXC container creation failed with error “HTTP/1.1 403 Permission check failed”

This was due to the that the API token generated from the Terraform user had the “Privilege separation” enabled by default. When it was enabled, the resultant privileges are the intersected ones between the privileges assigned directly to the token and the privileges assigned to the user account. Apparently there is none assigned directly to the token, hence the resultant privileges were effectively none. Disabling the “Privilege separation” fixed this issue.

When using API token the environment variable names cannot be changed

The name of environment variables PM_API_TOKEN_ID & PM_API_TOKEN_SECRET are hard-coded in the provider, they cannot be changed to anything else.

References


WordPress Appliance - Powered by TurnKey Linux