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 — OPEN-SOURCE INFRASTRUCTURE AS CODE Terraform (BSL) HashiCorp / IBM Lizenzänderung Aug. 2023 Fork OpenTofu (MPL 2.0) Linux Foundation registry.opentofu.org Zustandsverschlüsselung AES-GCM / AWS KMS / GCP KMS Frühe Variablenauswertung Vars in provider / backend Provider-Funktionen benutzerdefinierte HCL-Funktionen CI/CD-Pipeline setup-opentofu Action tofu plan → Genehmigung tofu apply OIDC-Authentifizierung AWS / Azure / GCP keine langlebigen Zugangsdaten Direkter Terraform-Ersatz · MPL 2.0 · Linux Foundation · tofu ersetzt terraform überall

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:

FunktionOpenTofuTerraform OSS
HCL-SyntaxIdentisch mit TF 1.5Gleich
Provider-Ökosystemregistry.opentofu.org + Fallback terraform.ioregistry.terraform.io
State-DateiformatBinärkompatibles .tfstateGleiches Format
.terraform.lock.hclFunktioniert unverändertGleich
Binärbefehletofu ersetzt terraform 1:1terraform
ZustandsverschlüsselungJa (AES-GCM, KMS)Nein
Frühe VariablenauswertungJa (1.8+)Nein
Provider-definierte FunktionenJa (1.8+)Nein
removed-BlockJa (1.7+)Partiell
Terraform CloudNicht kompatibelNativ

Die praktischen Migrationskosten für die meisten Teams bestehen in einem Suchen-und-Ersetzen von terraformtofu 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

FunktionOpenTofuTerraform OSSTerraform CloudPulumiCrossplaneCDK for TF
LizenzMPL 2.0BSL 1.1ProprietärApache 2.0Apache 2.0MPL 2.0
SpracheHCLHCLHCLPython/TS/GoYAML/GoPython/TS/Java
ZustandsverschlüsselungJa (eingebaut)NeinJa (verwaltet)Ja (verwaltet)N/ANein
Frühe Var-AuswertungJa (1.8+)NeinNeinN/AN/AN/A
Provider-ÖkosystemTerraform-ProviderTerraform-ProviderTerraform-ProviderPulumi-Provider + TF-BrückeKubernetes-CRDsTerraform-Provider
LernkurveGering (HCL)Gering (HCL)GeringMittel (echter Code)Hoch (K8s-CRDs)Mittel
Ideal fürOpen-Source-IaCKleine Teams, die BSL akzeptierenTeams, die verwaltetes Backend wollenEntwickler, die Code bevorzugenKubernetes-native TeamsEntwickler, 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 tofu durch terraform in 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- und provider-Blöcken und eliminiert viele partielle Konfigurationsworkarounds
  • Installation über apt, dnf, brew, asdf, Docker oder die GitHub Action setup-opentofu
  • Die CI/CD-Integration ist einfach: Ersetzen Sie terraform durch tofu, verwenden Sie OIDC für Cloud-Authentifizierung und folgen Sie dem Plan → Überprüfung → Apply-Workflow

Verwandte Artikel