Page cover

Terraform + Proxmox

Déploiement de VMs sur proxmox avec terraform à partir d'un template CloudInit

Cette doc permet le déploiement automatisé de machines virtuelles (VM) sur un cluster Proxmox VE à l’aide de Terraform et du provider bpg/proxmox. Bonus : Petite configuration Ansible

Prérequis

  • Un serveur Proxmox VE en version 8.x

  • Une machine Linux avec Terraform (>= 1.5) ou OpenTofu (>= 1.6) installé

  • Un utilisateur dédié sur Proxmox avec un API Token configuré

  • Un templaye de vm

  • Les accès SSH configurés si nécessaire pour la provision des VM

Création du rôle et de l'utilisateur Proxmox pour Terraform (via CLI)

Docs officielle : https://registry.terraform.io/providers/bpg/proxmox/latest/docs#api-token-authentication

Créer un rôle Terraform avec les droits nécessaires

pveum role add TerraformProv -privs "Datastore.AllocateSpace Datastore.AllocateTemplate Datastore.Audit Pool.Allocate Sys.Audit Sys.Console Sys.Modify VM.Allocate VM.Audit VM.Clone VM.Config.CDROM VM.Config.Cloudinit VM.Config.CPU VM.Config.Disk VM.Config.HWType VM.Config.Memory VM.Config.Network VM.Config.Options VM.Migrate VM.Monitor VM.PowerMgmt SDN.Use"

Ce rôle regroupe toutes les permissions recommandées pour piloter des VM, disques, réseaux, cloud-init, migration, etc.

Créer l'utilisateur Terraform

pveum user add terraform-prov@pve --password <votre_mot_de_passe>

Remplacer <votre_mot_de_passe> par un mot de passe fort.

Associer le rôle à l'utilisateur sur tout le cluster

pveum aclmod / -user terraform-prov@pve -role TerraformProv

Créer un token API pour l’utilisateur

pveum user token add terraform-prov@pve terraform -expire 0 -privsep 0 -comment "Terraform token"

Génération du Token API

Créer un token API pour l’utilisateur (ici nommé terraform) et accorder les roles necessaire au token :

pveum user token add terraform-prov@pve terraform -comment "Token Terraform"
#pveum aclmod / --roles TerraformProv --token 'terraform@pve!terraform' --propagate 1

Configuration des variables d’environnement

Ajouter ces variables à votre shell avant d’utiliser Terraform  :

export PROXMOX_VE_ENDPOINT="https://proxmox.lab.prod:8006/"
export PROXMOX_VE_INSECURE=true
export PROXMOX_VE_USERNAME="terraform-uer-proxmox@pve"
export PROXMOX_VE_PASSWORD="user-proxmox-x"
export PROXMOX_VE_API_TOKEN="API_Token"

Création du template cloudinit:

  • ID : 9000

  • nom de la VM : debian-cloudinit

  • RAM : 2Go

  • Interface réseau : vmbr1

✅1. Télécharger une ISO Debian Cloud-Init Ready

Utiliser une ISO minimale, par exemple via netinst, ou directement une image cloud-init-ready comme :

wget https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-genericcloud-amd64.qcow2

✅ 2. Créer une VM dans Proxmox (sans ISO) en CLI

qm create 9000 --name debian-cloudinit --memory 2048 --net0 virtio,bridge=vmbr1

✅ 3. Importer l’image disque téléchargée

qm importdisk 9000 debian-12-genericcloud-amd64.qcow2 local

local représente le nom du Datastore. Ensuite, attacher le disque au contrôleur :

qm set 9000 --scsihw virtio-scsi-pci --scsi0 local:9000/vm-9000-disk-0.raw

✅ 4. Ajouter le disque Cloud-Init

Sur Proxmox, le disque Cloud-Init est un volume virtuel ajouté à une machine virtuelle pour automatiser sa configuration lors du premier démarrage. Ce disque contient les paramètres essentiels définis par l’administrateur, tels que le nom d’hôte, la configuration réseau, les utilisateurs, les mots de passe ou encore les clés SSH. Lors du boot initial, l’agent Cloud-Init présent dans l’image de la VM détecte ce disque et applique automatiquement toutes les configurations fournies, ce qui permet de déployer rapidement et de façon standardisée des machines virtuelles personnalisées sans intervention manuelle répétitive. Cette méthode est particulièrement utile pour le clonage de templates, le déploiement en masse ou l’intégration à des infrastructures cloud, car elle garantit que chaque VM démarre avec les bons paramètres dès la première utilisation.

qm set 9000 --ide2 local:cloudinit

✅ 5. Configurer le boot & autres options

qm set 9000 --boot c --bootdisk scsi0
qm set 9000 --serial0 socket --vga serial0

✅ 6. Convertir en template

qm template 9000

🔁 Ensuite dans Terraform

