Automatisation10 min de lecture

OpenTofu : gérer votre flotte de VPS en Infrastructure as Code

Vous gérez dix VPS, puis vingt, et chaque nouveau serveur exige la même checklist manuelle : commande, réseau, Docker, reverse proxy, certificat. Une étape oubliée dans l'ordre, et c'est une livraison qui tombe. OpenTofu, le fork open source de Terraform hébergé sous la CNCF, inverse cette logique : vous décrivez l'état cible de votre infrastructure en HCL, vous lancez `tofu apply`, et l'outil calcule le delta entre ce qui existe et ce qui doit exister. Ce guide couvre le provisionnement de VPS — la création, la mise à jour et la destruction de serveurs — en complément de la configuration système qu'Ansible gère déjà.

Pourquoi OpenTofu plutôt que de continuer en SSH manuel

Jusqu'à cinq ou six clients, la gestion manuelle tient : vous vous souvenez de ce qui tourne où, et la checklist de mise en service est connue par cœur. Au-delà, la mémoire devient un risque opérationnel. Un VPS provisionné à la main n'a pas d'état lisible : vous ne savez pas, sans vous connecter, si le pare-feu est configuré, si Docker a bien la version attendue, ou si ce serveur fait encore partie de la rotation.

OpenTofu résout un problème différent d'Ansible. Ansible gère la *configuration* d'un serveur qui existe déjà — ce qui tourne dessus, les fichiers présents, les services démarrés. OpenTofu gère le *cycle de vie* du serveur lui-même : création, mise à jour des attributs, destruction. Il tient un fichier d'état (terraform.tfstate) qui sait exactement ce qui est provisionné et ce qui ne l'est plus. Les deux outils sont complémentaires : OpenTofu provisionne, Ansible configure.

En août 2023, HashiCorp a changé la licence de Terraform de MPL-2.0 vers BUSL-1.1, une licence non libre qui interdit certains usages commerciaux. La communauté a répondu en créant OpenTofu, un fork compatible HCL pour les versions antérieures à Terraform 1.6, aujourd'hui hébergé sous la CNCF (Cloud Native Computing Foundation) et la Linux Foundation. La commande est tofu, pas terraform, mais les fichiers .tf et la logique sont identiques.

Ce que vous gagnez avec un état déclaratif

  • Inventaire fiable — le fichier terraform.tfstate dit exactement quels serveurs existent, avec quelles IPs et quels attributs, sans aller se connecter un par un.
  • Reproductibilité — un nouveau client ou un nouveau projet reçoit le même VPS configuré de la même façon, depuis le même fichier .tf versionné dans Git.
  • Destruction propretofu destroy retire les ressources dans le bon ordre, sans laisser de serveurs orphelins qui continuent à être facturés.
  • Diff lisibletofu plan affiche exactement ce qui sera créé, modifié ou détruit avant d'agir, comme un git diff de votre infrastructure.
  • Complémentarité Ansible — OpenTofu crée le VPS et pose les métadonnées (clé SSH, nom, réseau) ; Ansible prend la main pour déployer Docker, Nginx et vos applications.
  • Versionnable et auditable — votre infrastructure devient un dépôt Git avec des commits, des revues de code et un historique des changements.
  • Licence open source pérenne — OpenTofu est sous MPL-2.0, sans restriction commerciale, avec une gouvernance communautaire sous la CNCF.

Prérequis avant de commencer

Ce guide suppose que vous disposez d'un VPS avec accès root et IPv4 dédiée pour faire tourner vos workloads, et d'un poste de développement (macOS, Linux ou Windows avec WSL2) depuis lequel vous lancez tofu. OpenTofu lui-même ne tourne pas sur le VPS cible : il s'exécute localement et parle à l'API du fournisseur ou au daemon Docker du serveur.

Pour suivre les exemples, vous avez besoin de : OpenTofu installé en local (voir opentofu.org/docs/intro/install), d'un accès API ou de credentials SSH vers le VPS cible, et de Git pour versionner vos fichiers .tf. Aucune dépendance supplémentaire n'est requise — OpenTofu télécharge lui-même les providers au tofu init.

Pour piloter Docker sur un VPS distant via OpenTofu, le daemon Docker du serveur doit écouter sur son socket Unix (par défaut) ou sur un port TCP sécurisé. Le provider kreuzwerker/docker se connecte à ce socket via SSH ou TCP.

Mettre en place OpenTofu sur une flotte de VPS

01

Installer OpenTofu en local

Rendez-vous sur opentofu.org/docs/intro/install pour les instructions selon votre OS. Sur macOS avec Homebrew : brew install opentofu. Sur Debian/Ubuntu : le dépôt officiel OpenTofu fournit le paquet opentofu. Vérifiez l'installation avec tofu version — la commande doit retourner la version installée.

