Require a specific Terraform version#

Why use version constraints#

HashiCorp offers Terraform Cloud as a service to run Terraform and keep the state instead of having a local copy of the state databases. This is great to make full use of Infrastructure-as-Code tools like Terraform and everyone can run them without losing the correct state. But when setting up a deployment plan a specific version of Terraform has to be selected manually in the webinterface, and you also have to manually increase it when new versions come out.

As the version, for now, can only be set via the webinterface of Terraform Cloud and allow a lot of people to forget to set it to a higher version causing life-cycle-management issues plans do work for repository A, but not for repository B as both plans use a different version of Terraform. While currently now option exists to define the version of Terraform to use when the plan runs, the configuration allows to specify the version of Terraform is required.

With the option required_version in the terraform block as shown below on line 2, we can enforce the version requirements.

Example of providers.tf with pinning the required version of Terraform#
terraform {
  required_version = "1.3.0"
}

When we now deploy the new configuration we see Terraform Cloud stops with the error that it tries to run the plan with a mismatched version of Terraform. Until we set the correct version in the webinterface of Terraform Cloud for this plan we can’t deploy anymore.

The output of Terraform Cloud when the version requirement is failing#

│ Error: Unsupported Terraform Core version

│   on providers.tf line 2, in terraform:
│    2:   required_version = "1.3.0"

│ This configuration does not support Terraform version 1.1.8. To proceed,
│ either choose another supported Terraform version or update this version
│ constraint. Version constraints are normally set for good reason, so
│ updating the constraint may lead to other errors or unexpected behavior.

Version constraint operators#

In the first example, the required version was pinned to 1.3.0, but more options to define constraints are possible and look familiar to other languages. The following constraint operators are valid to quote the Terraform documentation:

  • = (or no operator): Allows only one exact version number. Cannot be combined with other conditions.

  • !=: Excludes an exact version number.

  • >, >=, <, <=: Comparisons against a specified version, allowing versions for which the comparison is true. “Greater-than” requests newer versions, and “less-than” requests older versions.

  • ~>: Allows only the rightmost version component to increment. For example, to allow new patch releases within a specific minor release, use the full version number: ~> 1.0.4 will allow installation of 1.0.5 and 1.0.10 but not 1.1.0. This is usually called the pessimistic constraint operator.

The first operator is the = or when no operator is specified as in the first example. This allows for exact version pinning.

Example of the = operator#
terraform {
  required_version = "=1.3.0"
}

The second set of operators are the comparison operators and allows you to specify a minimum version with >= for example.

Example of the >= operator#
terraform {
  required_version = ">=1.3.0"
}

The comparison operators can also be combined to specify both a minimum and maximum version so you can stay within certain boundaries.

Example of both the >= and < operator#
terraform {
  required_version = ">=1.3.0,<1.4.0"
}

The previous example to specify a minimum and maximum version can also be rewritten with the ~> comparison operator. This allows the plan to be executed when the major and minor versions are matching and the patch version is at least on that version as Terraform follows Semantic Versioning.

Example of the ~> operator#
terraform {
  required_version = "~>1.3.0"
}

Best practices for the required_version option#

As seen in the previous section using the pessimistic constraint operator may give best of both worlds as limits the required version to a certain feature set and doesn’t require exact matching versions except to match the minimum required version.

Example of the pessimistic constraint operator#
terraform {
  required_version = "~>1.3.5"
}

Also as GitHub Dependabot isn’t keeping track of the required version of Terraform you need to keep manually track of new versions. A scheduled workflow in GitHub Actions to create an issue every three or six months may be an option until Dependabot can create merge requests.

Note

HashiCorp Terraform follows a two-year support policy or the last two major and minor versions. See endoflife for more information about supported versions.