TL;DR — Kurzzusammenfassung
OpenTofu ist der Open-Source-Fork von Terraform der Linux Foundation. Installation, Migration, Zustandsverschlüsselung, HCL-Syntax und CI/CD-Integration.
OpenTofu ist der Open-Source-Fork von Terraform, der unter der Linux Foundation gepflegt wird und entstand, nachdem HashiCorp im August 2023 die Lizenz von Terraform von der Mozilla Public License 2.0 auf die Business Source License (BSL) geändert hatte. Dieser Leitfaden deckt alles ab, was Sie brauchen, um die Ursprünge von OpenTofu zu verstehen, es zu installieren, bestehende Terraform-Projekte reibungslos zu migrieren, HCL-Grundlagen zu beherrschen, den Zustand mit clientseitiger Verschlüsselung sicher zu verwalten und es in moderne CI/CD-Pipelines zu integrieren.
Warum OpenTofu Existiert: Die Geschichte des Lizenz-Forks
Terraform war über neun Jahre lang unter MPL 2.0 Open Source. Am 10. August 2023 kündigte HashiCorp an, dass Terraform 1.6 und alle zukünftigen Versionen unter der Business Source License (BSL 1.1) veröffentlicht werden — eine Source-Available-Lizenz, die die Nutzung der Software zur Konkurrenz mit HashiCorp kommerziell einschränkt.
Die Reaktion der Community war schnell. Innerhalb von Tagen unterzeichneten Ingenieure von Spacelift, Gruntwork, Env0, Harness, Scalr und anderen einen offenen Brief und erstellten den OpenTofu-Fork aus der letzten MPL 2.0-Version (Terraform 1.5.7). Die Linux Foundation akzeptierte OpenTofu im September 2023 als Projekt, und OpenTofu 1.6.0 — das erste stabile Release mit neuen Features — erschien im Januar 2024.
Wichtige Auswirkungen der Lizenzänderung:
- Terraform OSS ist jetzt BSL — Sie können damit kein konkurrierendes Produkt erstellen
- OpenTofu bleibt MPL 2.0 — vollständig Open Source, ohne kommerzielle Einschränkungen
- HashiCorp (jetzt IBM) kontrolliert Terraform Cloud und Terraform Enterprise
- OpenTofu wird community-gesteuert, mit einem Technical Steering Committee und offenem RFC-Prozess
OpenTofu vs Terraform Kompatibilität
OpenTofu 1.6–1.9 zielt auf Drop-in-Kompatibilität mit Terraform 1.5.x ab:
| Funktion | OpenTofu | Terraform OSS |
|---|---|---|
| HCL-Syntax | Identisch mit TF 1.5 | Gleich |
| Provider-Ökosystem | registry.opentofu.org + Fallback terraform.io | registry.terraform.io |
| State-Dateiformat | Binärkompatibles .tfstate | Gleiches Format |
.terraform.lock.hcl | Funktioniert unverändert | Gleich |
| Binärbefehle | tofu ersetzt terraform 1:1 | terraform |
| Zustandsverschlüsselung | Ja (AES-GCM, KMS) | Nein |
| Frühe Variablenauswertung | Ja (1.8+) | Nein |
| Provider-definierte Funktionen | Ja (1.8+) | Nein |
removed-Block | Ja (1.7+) | Partiell |
| Terraform Cloud | Nicht kompatibel | Nativ |
Die praktischen Migrationskosten für die meisten Teams bestehen in einem Suchen-und-Ersetzen von terraform → tofu in CI-Skripten. HCL-Dateien, Provider, Module und State-Dateien bleiben unberührt.
Installation
apt (Debian / Ubuntu)
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://get.opentofu.org/opentofu.gpg | \
sudo tee /etc/apt/keyrings/opentofu.gpg > /dev/null
curl -fsSL https://packages.opentofu.org/opentofu/tofu/gpgkey | \
sudo gpg --no-tty --batch --dearmor -o /etc/apt/keyrings/opentofu-repo.gpg > /dev/null
echo "deb [signed-by=/etc/apt/keyrings/opentofu.gpg,/etc/apt/keyrings/opentofu-repo.gpg] \
https://packages.opentofu.org/opentofu/tofu/any/ any main" | \
sudo tee /etc/apt/sources.list.d/opentofu.list
sudo apt update && sudo apt install -y opentofu
tofu version
dnf (RHEL / Fedora / Rocky)
sudo tee /etc/yum.repos.d/opentofu.repo <<'EOF'
[opentofu]
name=opentofu
baseurl=https://packages.opentofu.org/opentofu/tofu/rpm_any/rpm_any/$basearch
enabled=1
gpgcheck=1
gpgkey=https://get.opentofu.org/opentofu.gpg
EOF
sudo dnf install -y opentofu
Homebrew
brew install opentofu
asdf
asdf plugin add opentofu
asdf install opentofu 1.9.0
asdf global opentofu 1.9.0
Migration von Terraform
Schritt 1 — OpenTofu neben Terraform installieren
Beide Binärdateien können koexistieren. tofu und terraform sind separate ausführbare Dateien.
Schritt 2 — tofu init im bestehenden Projekt ausführen
cd mein-terraform-projekt/
tofu init
OpenTofu liest denselben versions.tf-/required_providers-Block. Es lädt Provider von registry.opentofu.org herunter. Ihre .terraform.lock.hcl wird unverändert wiederverwendet.
Schritt 3 — terraform durch tofu in CI-Skripten ersetzen
# Vorher
terraform fmt -check
terraform init -input=false
terraform plan -out=tfplan
terraform apply -auto-approve tfplan
# Nachher (keine Logikänderung)
tofu fmt -check
tofu init -input=false
tofu plan -out=tfplan
tofu apply -auto-approve tfplan
Schritt 4 — State-Kompatibilität überprüfen
Das .tfstate JSON-Format ist identisch. Wenn Sie Remote-State verwalten (S3, GCS, Azure Blob), ist keine Migration erforderlich. Führen Sie einen Plan mit OpenTofu aus: Er sollte keine Änderungen zeigen, wenn die Infrastruktur dem bestehenden State entspricht.
tofu plan
# Erwartet: No changes. Your infrastructure matches the configuration.
HCL-Grundlagen
Provider, Ressourcen und Datenquellen
terraform {
required_version = ">= 1.6"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.40"
}
}
}
provider "aws" {
region = var.aws_region
}
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr
enable_dns_support = true
enable_dns_hostnames = true
tags = {
Name = "${var.project}-vpc"
Environment = var.environment
}
}
data "aws_ami" "al2023" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["al2023-ami-2023.*-x86_64"]
}
}
Variablen, Locals und Outputs
variable "environment" {
type = string
validation {
condition = contains(["dev", "staging", "prod"], var.environment)
error_message = "Die Umgebung muss dev, staging oder prod sein."
}
}
locals {
common_tags = {
Project = var.project
Environment = var.environment
ManagedBy = "opentofu"
}
}
output "vpc_id" {
description = "ID des erstellten VPC"
value = aws_vpc.main.id
}
count und for_each
resource "aws_subnet" "public" {
count = 3
vpc_id = aws_vpc.main.id
cidr_block = cidrsubnet(var.vpc_cidr, 8, count.index)
availability_zone = data.aws_availability_zones.available.names[count.index]
tags = merge(local.common_tags, { Name = "${var.project}-oeffentlich-${count.index + 1}" })
}
resource "aws_s3_bucket" "this" {
for_each = var.buckets
bucket = "${var.project}-${each.key}-${data.aws_caller_identity.current.account_id}"
tags = merge(local.common_tags, { Name = each.key })
}
Dynamische Blöcke
resource "aws_security_group" "web" {
name = "${var.project}-sg-web"
vpc_id = aws_vpc.main.id
dynamic "ingress" {
for_each = var.eingangsregeln
content {
from_port = ingress.value.port
to_port = ingress.value.port
protocol = ingress.value.protokoll
cidr_blocks = ingress.value.cidrs
description = ingress.value.beschreibung
}
}
}
Zustandsverwaltung
Remote-Backends
# S3 + DynamoDB
terraform {
backend "s3" {
bucket = "mein-tofu-state-bucket"
key = "prod/infra/terraform.tfstate"
region = "us-east-1"
dynamodb_table = "tofu-state-sperren"
encrypt = true
}
}
Clientseitige Zustandsverschlüsselung (exklusiv für OpenTofu)
# AWS KMS (empfohlen für Produktion)
terraform {
encryption {
key_provider "aws_kms" "prod_schluessel" {
kms_key_id = "arn:aws:kms:us-east-1:123456789012:key/mrk-abc123"
region = "us-east-1"
key_spec = "AES_256"
}
method "aes_gcm" "prod_methode" {
keys = key_provider.aws_kms.prod_schluessel
}
state {
method = method.aes_gcm.prod_methode
}
plan {
method = method.aes_gcm.prod_methode
}
}
}
Nützliche State-Befehle
tofu state list
tofu state show aws_instance.web[0]
tofu import aws_s3_bucket.assets mein-vorhandener-bucket
tofu state mv aws_instance.web aws_instance.app
tofu force-unlock LOCK_ID
Module
# Lokaler Pfad
module "vpc" {
source = "./modules/vpc"
project = var.project
cidr = "10.0.0.0/16"
}
# Git-Tag
module "vpc_staging" {
source = "git::https://github.com/org/infra-modules.git//vpc?ref=v2.3.0"
project = var.project
cidr = "10.1.0.0/16"
}
# OpenTofu/Terraform-Registry
module "eks" {
source = "terraform-aws-modules/eks/aws"
version = "~> 20.0"
cluster_name = "${var.project}-${var.environment}"
vpc_id = module.vpc.vpc_id
subnet_ids = module.vpc.subnet_ids
}
Workspaces
tofu workspace new staging
tofu workspace new prod
tofu workspace list
tofu workspace select staging
locals {
umgebung_konfiguration = {
dev = { instanz_typ = "t3.micro", min = 1, max = 2 }
staging = { instanz_typ = "t3.small", min = 2, max = 4 }
prod = { instanz_typ = "t3.medium", min = 3, max = 10 }
}
aktuell = local.umgebung_konfiguration[terraform.workspace]
}
CI/CD-Integration
GitHub Actions mit OIDC
name: OpenTofu Plan und Apply
on:
push:
branches: [main]
pull_request:
branches: [main]
permissions:
id-token: write
contents: read
pull-requests: write
jobs:
tofu:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: OpenTofu einrichten
uses: opentofu/setup-opentofu@v1
with:
tofu_version: "1.9.0"
- name: AWS-Zugangsdaten via OIDC konfigurieren
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/GitHubActionsTofu
aws-region: us-east-1
- name: tofu init
run: tofu init -input=false
- name: tofu fmt prüfen
run: tofu fmt -check -recursive
- name: tofu validate
run: tofu validate
- name: tofu plan
run: tofu plan -out=tfplan -input=false
- name: tofu apply
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
run: tofu apply -auto-approve tfplan
Tool-Vergleichstabelle
| Funktion | OpenTofu | Terraform OSS | Terraform Cloud | Pulumi | Crossplane | CDK for TF |
|---|---|---|---|---|---|---|
| Lizenz | MPL 2.0 | BSL 1.1 | Proprietär | Apache 2.0 | Apache 2.0 | MPL 2.0 |
| Sprache | HCL | HCL | HCL | Python/TS/Go | YAML/Go | Python/TS/Java |
| Zustandsverschlüsselung | Ja (eingebaut) | Nein | Ja (verwaltet) | Ja (verwaltet) | N/A | Nein |
| Frühe Var-Auswertung | Ja (1.8+) | Nein | Nein | N/A | N/A | N/A |
| Provider-Ökosystem | Terraform-Provider | Terraform-Provider | Terraform-Provider | Pulumi-Provider + TF-Brücke | Kubernetes-CRDs | Terraform-Provider |
| Lernkurve | Gering (HCL) | Gering (HCL) | Gering | Mittel (echter Code) | Hoch (K8s-CRDs) | Mittel |
| Ideal für | Open-Source-IaC | Kleine Teams, die BSL akzeptieren | Teams, die verwaltetes Backend wollen | Entwickler, die Code bevorzugen | Kubernetes-native Teams | Entwickler, die HCL nicht mögen |
Praktisches Beispiel: AWS-Infrastruktur
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr
enable_dns_support = true
enable_dns_hostnames = true
tags = merge(local.common_tags, { Name = "${var.project}-vpc" })
}
resource "aws_subnet" "public" {
count = var.az_count
vpc_id = aws_vpc.main.id
cidr_block = cidrsubnet(var.vpc_cidr, 8, count.index)
availability_zone = data.aws_availability_zones.available.names[count.index]
map_public_ip_on_launch = true
tags = merge(local.common_tags, { Name = "${var.project}-oeffentlich-${count.index + 1}" })
}
resource "aws_lb" "main" {
name = "${var.project}-alb"
internal = false
load_balancer_type = "application"
security_groups = [aws_security_group.alb.id]
subnets = aws_subnet.public[*].id
tags = local.common_tags
}
resource "aws_autoscaling_group" "app" {
name = "${var.project}-asg"
vpc_zone_identifier = aws_subnet.private[*].id
target_group_arns = [aws_lb_target_group.app.arn]
min_size = local.aktuell.min
max_size = local.aktuell.max
launch_template {
id = aws_launch_template.app.id
version = "$Latest"
}
}
output "alb_dns_name" {
description = "DNS-Name des Application Load Balancers"
value = aws_lb.main.dns_name
}
Fallstricke und Randfälle
Provider-Registry-Fallback: OpenTofu prüft zuerst registry.opentofu.org. Wenn ein Provider nur auf registry.terraform.io verfügbar ist, fügen Sie eine explizite source in required_providers hinzu.
Migration der Zustandsverschlüsselung: Das Aktivieren der Verschlüsselung für eine bestehende unverschlüsselte State-Datei ist ein einseitiger Vorgang pro Schlüssel. Planen Sie das Rollout sorgfältig — dokumentieren Sie Ihren Schlüssel-ARN und stellen Sie sicher, dass mehrere Teammitglieder Zugang zu KMS haben, bevor Sie es aktivieren.
Frühe Variablenauswertung (1.8+): Variablen können jetzt in backend- und provider-Blöcken verwendet werden, was in vielen Setups die Notwendigkeit von partiellen Backend-Konfigurationsworkarounds eliminiert.
Workspace-Isolation: CLI-Workspaces teilen sich denselben Backend-Bucket, verwenden aber unterschiedliche State-Keys. Sie bieten KEINE Isolation von Cloud-Zugangsdaten, IAM-Rollen oder Provider-Konfigurationen.
Zusammenfassung
- OpenTofu wurde im August 2023 von Terraform 1.5.7 geforkt, nachdem HashiCorp die BSL-Lizenzänderung vorgenommen hatte, und ist jetzt ein Linux Foundation-Projekt unter MPL 2.0
- Es ist ein direkter Ersatz für Terraform 1.5.x — gleiches HCL, gleiche Provider, gleiches State-Format; die Migration erfordert nur das Ersetzen von
tofudurchterraformin Befehlen - Die clientseitige Zustandsverschlüsselung (AES-GCM, AWS KMS, GCP KMS) ist das bedeutendste neue Feature von OpenTofu — in Terraform OSS nicht verfügbar
- Die frühe Variablenauswertung (1.8+) ermöglicht Variablen in
backend- undprovider-Blöcken und eliminiert viele partielle Konfigurationsworkarounds - Installation über
apt,dnf,brew,asdf, Docker oder die GitHub Actionsetup-opentofu - Die CI/CD-Integration ist einfach: Ersetzen Sie
terraformdurchtofu, verwenden Sie OIDC für Cloud-Authentifizierung und folgen Sie dem Plan → Überprüfung → Apply-Workflow
Verwandte Artikel
- Einführung in Terraform: Infrastructure as Code
- Ansible Playbooks und Rollen: Vollständiger Leitfaden zur Infrastrukturautomatisierung
- Ansible für Einsteiger: Serverkonfiguration ohne Agent automatisieren
- Docker Compose: Multi-Container-Anwendungen definieren und ausführen
- GitHub Actions: Vollständiger Leitfaden zur CI/CD-Automatisierung