Note: This page is about a feature of Terraform 0.14 and later. Priorversions of Terraform did not track dependency selections at all, so theinformation here is not relevant to those versions.
Hands-on: Try the Lock and Upgrade Provider Versions tutorial.
A Terraform configuration may refer to two different kinds of externaldependency that come from outside of its own codebase:
- Providers, which are plugins for Terraformthat extend it with support for interacting with various external systems.
- Modules, which allowsplitting out groups of Terraform configuration constructs (written in theTerraform language) into reusable abstractions.
Both of these dependency types can be published and updated independently fromTerraform itself and from the configurations that depend on them. For thatreason, Terraform must determine which versions of those dependencies arepotentially compatible with the current configuration and which versions arecurrently selected for use.
Version constraints within the configurationitself determine which versions of dependencies are potentially compatible,but after selecting a specific version of each dependency Terraform remembersthe decisions it made in a dependency lock file so that it can (by default)make the same decisions again in future.
At present, the dependency lock file tracks only provider dependencies.Terraform does not remember version selections for remote modules, and soTerraform will always select the newest available module version that meetsthe specified version constraints. You can use an exact version constraintto ensure that Terraform will always select the same module version.
The dependency lock file is a file that belongs to the configuration as awhole, rather than to each separate module in the configuration. For that reasonTerraform creates it and expects to find it in your current working directorywhen you run Terraform, which is also the directory containing the .tf
filesfor the root module of your configuration.
The lock file is always named .terraform.lock.hcl
, and this name is intendedto signify that it is a lock file for various items that Terraform caches inthe .terraform
subdirectory of your working directory.
Terraform automatically creates or updates the dependency lock file each timeyou run the terraform init command. You shouldinclude this file in your version control repository so that you can discusspotential changes to your external dependencies via code review, just as youwould discuss potential changes to your configuration itself.
The dependency lock file uses the same low-level syntax as the main Terraformlanguage, but the dependency lock file is not itself a Terraform languageconfiguration file. It is named with the suffix .hcl
instead of .tf
inorder to signify that difference.
Dependency Installation Behavior
When terraform init
is working on installing all of the providers needed fora configuration, Terraform considers both the version constraints in theconfiguration and the version selections recorded in the lock file.
If a particular provider has no existing recorded selection, Terraform willselect the newest available version that matches the given version constraint,and then update the lock file to include that selection.
If a particular provider already has a selection recorded in the lock file,Terraform will always re-select that version for installation, even if anewer version has become available. You can override that behavior by addingthe -upgrade
option when you run terraform init
, in which case Terraformwill disregard the existing selections and once again select the newestavailable version matching the version constraint.
If a particular terraform init
call makes changes to the lock file, Terraformwill mention that as part of its output:
Terraform has made some changes to the provider dependency selections recordedin the .terraform.lock.hcl file. Review those changes and commit them to yourversion control system if they represent changes you intended to make.
When you see this message, you can use your version control system toreview the changes Terraform has proposed in the file,and if they represent changes you made intentionally you can send the changethrough your team's usual code review process.
Checksum verification
Terraform will also verify that each package it installs matches at least oneof the checksums it previously recorded in the lock file, if any, returning anerror if none of the checksums match:
Error: Failed to install providerError while installing hashicorp/azurerm v2.1.0: the current package forregistry.terraform.io/hashicorp/azurerm 2.1.0 doesn't match any of thechecksums previously recorded in the dependency lock file.
This checksum verification is intended to represent atrust on first useapproach. When you add a new provider for the first time you can verify itin whatever way you choose or any way you are required to by relevantregulations, and then trust that Terraform will raise an error if a futurerun of terraform init
encounters a non-matching package for the sameprovider version.
There are two special considerations with the "trust on first use" model:
If you install a provider from an origin registry which provides checksumsthat are signed with a cryptographic signature, Terraform will treat allof the signed checksums as valid as long as one checksum matches. The lockfile will therefore include checksums for both the package you installed foryour current platform and any other packages that might be available forother platforms.
In this case, the
terraform init
output will include the fingerprint ofthe key that signed the checksums, with a message like(signed by a HashiCorp partner, key ID DC9FC6B1FCE47986)
. You may wish toconfirm that you trust the holder of the given key before committing thelock file containing the signed checksums, or to retrieve and verify thefull set of available packages for the given provider version.If you install a provider for the first time using an alternativeinstallation method, such as a filesystem or network mirror, Terraform willnot be able to verify the checksums for any platform other than the onewhere you ran
terraform init
, and so it will not record the checksumsfor other platforms and so the configuration will not be usable on any otherplatform.To avoid this problem you can pre-populate checksums for a variety ofdifferent platforms in your lock file usingthe terraform providers lock command,which will then allow future calls to
terraform init
to verify that thepackages available in your chosen mirror match the official packages fromthe provider's origin registry.
Because the dependency lock file is primarily maintained automatically byTerraform itself, rather than being updated manually by you or your team,your version control system may show you that the file has changed.
There are a few different types of changes that Terraform can potentially maketo your lock file, which you may need to understand in order to review theproposed changes. The following sections will describe these common situations.
Dependency on a new provider
If you add a new entry to theprovider requirements for any module in yourconfiguration, or if you add an external module that includes a new providerdependency itself, terraform init
will respond to that by selecting thenewest version of that provider which meets all of the version constraintsin the configuration, and it will record its decision as a new provider
block in the dependency lock file.
--- .terraform.lock.hcl 2020-10-07 16:12:07.539570634 -0700+++ .terraform.lock.hcl 2020-10-07 16:12:15.267487237 -0700@@ -6,6 +6,26 @@ ] }+provider "registry.terraform.io/hashicorp/azurerm" {+ version = "2.30.0"+ constraints = "~> 2.12"+ hashes = [+ "h1:FJwsuowaG5CIdZ0WQyFZH9r6kIJeRKts9+GcRsTz1+Y=",+ "h1:c/ntSXrDYM1mUir2KufijYebPcwKqS9CRGd3duDSGfY=",+ "h1:yre4Ph76g9H84MbuhZ2z5MuldjSA4FsrX6538O7PCcY=",+ "zh:04f0a50bb2ba92f3bea6f0a9e549ace5a4c13ef0cbb6975494cac0ef7d4acb43",+ "zh:2082e12548ebcdd6fd73580e83f626ed4ed13f8cdfd51205d8696ffe54f30734",+ "zh:246bcc449e9a92679fb30f3c0a77f05513886565e2dcc66b16c4486f51533064",+ "zh:24de3930625ac9014594d79bfa42d600eca65e9022b9668b54bfd0d924e21d14",+ "zh:2a22893a576ff6f268d9bf81cf4a56406f7ba79f77826f6df51ee787f6d2840a",+ "zh:2b27485e19c2aaa9f15f29c4cff46154a9720647610171e30fc6c18ddc42ec28",+ "zh:435f24ce1fb2b63f7f02aa3c84ac29c5757cd29ec4d297ed0618423387fe7bd4",+ "zh:7d99725923de5240ff8b34b5510569aa4ebdc0bdb27b7bac2aa911a8037a3893",+ "zh:7e3b5d0af3b7411dd9dc65ec9ab6caee8c191aee0fa7f20fc4f51716e67f50c0",+ "zh:da0af4552bef5a29b88f6a0718253f3bf71ce471c959816eb7602b0dadb469ca",+ ]+}+ provider "registry.terraform.io/newrelic/newrelic" { version = "2.1.2" constraints = "~> 2.1.1"
The new lock file entry records several pieces of information:
- version: the exact version that Terraform selected based on the versionconstraints in the configuration.
- constraints: all of the version constraints that Terraform considered whenmaking this selection. (Terraform doesn't actually use this information tomake installation decisions, but includes it to help explain to human readershow the previous decision was made.)
- hashes: a number of checksums that are all considered to be valid forpackages implementing the selected version of this provider on differentplatforms. The meaning of these hashes is explained more underNew provider package checksums below.
New version of an existing provider
If you run terraform init -upgrade
to ask Terraform to consider newer providerversions that still match the configured version constraints, Terraform maythen select a newer version for a provider and update its existing provider
block to reflect that change.
--- .terraform.lock.hcl 2020-10-07 16:44:25.819579509 -0700+++ .terraform.lock.hcl 2020-10-07 16:43:42.785665945 -0700@@ -7,22 +7,22 @@ } provider "registry.terraform.io/hashicorp/azurerm" {- version = "2.1.0"- constraints = "~> 2.1.0"+ version = "2.0.0"+ constraints = "2.0.0" hashes = [- "h1:EOJImaEaVThWasdqnJjfYc6/P8N/MRAq1J7avx5ZbV4=",- "zh:0015b491cf9151235e57e35ea6b89381098e61bd923f56dffc86026d58748880",- "zh:4c5682ba1e0fc7e2e602d3f103af1638f868c31fe80cc1a884a97f6dad6e1c11",- "zh:57bac885b108c91ade4a41590062309c832c9ab6bf6a68046161636fcaef1499",- "zh:5810d48f574c0e363c969b3f45276369c8f0a35b34d6202fdfceb7b85b3ac597",- "zh:5c6e37a44462b8662cf9bdd29ce30523712a45c27c5d4711738705be0785db41",- "zh:64548940a3387aa3a752e709ee9eb9982fa820fe60eb60e5f212cc1d2c58549e",- "zh:7f46749163da17330bbb5293dc825333c86304baa0a7c6256650ac536b4567c8",- "zh:8f8970f2df75ac43ffdd112055ee069d8bd1030f7eb4367cc4cf494a1fa802c3",- "zh:9ad693d00dc5d7d455d06faba70e716bce727c6706f7293288e87fd7956b8fe0",- "zh:b6e3cb55e6aec62b47edd0d2bd5e14bd6a2bcfdac65930a6e9e819934734c57b",- "zh:d6a3f3b9b05c28ecf3919e9e7afa185805a6d7442fc4b3eedba749c2731d1f0e",- "zh:d81fb624a357c57c7ea457ce543d865b39b12f26c2edd58a2f7cd43326c91010",+ "h1:bigGXBoRbp7dv79bEEn+aaju8575qEXHQ57XHVPJeB8=",+ "zh:09c603c8904ca4a5bc19e82335afbc2837dcc4bee81e395f9daccef2f2cba1c8",+ "zh:194a919d4836d6c6d4ce598d0c66cce00ddc0d0b5c40d01bb32789964d818b42",+ "zh:1f269627df4e266c4e0ef9ee2486534caa3c8bea91a201feda4bca525005aa0a",+ "zh:2bae3071bd5f8e553355c4b3a547d6efe1774a828142b762e9a4e85f79be7f63",+ "zh:6c98dfa5c3468e8d02e2b3af7c4a8a14a5d469ce5a642909643b413a17ca338b",+ "zh:7af78f61666fd45fbf428161c061ea2623162d601b79dc71d6a5158756853ffa",+ "zh:883c2df86ae9ba2a5c167cf5c2c7deca0239171a224d6d335f0fd6dd9c283830",+ "zh:a2028379078577d8ff5ecfca6e8a8b25a25ffb1686de0ee52a7fe8011783488b",+ "zh:abe6ef399552fd3861a454a839cd978c1d15735658fdc00f9054435aff0f4620",+ "zh:c30b1bf14077913c3cdf34979b1434dbb1353cb5995eb3956b191c50538b64a9",+ "zh:ca64ae2ad9793e5631e3b0b9327f7cb22cb5d8e9de57be7d85821791b1d5a375",+ "zh:fffe56904a38109bb8d613b02808a177c3ddfac19f03b3aac799281fea38f475", ] }
The primary effect of selecting a new provider version is to change thevalue of version
in the provider
block. If the upgrade came along witha change to the configured version constraints, Terraform will also recordthat change in the constraints
value.
Because each version has its own set of distribution packages, switching toa new version will also tend to replace all of the values in hashes
, toreflect the checksums of the packages for the new version.
New provider package checksums
A more subtle change you may see in a provider
block is the addition ofnew checksums that were not previously recorded, even though nothing elsein the provider
block has changed:
--- .terraform.lock.hcl 2020-10-07 17:24:23.397892140 -0700+++ .terraform.lock.hcl 2020-10-07 17:24:57.423130253 -0700@@ -10,6 +10,7 @@ version = "2.1.0" constraints = "~> 2.1.0" hashes = [+ "h1:1xvaS5D8B8t6J6XmXxX8spo97tAzjhacjedFX1B47Fk=", "h1:EOJImaEaVThWasdqnJjfYc6/P8N/MRAq1J7avx5ZbV4=", "zh:0015b491cf9151235e57e35ea6b89381098e61bd923f56dffc86026d58748880", "zh:4c5682ba1e0fc7e2e602d3f103af1638f868c31fe80cc1a884a97f6dad6e1c11",
The addition of a new checksum into the hashes
value represents Terraformgradually transitioning between different hashing schemes. The h1:
andzh:
prefixes on these values represent different hashing schemes, eachof which represents calculating a checksum using a different algorithm.We may occasionally introduce new hashing schemes if we learn of limitationsin the existing schemes or if a new scheme offers some considerableadditional benefit.
The two hashing schemes currently supported are:
zh:: a mnemonic for "zip hash", this is a legacy hash format which ispart of the Terraform provider registry protocol and is therefore used forproviders that you install directly from an origin registry.
This hashing scheme captures a SHA256 hash of each of the official
.zip
packages indexed in the origin registry. This is an effective scheme forverifying the official release packages when installed from a registry, butit's not suitable for verifying packages that come from otherprovider installation methods,such as filesystem mirrors using the unpacked directory layout.h1:: a mnemonic for "hash scheme 1", which is the current preferred hashingscheme.
Hash scheme 1 is also a SHA256 hash, but is one computed from the contentsof the provider distribution package, rather than of the
.zip
archiveit's contained within. This scheme therefore has the advantage that it canbe calculated for an official.zip
file, an unpacked directory with thesame contents, or a recompressed.zip
file which contains the same filesbut potentially different metadata or compression schemes.Due to the limited scope of the
zh:
scheme, Terraform willopportunistically add in the correspondingh1:
checksums as it learnsof them, which is what caused the addition of a secondh1:
checksumin the example change shown above.
Terraform will add a new hash to an existing provider only if the hash iscalculated from a package that also matches one of the existing hashes. Inthe above example, Terraform installed a hashicorp/azurerm
package for adifferent platform than that which produced the original h1:
checksum, but wasable to match it against one of the zh:
checksums recorded previously.After confirming the zh:
checksum match, Terraform then recorded thecorresponding h1:
checksum in order to gradually migrate from the old schemeto the new scheme.
When installing a particular provider for the first time (where there is noexisting provider
block for it), Terraform will pre-populate the hashes
value with any checksums that are covered by the provider developer'scryptographic signature, which usually covers all of the available packagesfor that provider version across all supported platforms. However, becausethe provider registry protocol still uses the zh:
scheme, the initial setwill consist primarily of hashes using that scheme, which Terraform will thenupgrade opportunistically as you install the packages on different platforms.
If you wish to avoid ongoing additions of new h1:
hashes as you work withyour configuration on new target platforms, or if you are installing providersfrom a mirror that therefore can't provide official signed checksums, youcan ask Terraform to pre-populate hashes for a chosen set of platformsusingthe terraform providers lock command:
terraform providers lock \ -platform=linux_arm64 \ -platform=linux_amd64 \ -platform=darwin_amd64 \ -platform=windows_amd64
The above command will download and verify the official packages for all ofthe required providers across all four of the given platforms, and then recordboth zh:
and h1:
checksums for each of them in the lock file, thus avoidingthe case where Terraform will learn about a h1:
equivalent only at a latertime. See the terraform providers lock
documentation for more information onthis command.
Providers that are no longer required
To determine whether there still exists a dependency on a given provider,Terraform uses two sources of truth: the configuration itself, and the state.If you remove the last dependency on a particular provider from both yourconfiguration and state, then terraform init
will remove any existing lockfile entry for that provider.
--- .terraform.lock.hcl 2020-10-07 16:12:07.539570634 -0700+++ .terraform.lock.hcl 2020-10-07 16:12:15.267487237 -0700@@ -6,26 +6,6 @@ ] }-provider "registry.terraform.io/hashicorp/azurerm" {- version = "2.30.0"- constraints = "~> 2.12"- hashes = [- "h1:FJwsuowaG5CIdZ0WQyFZH9r6kIJeRKts9+GcRsTz1+Y=",- "h1:c/ntSXrDYM1mUir2KufijYebPcwKqS9CRGd3duDSGfY=",- "h1:yre4Ph76g9H84MbuhZ2z5MuldjSA4FsrX6538O7PCcY=",- "zh:04f0a50bb2ba92f3bea6f0a9e549ace5a4c13ef0cbb6975494cac0ef7d4acb43",- "zh:2082e12548ebcdd6fd73580e83f626ed4ed13f8cdfd51205d8696ffe54f30734",- "zh:246bcc449e9a92679fb30f3c0a77f05513886565e2dcc66b16c4486f51533064",- "zh:24de3930625ac9014594d79bfa42d600eca65e9022b9668b54bfd0d924e21d14",- "zh:2a22893a576ff6f268d9bf81cf4a56406f7ba79f77826f6df51ee787f6d2840a",- "zh:2b27485e19c2aaa9f15f29c4cff46154a9720647610171e30fc6c18ddc42ec28",- "zh:435f24ce1fb2b63f7f02aa3c84ac29c5757cd29ec4d297ed0618423387fe7bd4",- "zh:7d99725923de5240ff8b34b5510569aa4ebdc0bdb27b7bac2aa911a8037a3893",- "zh:7e3b5d0af3b7411dd9dc65ec9ab6caee8c191aee0fa7f20fc4f51716e67f50c0",- "zh:da0af4552bef5a29b88f6a0718253f3bf71ce471c959816eb7602b0dadb469ca",- ]-}- provider "registry.terraform.io/newrelic/newrelic" { version = "2.1.2" constraints = "~> 2.1.1"
If you add a new requirement for the same provider at a later date and runterraform init
again, Terraform will treat it as if it werean entirely new providerand so will not necessarily select the same version that was previouslyselected and will not be able to verify that the checksums remained unchanged.
Note: In Terraform v1.0 and earlier, terraform init
does notautomatically remove now-unneeded providers from the lock file, and insteadjust ignores them. If you removed a provider dependency while using anearlier version of Terraform and then upgraded to Terraform v1.1 or laterthen you may see the error "missing or corrupted provider plugins", referring tothe stale lock file entries. If so, run terraform init
with the new Terraformversion to tidy those unneeded entries and then retry the previous operation.