Objectif : une commande, et une VM Debian 13 tourne sur ton Proxmox avec une IP fixe et ta clé SSH. Terraform parle à Proxmox par son API avec un token ; Proxmox télécharge l'image Debian officielle et crée la VM.
- Proxmox VE 9 et un accès root à l'interface web.
- Terraform installé sur ton poste (
terraform -version) : guide d'installation officiel. - Une clé SSH sur ton poste. Sinon :
ssh-keygen -t ed25519.
Arborescence du projet
proxmox-debian/
├── provider.tf connexion à Proxmox
├── variables.tf liste des paramètres
├── terraform.tfvars tes valeurs (nœud, IP...)
├── main.tf image Debian + VM
└── outputs.tf commande SSH affichée à la finmkdir proxmox-debian && cd proxmox-debianLe contenu des fichiers
Copie chaque bloc dans le fichier du même nom. Tu n'as à modifier que terraform.tfvars.
terraform {
required_providers {
proxmox = {
source = "bpg/proxmox"
version = "~> 0.114.0"
}
}
}
provider "proxmox" {
# Adresse et token lus dans PROXMOX_VE_ENDPOINT et PROXMOX_VE_API_TOKEN
insecure = true # certificat auto-signé de Proxmox
}variable "proxmox_node" {
description = "Nom du nœud Proxmox"
type = string
}
variable "vm_id" {
description = "ID libre pour la VM"
type = number
}
variable "vm_name" {
description = "Nom de la VM"
type = string
}
variable "ip" {
description = "IP de la VM avec le masque, ex. 192.168.1.50/24"
type = string
}
variable "gateway" {
description = "Passerelle du réseau"
type = string
}
variable "ssh_key" {
description = "Chemin de ta clé SSH publique"
type = string
default = "~/.ssh/id_ed25519.pub"
}proxmox_node = "pve"
vm_id = 210
vm_name = "debian-01"
ip = "192.168.1.50/24"
gateway = "192.168.1.1"# 1. Proxmox télécharge l'image cloud Debian 13
resource "proxmox_download_file" "debian_13" {
node_name = var.proxmox_node
datastore_id = "local"
content_type = "import"
url = "https://cloud.debian.org/images/cloud/trixie/latest/debian-13-genericcloud-amd64.qcow2"
file_name = "debian-13-genericcloud-amd64.qcow2"
overwrite = false
}
# 2. La VM, créée à partir de cette image
resource "proxmox_virtual_environment_vm" "debian" {
node_name = var.proxmox_node
vm_id = var.vm_id
name = var.vm_name
stop_on_destroy = true
cpu {
cores = 2
type = "x86-64-v2-AES"
}
memory {
dedicated = 2048 # Mo
}
disk {
datastore_id = "local-lvm"
import_from = proxmox_download_file.debian_13.id
interface = "scsi0"
size = 20 # Go
}
network_device {
bridge = "vmbr0"
}
serial_device {} # obligatoire pour les images cloud Debian
# cloud-init : réseau, utilisateur et clé SSH au premier démarrage
initialization {
datastore_id = "local-lvm"
dns {
servers = ["1.1.1.1", "9.9.9.9"]
}
ip_config {
ipv4 {
address = var.ip
gateway = var.gateway
}
}
user_account {
username = "debian"
keys = [trimspace(file(pathexpand(var.ssh_key)))]
}
}
}output "ssh" {
value = "ssh debian@${split("/", var.ip)[0]}"
}local-lvm: ton stockage de disques (peut êtrelocal-zfs).vmbr0: ton bridge réseau.proxmox_node: le nom affiché sous Datacenter dans l'arbre de gauche.
Autoriser les images sur le stockage local
Proxmox doit pouvoir ranger l'image Debian dans local. Dans l'interface web : Datacenter › Storage › local › Edit.
Dans Content, ajoute Import à ce qui est déjà sélectionné, puis OK.
Pour vérifier : local › Summary, la ligne Content doit maintenant contenir Import.

Créer le rôle Terraform
Datacenter › Permissions › Roles › Create. Nom : TerraformProv. Dans Privileges, coche ces privilèges :
Datastore.Allocate
Datastore.AllocateSpace
Datastore.AllocateTemplate
Datastore.Audit
Pool.Allocate
Pool.Audit
SDN.Use
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.Console
VM.GuestAgent.Audit
VM.Migrate
VM.PowerMgmt
Si un ancien tuto te dit de cocher VM.Monitor : ce privilège n'existe plus sur Proxmox 9, ignore-le.
Créer l'utilisateur
Datacenter › Permissions › Users › Add.
Le compte complet s'appelle terraform@pve. Le mot de passe ne servira pas à Terraform (il utilise le token), mais il est demandé.
Donner le rôle à l'utilisateur
Datacenter › Permissions › Add › User Permission.
Path / avec Propagate coché : le droit s'applique à tout le Proxmox (nœuds, stockages, VM).
Créer le token d'API
Datacenter › Permissions › API Tokens › Add.
C'est l'oubli le plus courant. Coché, le token n'a aucun droit tant qu'on ne lui en donne pas séparément, et Terraform reçoit des erreurs 403. Décoché, il reprend les droits de terraform@pve.
Après Add, Proxmox affiche le secret :
Copie le secret maintenant. Si tu fermes la fenêtre sans l'avoir noté, supprime le token et recrées-en un.
Lancer la création
Dans le dossier proxmox-debian, donne l'adresse et le token à Terraform. Remplace l'IP et le secret par les tiens :
export PROXMOX_VE_ENDPOINT='https://192.168.1.10:8006/'
export PROXMOX_VE_API_TOKEN='terraform@pve!provider=3f6c1a2e-xxxx-xxxx-xxxx-xxxxxxxxxxxx'Format du token : Token ID + = + Secret. Garde les guillemets simples, à cause du !.
terraform init # télécharge le provider Proxmox
terraform plan # montre ce qui va être créé
terraform apply # crée, après avoir tapé yesLe plan doit finir par :
Plan: 2 to add, 0 to change, 0 to destroy.Et l'apply, au bout d'une à quelques minutes :
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
Outputs:
ssh = "ssh [email protected]"Vérifier
Dans Proxmox, la VM 210 apparaît dans l'arbre. Son onglet Cloud-Init reprend tes paramètres : utilisateur, clé SSH, IP et passerelle.

Attends une minute que la VM finisse de démarrer, puis connecte-toi avec la commande affichée par Terraform :
ssh [email protected]
cloud-init status # doit répondre : status: doneSupprimer la VM
terraform destroy # supprime la VM et l'image, après avoir tapé yesPour recréer : terraform apply. C'est tout l'intérêt : la VM se reconstruit à l'identique quand tu veux.
Si ça bloque
| Message | Solution |
|---|---|
401 | Token ou secret mal copié. Refais les export avec des guillemets simples. |
403 Permission check failed | Privilege Separation est resté coché (étape 7), ou un privilège manque dans le rôle (étape 4). |
| Erreur sur le contenu import | Import n'est pas activé sur le stockage local (étape 3). |
VM 210 already exists | Change vm_id dans terraform.tfvars. |
| SSH refusé | Attends que cloud-init termine, et vérifie que ssh_key pointe sur ta clé publique. |