Open-source project
opentofu/opentofu avatar
opentofu/opentofu

The OpenTofu Docker image fails the build if you use it as a base, on purpose

OpenTofu lets you declaratively manage your cloud infrastructure.

30,841 stars1,428 forksGoMPL-2.0

At a glance

What is it?
OpenTofu is a Go infrastructure-as-code tool with a plan-and-apply workflow and a resource graph. Two details in its repository matter more than the feature list: the published image deliberately breaks if you inherit from it, and a separate experimental build exists behind a compile flag.
Who is it for?
OpenTofu fits a team that wants declarative infrastructure with a reviewable plan before anything changes, and that can accept the registry policy as a condition of use. Three things to check before adopting it.
Can I use it commercially?
Yes, with conditions. MPL-2.0 is a weak copyleft licence: you can use it inside commercial and closed-source software, but if you distribute changes to its own files, you must publish those changes under the same licence.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 13, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • opentofu/opentofu30,841 ★ · +671
Star history
Repository2026-09-132026-11-13
opentofu/opentofu30.2k30.8k

671 Stars in the last 61 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

The Docker image prints a warning and exits 1 when you inherit from it

The Dockerfile contains an ONBUILD step that is unusual enough to be worth reading closely. When your build uses the OpenTofu image as a base, the step prints a multi-line warning to standard error and then exits with status 1, failing your build. The warning text says the image is no longer supported as a base as of OpenTofu 1.10, tells you to follow the documentation for building your own image, and links an issue explaining the decision. This is a deliberate deprecation enforced in the build rather than a note in a changelog, so it turns a documentation requirement into a hard failure. The base itself is Alpine, with git, bash, and openssh installed, the binary copied to a path under the local bin directory, and that same binary declared as the entrypoint.

An experimental engine is compiled with a flag that also disables optimizations

The Makefile carries a second build target for what it calls experimental engine building. It sets an environment variable that enables the experimental runtime, and it adds a compiler flag that disables optimizations and inlining across all packages. It also passes a linker flag setting a variable named for experiments being allowed. The performance cost is a side effect of how the runtime is compiled rather than a stated goal. The matching test target restricts itself to one internal package instead of the whole tree, which tells you where the experimental code lives. So the experimental path is a compile-time switch, not a runtime configuration value, and a build made with it is a different binary from the one the release pipeline produces.

Nightly builds expire after thirty days and are labelled as not for production

There is a continuous build channel separate from releases, and its terms are stated plainly. Nightly builds are available for testing the latest changes on the main branch. They are described as experimental and explicitly not intended for production use. Each build is removed after thirty days, so the artifact URL for a given date stops working rather than going stale in place. Builds are listed at a nightly host, and a machine readable file at a separate path on that host is kept up to date with the latest build information for tooling that wants to consume it. The detail that matters operationally is the thirty day expiry, since a pipeline that pins a nightly URL will break on its own and needs a substitution step.

Registry access is blocked by country of origin, stated as sanctions compliance

The README documents a restriction that has no analogue in most infrastructure tools. In an effort to comply with applicable sanctions, access to the registry is blocked from specific countries of origin, and the registry repository holds the inclusion policy describing the detail. This is the kind of policy that does not affect a routine install and then becomes the deciding factor for a team with a distributed or multinational staff, or one operating under export controls. It is worth reading the policy before standardising on the tool rather than after a CI job fails for a reason that looks like a network fault. Two other contact routes sit nearby in the README: a liaison address for possible copyright and intellectual property issues, and a security policy for reporting vulnerabilities.

The plan step exists so a human can read the diff before anything is applied

The core workflow is described in four features, and the first two are the ones that shape day to day use. Infrastructure as code means infrastructure is described in a high-level configuration syntax, which lets a blueprint of a datacenter be versioned and treated like other code, and shared and reused. The execution plan is a distinct step: the tool generates a plan that shows what it will do when you apply, and the stated purpose is to avoid surprises when it manipulates infrastructure. The resource graph is what makes that plan meaningful, since OpenTofu builds a graph of all resources and parallelises creation and modification of non-dependent ones. The consequence is that operators get visibility into dependencies as a side effect of the mechanism that provides the speedup. The fourth feature, change automation, ties the other three together: complex changesets can be applied with minimal human interaction precisely because the plan already showed what would change and the graph already established the order, which the feature description presents as the way to avoid human error.

The repository is a Go module pinned to a specific toolchain version

The go.mod declares the module path and requires a specific Go language version, 1.27.3, rather than a range, so building from source pins the toolchain. What makes the file worth reading is the godebug block, which sets two defaults deliberately. One disables a TLS behaviour change related to a key exchange mechanism, and the comment explains why: the new Go feature had a number of open issues affecting named cloud services. The comment also records that the flag controlling it was named differently in an earlier Go release before being renamed, which is the kind of detail that saves an hour when a build behaves unexpectedly. A second setting disables a Windows symlink behaviour and links the pull request that changed it.

Governance documents are numerous and kept beside the code

The root of the repository is unusually heavy on process documents, which reflects a project that governs itself explicitly. There is a charter defining the project's scope, a governance document describing how decisions are made, a maintainers file, and a code of conduct. Contribution guidance is split in two, one document for ordinary contributions and a separate one for releases, so the release process has its own review path. A bug reports document and a changelog sit beside them, and a dedicated RFC directory exists for proposals. Release engineering is driven by a configuration file rather than by hand, and the Makefile pins a license checking tool to an exact version so that a dependency bump cannot silently change what the licence audit accepts. The build is also reproducible in a visible way: the binary embeds a version string derived from the git description, falling back to the commit hash when no tag is present, and a dirty working tree is recorded in that string rather than being hidden. Test targets run the whole package tree, and a separate coverage target writes an atomic profile and renders it to HTML, with the comment noting that atomic counters are what make the report correct when tests run in parallel.

Editorial conclusion

OpenTofu fits a team that wants declarative infrastructure with a reviewable plan before anything changes, and that can accept the registry policy as a condition of use. Three things to check before adopting it. The binary name is not the repository name, which matters for every script and CI job you write. The container image cannot be used as a base, so your build pipeline needs its own image. And the registry blocks access by country of origin, which is fine until you need to reason about who can run a plan.

Frequently asked questions

What is OpenTofu used for?

OpenTofu is an open source tool for building, changing, and versioning infrastructure. Infrastructure is described in a high-level configuration syntax so a blueprint can be versioned like code, and a planning step produces an execution plan showing what will change before anything is applied.

Is OpenTofu free?

It is released under the Mozilla Public License v2.0 and described as an open source tool. The README also states that access to the registry is blocked from specific countries of origin in order to comply with applicable sanctions.

how to install opentofu

The README does not contain an install command and links to the installation documentation on the project homepage. Building from source uses the Makefile, which produces a binary named tofu from the cmd/tofu package.

What is OpenTofu vs Terraform?

The README does not contain a comparison with Terraform. It describes OpenTofu as an open source tool for infrastructure as code, licensed under the Mozilla Public License v2.0, with a planning step, a resource graph, and nightly builds from the main branch.

Official sources

  1. License: MPL-2.0
  2. opentofu/opentofu on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/opentofu-opentofu.svg)](https://hysenlabs.com/projects/opentofu-opentofu)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/opentofu-opentofu.svg)](https://hysenlabs.com/projects/opentofu-opentofu)

Was this useful?