On pourra directement l’utiliser comme vm_id = 9000 dans ta config clone.

🧼 Bonus : nettoyage au besoin

rm debian-12-genericcloud-amd64.qcow2

Création d'une clé ssh

Cette clé ssh sera déployée sur les vms qu'on créera

ssh-keygen -t rsa -b 2048 -f ~/.ssh/id_rsa

Cela génèrera deux fichiers :

  • id_rsa → Clé privée (à garder secrète).

  • id_rsa.pub → Clé publique (à injecter dans les VMs).

Place la clé publique dans le dossier Terraform : Le fichier id_rsa.pub doit se trouver dans le dossier contenant ton projet Terraform.

Création des fichiers de configs terraform

proxmox-bpg-terraform/ ├── README.md ├── main.tf ├── data.tf ├── variables.tf ├── outputs.tf ├── vm.tf Tout ça est disponible sur mon repo Github

main.tf

terraform {
  required_providers {
    proxmox = {
      source  = "bpg/proxmox"
      version = "0.66.2"
    }
  }
}

data.tf

data "local_file" "ssh_public_key" {
  filename = "${path.module}/id_rsa.pub"
}
  • local_file est un data source qui lit le contenu d’un fichier local.

  • trimspace(...) est utilisé ensuite dans le vm.tf pour s'assurer qu'aucun saut de ligne inutile ne soit injecté dans le cloud-init.

variables.tf

variable "node_name" {
  description = "proxmox "
  default     = "prox"
}

variable "template_debian_id" {
  description = " template debian cloudinit"
  default     = "9000"
}

variable "nb_vms" {
  description = "nombre de vms à créer"
}

variable "vm_names" {
  description = "nom des vm"
  type        = list(string)
  default     = ["vm1", "vm2", "vm3"]
}

outputs.tf

output "vms_ipv4" {
  description = "IPv4 des VMs créées"
  value = {
    for vm_name, vm in proxmox_virtual_environment_vm.vm :
    vm_name => vm.ipv4_addresses
  }
}

vm.tf

Dans Terraform, le mot de passe fourni à user_account doit être hashé .

  • Génération du mot de passe chiffré

sudo apt install openssl
sudo dnf install openssl # pour le gestionnaire de paquet dnf
sudo yum install openssl # pour le gestionnaire de paquet yum
openssl passwd -6 le-mot-de-passe-à-chiffré
  • Exemple de résultat

imad@:/mnt/c/Users/imad$ openssl passwd -6 password
$6$tHVVDVCWxyr0H0kf$AXm7J6O/nGKMpKK1qzx/uMMRKw7IawWPHWbhu0lYIkql/I/chCaX9nAdisUJ65tuY1RBb4WqqqNMErQiE725n0

Le mot de passe haché est à utiliser dans :

user_account {
  username = "imad"
  password = "<mot_de_passe_hashé>"
  keys     = [trimspace(data.local_file.ssh_public_key.content)]
}

Avec keys = [trimspace(data.local_file.ssh_public_key.content)] qui représente la clé public récupéré en data source dans data.tf et username le nom d'utilisateur des vms qui seront déployés

Le fichier vm.tf devrait ressembler à ca

resource "proxmox_virtual_environment_vm" "vm" {
  for_each  = toset(var.vm_names)
  name      = each.key
  node_name = var.node_name
  vm_id     = 900 + index(var.vm_names, each.key)
  clone {
    vm_id = 9000
    full  = true
  }
  initialization {
    datastore_id = "local"

    user_account {
      username = "imad"
      password = "mot-de-passe-haché"
      keys     = [trimspace(data.local_file.ssh_public_key.content)]
    }
    dns {
      domain  = "local"
      servers = ["1.1.1.1"]
    }
    ip_config {
      ipv4 {
        address = "10.10.10.${50 + index(var.vm_names, each.key)}/24"
        gateway = "10.10.10.1"
      }
    }
  }
  lifecycle {
    ignore_changes = [
      # ignore toute mise à jour sur ces attributs pour les VMs existantes
      initialization[0].ip_config[0].ipv4[0].address,
      initialization[0].ip_config[0].ipv4[0].gateway,
      network_device,
      disk,
      memory,
      cpu
    ]
  }
  #  prevent_destroy = true
}

Déploiement

  • terraform init → Prépare l’environnement

  • terraform fmt → Formate le code

  • terraform validate → Vérifie la validité de la configuration

  • terraform plan → Prévisualise les changements

  • terraform apply → Applique les changements sur l’infrastructure

Pour ajouter de nouvelles VMs à défaut de modifier le fichier variables.tf :

terraform apply -var='vm_names=["vm1", "vm2", "vm3", "dns"]'

Une fois les Vms créées on peut leur appliquer des configs spécifiques avec ansible. ICI

Last updated

Was this helpful?