02

Structurer votre projet Infrastructure as Code

Créez un répertoire dédié et quatre fichiers standards.

# main.tf — ressources principales
# variables.tf — déclarations de variables
# outputs.tf — valeurs exposées après apply
# terraform.tfvars — valeurs concrètes (gitignorer si secrets)

Cette structure n'est pas obligatoire pour OpenTofu, mais elle est la convention largement adoptée : main.tf porte les ressources, variables.tf déclare les types et valeurs par défaut, outputs.tf expose ce qu'Ansible ou un autre outil doit lire après le provisionnement (IP du serveur, nom d'hôte…), et terraform.tfvars contient les valeurs concrètes que vous ne souhaitez pas coder en dur dans main.tf.

03

Déclarer le provider et générer une clé SSH

OpenTofu installe les providers nécessaires au tofu init. Le provider hashicorp/tls génère une paire de clés SSH en local, ce qui évite de gérer des clés manuellement.

terraform {
  required_providers {
    tls = {
      source  = "hashicorp/tls"
      version = "~> 4.0"
    }
  }
}

resource "tls_private_key" "vps_key" {
  algorithm = "ED25519"
}

output "private_key_pem" {
  value     = tls_private_key.vps_key.private_key_pem
  sensitive = true
}

Lancez tofu init pour télécharger le provider, puis tofu apply pour générer la clé. Récupérez-la avec tofu output -raw private_key_pem > ~/.ssh/vps_key && chmod 600 ~/.ssh/vps_key.

04

Provisionner le VPS avec null et local-exec

Si votre fournisseur VPS n'a pas de provider OpenTofu officiel, le provider hashicorp/null avec un local-exec permet d'exécuter une commande locale (un appel API curl, un script shell) et de modéliser la ressource dans le state.

resource "null_resource" "vps_provision" {
  triggers = {
    server_name = var.server_name
  }

  provisioner "local-exec" {
    command = <<EOT
      curl -s -X POST https://api.votre-fournisseur.com/v1/servers \
        -H "Authorization: Bearer ${var.api_token}" \
        -d '{"name": "${var.server_name}", "image": "ubuntu-22.04"}'
    EOT
  }
}

Ce pattern est adapté à une phase transitoire. Si votre fournisseur expose une API REST, un script shell appelé en local-exec suffit pour créer le serveur et écrire son IP dans un fichier que outputs.tf exposera ensuite.

05

Piloter Docker sur le VPS avec le provider kreuzwerker

Une fois le VPS provisionné et Docker installé (par Ansible, typiquement), le provider kreuzwerker/docker vous permet de déclarer des conteneurs, des réseaux et des volumes dans OpenTofu.

terraform {
  required_providers {
    docker = {
      source  = "kreuzwerker/docker"
      version = "~> 3.0"
    }
  }
}

provider "docker" {
  host = "ssh://root@${var.server_ip}:22"
}

resource "docker_container" "app" {
  name  = "mon-app"
  image = docker_image.app.image_id
}

resource "docker_image" "app" {
  name = "nginx:alpine"
}

Le provider se connecte au daemon Docker du VPS via SSH — aucun port TCP supplémentaire à ouvrir. La version stable du provider est disponible sur le Terraform Registry.

06

Versionner le state pour une équipe

En développement solo, le state local (terraform.tfstate) suffit. En équipe ou en CI/CD, deux développeurs qui lancent tofu apply simultanément corrompent le state. La solution est un backend distant avec verrouillage.

OpenTofu supporte nativement S3 (AWS, MinIO auto-hébergé) et le GitLab Managed Terraform State. Avec un bucket MinIO sur un VPS :

terraform {
  backend "s3" {
    bucket                      = "tofu-state"
    key                         = "production/terraform.tfstate"
    region                      = "eu-west-1"
    endpoint                    = "https://minio.votre-domaine.com"
    skip_credentials_validation = true
    skip_metadata_api_check     = true
    skip_region_validation      = true
    force_path_style            = true
  }
}

Le verrouillage est automatique : si un tofu apply est en cours, un second est refusé jusqu'à la fin du premier.

07

Intégrer OpenTofu dans votre pipeline CI/CD

Un pipeline Woodpecker CI ou Forgejo Actions typique exécute tofu plan sur chaque pull request (pour revue humaine du diff d'infrastructure) et tofu apply sur merge dans la branche principale.

steps:
  - name: tofu-plan
    image: ghcr.io/opentofu/opentofu:latest
    commands:
      - tofu init
      - tofu plan -out=tfplan

  - name: tofu-apply
    image: ghcr.io/opentofu/opentofu:latest
    commands:
      - tofu apply tfplan
    when:
      branch: main
      event: push

Le state distant (étape précédente) est indispensable ici : le runner CI n'a pas accès au state local de votre poste.

Séparez les workspaces par environnement

OpenTofu propose les workspaces pour isoler plusieurs états dans le même backend : tofu workspace new staging crée un espace isolé, tofu workspace select production bascule vers la production. C'est plus léger que de dupliquer les répertoires .tf. En pratique, un workspace par client ou par environnement (staging, prod) évite qu'un tofu destroy en staging touche la production. Nommez vos ressources avec ${terraform.workspace} pour qu'elles restent distinctes dans le state.

Ansible et OpenTofu : la frontière entre les deux

La question revient souvent : Ansible fait déjà le travail, pourquoi ajouter un outil ? La frontière est nette une fois qu'on la pose clairement.

OpenTofu répond à « qu'est-ce qui existe ? » : il crée le serveur, lui assigne une IP, pose une clé SSH, enregistre son état. Si vous le supprimez de votre fichier .tf et lancez tofu apply, le serveur disparaît — OpenTofu tient le cycle de vie.

Ansible répond à « dans quel état est ce qui existe ? » : il installe Docker, configure Nginx, dépose un fichier .env, redémarre un service. Si le serveur est déjà là, Ansible en fait ce que vous lui demandez — mais s'il n'est pas là, Ansible ne peut pas le créer.

Le flux naturel pour une agence : OpenTofu provisionne le VPS et expose son IP en output, un playbook Ansible consomme cet output via un inventaire dynamique, configure le serveur et déploie les applications. L'article Ansible : automatiser la configuration de vos serveurs VPS couvre la partie configuration en détail.

Dépannage : les erreurs fréquentes

Trois situations reviennent régulièrement quand on adopte OpenTofu sur une flotte existante.

Erreurs courantes et leur correction

  • Error acquiring the state lock — un crash en cours d'apply laisse un fichier .terraform.tfstate.lock.info sur le backend. OpenTofu refuse de continuer tant que le verrou existe. Après avoir vérifié qu'aucun autre apply ne tourne, supprimez le verrou avec tofu force-unlock <LOCK_ID> (l'ID apparaît dans le message d'erreur). Sur un backend S3/MinIO, le fichier est visible dans le bucket.
  • tofu plan affiche destroy + create inattendu — certains attributs d'une ressource forcent une recréation (force new resource) quand ils changent : le nom du serveur, le type d'image OS, la région. Si vous modifiez l'un de ces attributs, OpenTofu ne peut pas faire une mise à jour en place — il détruit et recrée. Lisez le plan attentivement avant d'appliquer et utilisez tofu plan -target=resource.name pour limiter la portée.
  • State perdu ou désynchronisé — si le fichier state est perdu et que les serveurs existent encore, tofu state list liste ce qu'OpenTofu croit provisionné, et tofu import <resource.type.name> <id-externe> importe une ressource existante dans le state sans la recréer. C'est l'outil de récupération quand la réalité et le state ont divergé.
  • Provider non trouvé après tofu init — vérifiez que le source du provider est exact (ex. kreuzwerker/docker et non docker/docker) et que vous avez accès à internet depuis la machine qui lance tofu init. Dans un environnement air-gapped, pré-téléchargez les providers et utilisez plugin_cache_dir.
  • Error: No valid credential sources found — OpenTofu ne trouve pas les credentials pour le provider. Vérifiez les variables d'environnement attendues par le provider (souvent TF_VAR_api_token ou un fichier de credentials spécifique) et que terraform.tfvars est bien lu (il doit être dans le même répertoire que main.tf).

Votre infrastructure devient du code versionné

OpenTofu ne remplace pas SSH, il rend SSH exceptionnel. Le flux quotidien devient : modifier un fichier .tf, lancer tofu plan pour lire le diff, valider, lancer tofu apply. Les serveurs que vous n'avez plus à gérer sont détruits par tofu destroy et disparaissent de la facturation.

Pour une agence qui dépasse la dizaine de clients, c'est le levier qui fait passer la gestion d'infrastructure d'un travail de mémoire à un travail de code. Un VPS Cloud ServOrbit avec accès root, IPv4 dédiée et choix d'OS est l'unité de base que vos fichiers .tf provisionnent et détruisent à la demande. Votre infrastructure devient du code versionné.

Un VPS Cloud prêt pour OpenTofu

Accès root, IPv4 dédiée et choix d'OS : un VPS Cloud ServOrbit est l'unité de base que vos fichiers `.tf` provisionnent et détruisent à la demande.

Besoin d'aide ?

Parcourez notre centre d'aide et notre FAQ, ou contactez notre équipe — rappel, WhatsApp ou e-mail. Support en français, anglais et arabe.