skip to Main Content

As far as I can see there are three ways to make Terraform use prepopulated plugins (to prevent downloads from web on init command).

  1. terraform provider mirror command + provider_installation in .terraformrc (or terraform.rc)
  2. terraform init -plugin-dir command
  3. warming up provider-plugin-cache

Are they all equivalent? Which one is recommended? My use case is building "deployer" docker image for CI/CD pipeline and also I am considering the possibility to use Terraform under Terraspace.

2

Answers


  1. Not sure about Terraspace. Only regarding plugins:

    1. terraform provider mirror command + provider_installation in .terraformrc (or terraform.rc): seems more secure version, but it requires to update the local mirror whenever you change plugin versions. It’s not very clear whether you can reuse the same mirror location for different configurations requiring different set or versions of plugins.

    2. terraform init -plugin-dir command: terraform commands will fail if required plugins and specific versions are not preinstalled. This approach seems to be the most time consuming and the most controlling of available plugins.

    When this option is used, only the plugins in the given directory are available for use.

    1. warming up provider-plugin-cache: this one can re-use pre-downloaded plugin versions and also will try to download new versions when you update the constraints. This approach will work if your cache path is writable. If it is not then terraform probably will fail as 2nd option. This option seems to be the least time consuming and more close to the local development. Cache is not automatically cleaned up and will need some cleaning automation.

    Depending on whether you have many different configurations, what level of security is required, whether you have capacity to update caches/mirrors frequently enough to follow with required versions, the choice could be different as well.

    Login or Signup to reply.
  2. The first two of these are connected in that they all share the same underlying mechanism: the "filesystem mirror" plugin installation method.

    Using terraform init -plugin-dir makes Terraform in effect construct a one-off provider_installation block which contains only a single filesystem_mirror block referring to the given directory. It allows you to get that effect for just one installation operation, rather than configuring it in a central place for all future commands.

    Specifically, if you run terraform init -plugin-dir=/example then that’s functionally equivalent to the following CLI configuration:

    provider_installation {
      filesystem_mirror {
        path = "/example"
      }
    }
    

    The plugin cache directory is different because Terraform will still access the configured installation methods (by default, the origin registry for each provider) but will skip downloading the plugin package file (the file actually containing the plugin code, as opposed to the metadata about the release) if it’s already in the cache. Similarly, it’ll save any new plugin package it downloads into the cache for future use.

    This therefore won’t stop Terraform from trying to install any new plugins it encounters via network access to the origin registry. It is just an optimization to avoid re-downloading the same package repeatedly.


    There is a final approach which is similar to the first one but with a slight difference: Implied Local Mirror Directories.

    If you don’t have a provider_installation block in your configuration then Terraform will construct one for itself by searching the implied mirror directories and treating any provider it finds there as a local-only one. For example, if /usr/share/terraform/plugins contains any version of registry.terraform.io/hashicorp/aws (the official AWS provider) then Terraform will behave as if it were configured as follows:

    provider_installation {
      filesystem_mirror {
        path    = "/usr/share/terraform/plugins"
        include = ["registry.terraform.io/hashicorp/aws"]
      }
      direct {
        exclude = ["registry.terraform.io/hashicorp/aws"]
      }
    }
    
    

    This therefore makes Terraform treat the local directory as the only possible installation source for that particular provider, but still allows Terraform to fetch any other providers from upstream if requested.


    If your requirement is for terraform init to not consult any remote services at all for the purposes of plugin installation, the approach directly intended for that case is to write a provider_installation block with only a filesystem_mirror block inside of it, which will therefore disable the direct {} installation method and thus prevent Terraform from trying to access the origin registry for any provider.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search