Terraform nach OpenTofu migrieren

30.06.2026

Thema: alle Beiträge zu OpenTofu

Terraform nach OpenTofu migrieren, ohne dass ein Team stillsteht: die richtige Reihenfolge, die State-Version und die terraform_remote_state-Falle.

Inhaltsverzeichnis

Voraussetzungen

  1. eine bestehende Terraform-Konfiguration, die du auf OpenTofu umstellen möchtest
  2. tofu ist installiert (OpenTofu >= 1.6)
  3. dein State liegt in einem Remote-Backend (z. B. S3) mit aktiviertem Versioning, oder du legst vor der Migration ein Backup an

Warum OpenTofu?

Im August 2023 hat HashiCorp die Lizenz von Terraform von der quelloffenen MPL 2.0 auf die Business Source License (BSL) umgestellt. Die letzte unter MPL veröffentlichte Version ist Terraform 1.5.7. Alles danach ist nicht mehr Open Source im klassischen Sinn.

OpenTofu ist der von der Linux Foundation getragene Fork genau dieser letzten freien Version. Quelloffen, herstellerunabhängig und damit ein Baustein digitaler Souveränität: kein Vendor-Lock-in, keine Lizenz-Überraschung von oben.

Der Fork-Punkt, nachgewiesen

Man muss das nicht glauben, man kann es sehen. OpenTofu zweigt nachweisbar von Terraform ab. Der gemeinsame Vorfahr beider Git-Historien lässt sich exakt bestimmen:

git clone https://github.com/hashicorp/terraform.git
git clone https://github.com/opentofu/opentofu.git
mkdir compare && cd compare && git init
git remote add terraform ../terraform
git remote add opentofu ../opentofu
git fetch terraform
git fetch opentofu
git merge-base opentofu/main terraform/main

git merge-base liefert den Commit, an dem sich die beiden Historien das letzte Mal trafen, also den Verzweigungspunkt. OpenTofu ist also kein Re-Implementierungsversuch von außen, sondern teilt sich die Vergangenheit mit Terraform.

Der einfache Fall

Hat man ein einziges, isoliertes Projekt, ist die Migration tatsächlich beinahe ein Nicht-Ereignis. Statt terraform ruft man tofu auf:

tofu init
tofu plan

tofu init baut den lokalen .terraform-Cache neu auf, tofu plan vergleicht deinen Code mit dem State. Im Idealfall meldet OpenTofu:

No changes. Your infrastructure matches the configuration.

Kein Diff, keine geplanten Änderungen. OpenTofu liest denselben State und dieselbe Konfiguration wie Terraform zuvor. Genau das wollen wir.

Das Problem: Fast niemand hat nur ein Projekt. Sobald mehrere Konfigurationen im Spiel sind, beginnt die eigentliche Migration, und mit ihr die Fallen.

Falle 1: Die State-Version ist eine Einbahnstraße

Jeder State trägt Versionsangaben, und hier lohnt eine Präzisierung, die oft falsch dargestellt wird. Die äußere Formatversion (aktuell 4) steht seit Terraform 0.12 aus dem Jahr 2019 praktisch fest und ändert sich beim Umstieg nicht. Was sich ändert, sind die inneren Versionsangaben im State: die Version des Werkzeugs, das zuletzt geschrieben hat, und die Provider-Schema-Versionen. Migrierst du ein Projekt auf OpenTofu und führst dort einen apply aus, zieht das genau diese inneren Angaben hoch. Das ist an sich harmlos, solange alle Werkzeuge, die diesen State lesen, mit den neueren Angaben umgehen können.

Der Haken: Diese Anhebung ist eine Einbahnstraße. Älteres Terraform (z. B. das eingefrorene 1.5.7) kann einen State, dessen innere Versionsangaben ein neueres Werkzeug hochgezogen hat, nicht mehr zuverlässig lesen. Ein Downgrade dieser Angaben gibt es nicht.

Quick-Win: so sicherst du dich ab

  1. State sichern, bevor du den ersten apply mit OpenTofu fährst.
  2. Bucket-Versioning aktivieren (bei S3 & Co.), damit du jederzeit auf die vorherige State-Version zurückkannst.
  3. Niemals zuerst in Produktion migrieren. Übe in einer unkritischen Umgebung, bis der Ablauf sitzt.

Das klingt nach Pflichtprogramm, und das ist es auch. Denn genau dieser Mechanismus ist der Auslöser für die große Falle.

Falle 2: Wie terraform_remote_state die State-Version propagiert

In der Praxis sind Konfigurationen aufgeteilt, z. B. eine network-Konfiguration und eine app-Konfiguration. Die app greift über terraform_remote_state lesend auf den State der network-Konfiguration zu:

data "terraform_remote_state" "network" {
  backend = "s3"
  config = {
    bucket = "mein-state-bucket"
    key    = "network/terraform.tfstate"
    region = "eu-central-1"
  }
}

Und hier wird es gefährlich. terraform_remote_state liest nicht nur einzelne Outputs heraus. Es liest das komplette State-File ein, inklusive dieser inneren Versionsangaben.

Das Szenario:

  1. Du migrierst die network-Konfiguration auf OpenTofu und fährst einen apply. Die inneren Versionsangaben im network-State werden angehoben.
  2. Die app-Konfiguration läuft aber noch mit dem alten Terraform.
  3. Beim nächsten Lauf will die app über terraform_remote_state den network-State lesen, und kann die angehobenen Versionsangaben nicht mehr verarbeiten.
  4. Die app steht still. Obwohl an ihrem eigenen Code nichts geändert wurde.

Das ist der Moment, in dem ein Team ausgebremst wird, ohne zu verstehen, warum: Die Ursache liegt in einer anderen Konfiguration.

Die Lösung: als ein Paket migrieren

Interdependente Konfigurationen, die über terraform_remote_state verbunden sind, gehören gemeinsam migriert: in der richtigen Reihenfolge, als ein zusammenhängendes Paket. Migriere nicht die network, lass die app zurück und hoffe das Beste. Plane den Schnitt so, dass alle Beteiligten danach dasselbe Werkzeug (OpenTofu) und damit dieselben Versionsangaben in den State schreiben.

Übrigens: Den Daten-Block heißt weiterhin terraform_remote_state, auch unter OpenTofu. Es gibt hier nichts umzubenennen.

Details dazu im offiziellen Guide: Migrating multiple configurations.

Schnelldurchlauf: der Kleinkram

Drei Kleinigkeiten, die in der Praxis trotzdem stolpern lassen:

  1. required_version: Versions-Constraints, die auf Terraform-Versionen zielen, prüfen. OpenTofu hat eine eigene Versionsreihe (ab 1.6).
  2. Lock-File neu erzeugen: die .terraform.lock.hcl referenziert die Provider-Registry. Nach der Migration neu generieren, damit Provider aus registry.opentofu.org gezogen werden.
  3. Binary-Name tofu: durchsuche CI-Pipelines, Makefiles und Skripte nach hartcodierten terraform-Aufrufen und stelle sie auf tofu um.

Falle: der sso-Backend-Cache-Fehler

Eine Falle, die beim ersten tofu init mit S3-Backend zuverlässig zuschlägt:

Error: Failed to decode current backend config

The backend configuration created by the most recent run of "tofu init"
could not be decoded: unsupported attribute "sso".
Run "tofu init -reconfigure" to force re-initialization.

Ursache: Der lokale Backend-Cache .terraform/terraform.tfstate (das ist nicht dein echter State!) wurde von Terraform >= 1.6 geschrieben. Dessen s3-Backend kennt ein sso-Attribut (AWS IAM Identity Center). OpenTofus s3-Backend kennt dieses Attribut nicht, also scheitert das Decoding.

Fix (der Remote-State bleibt dabei völlig unangetastet):

tofu init -reconfigure
# Notnagel mit gleichem Effekt:
rm -rf .terraform && tofu init

Bewusst nicht -migrate-state: Das Backend wechselt ja gar nicht, nur der lokale Cache wird neu aufgebaut.

Fazit

Der Wechsel von Terraform zu OpenTofu ist in Isolation ein Einzeiler. Die Tücken stecken im Zusammenspiel mehrerer Konfigurationen. Du hast in diesem Tutorial gelernt:

  1. warum OpenTofu (Lizenzwechsel, nachgewiesener Fork-Punkt via git merge-base),
  2. dass der einfache Fall dank tofu init / tofu plan → „No changes” trivial ist,
  3. dass die State-Version eine Einbahnstraße ist, und wie du dich mit Backup und Versioning absicherst,
  4. wie terraform_remote_state genau diese Version über interdependente Konfigurationen propagiert und ein Team lahmlegen kann, und dass die Lösung das gemeinsame Migrieren als Paket ist,
  5. und wie du Kleinkram wie den sso-Backend-Cache-Fehler mit tofu init -reconfigure ausräumst.

Migriere in der richtigen Reihenfolge, und der Wechsel auf einen offenen, souveränen Stack ist kein Drama, sondern ein Routine-Schritt.

© 2026 Trutz Software Consulting GmbH. CC BY 4.0: Dieser Text darf mit Namensnennung weiterverwendet und bearbeitet werden, auch kommerziell. Code-Beispiele darin stehen unter Apache 2.0. Ausgenommen sind Marke und Logo sowie gekennzeichnete Zitate Dritter. Was das genau heißt.

Newsletter

Erhalte praxisnahe Tutorials, Best Practices und echte Lösungen für die häufigsten DevOps-Probleme direkt in Dein Postfach.

Datenschutz: Deine E-Mail-Adresse wird DSGVO-konform in Deutschland gespeichert. Keine Spam, nur relevante Inhalte. Eine E-Mail alle 1 bis 2 Wochen.