Terraform Registry Guide: Tips, Examples and Best Practices
Tags: terraform, devops, cloudcomputing, infrastructureascode
Published: 2024-05-13 13:00:00

The Terraform registry is an essential asset for every Terraform user. In this blog, I’ll provide a practical guide for how it can be best used and explore ways you can leverage it to streamline and standardize cloud infrastructure provisioning.

**What is Terraform Registry?**
-------------------------------

The Terraform registry is an official repository for [Terraform modules](https://www.env0.com/blog/terraform-modules) and [providers](https://www.env0.com/blog/how-to-use-terraform-providers) hosted by HashiCorp. 

The registry serves as a central hub for individuals and organizations looking to publish, discover, and use Terraform modules and providers to automate the setup and management of cloud infrastructure. 

Modules in the Terraform registry function similarly to libraries in a programming language, allowing reuse instead of requiring you to build your own from scratch. 

Providers are basically plugins for Terraform to communicate with cloud providers like AWS, Azure, Google Cloud, etc., to provision or manage your infrastructure.

The benefits of using the Terraform registry include:

1.  **Efficiency:** You can utilize the registry to save time by using pre-existing modules instead of starting from scratch.
For example, you can import a pre-built Terraform [EKS module](https://registry.terraform.io/modules/terraform-aws-modules/eks/aws/latest) from the registry, saving the time and effort of writing the EKS config.

2.  **Simplicity:** Using the registry abstracts complex resource details simplifies your configuration.
For instance, deploying a VPC manually requires configuring numerous components, including subnets, gateways, etc. However, utilizing a [VPC module](https://registry.terraform.io/modules/terraform-aws-modules/vpc/aws/latest) smooths the experience by abstracting the intricate configurations.

3.  **Peace of mind:** The Terraform registry classifies modules and providers with badges (official, partner, community) to denote their source and level of verification. Moreover, the registry holds information about downloads, as an indication of usage and trustworthiness. 

  
Having this information available will help you identify popular, verified, and community-vetted assets and help improve your IaC quality, reliability, and security. 

**Terraform Public vs. TFC Private Registry**
---------------------------------------------

The official Terraform registry is public, and should not be confused with the private self-hosted registry offered by TFC, [env0](https://docs.env0.com/docs/modules), and other IaC management platforms, or OSS modules like [Citizen](https://github.com/outsideris/citizen), [Terrareg](https://github.com/matthewjohn/terrareg), etc.

The use cases for using a private registry include:

*   **Customization:** Organizations can create and manage modules that are tailored to their internal use, specific infrastructure requirements and policies, etc.
*   **Security:** Security and compliance requirements can necessitate some organizations to self-host their registry or/and some of its modules.
*   **Centralized Governance:** A private registry can be used for management and [versioning](https://www.env0.com/blog/tutorial-how-to-manage-terraform-versioning) of modules specific to the organization, to support internal guidelines and processes.  
    

**Example: Using Terraform AWS S3 Module**
------------------------------------------

To show how the Terraform registry works (and how you should be working with it), here is a hands-on example of how we can provision an S3 bucket with Server Side Encryption (SSE) and versioning - all enabled through the use of an S3 module in the Terraform Registry.

Generally speaking, there are four steps you should take to use providers and modules from the registry to spin up an infrastructure:

### **1\. Search and Discover**

Since we want to import Terraform S3 code, our initial step would be to find an AWS S3 module with the necessary parameters (SSE and versioning). First, click on **Browse Modules** to find a range of different modules in the registry.

![](https://assets-global.website-files.com/63eb9bf7fa9e2724829607c1/65d73c9ce6726d1caa9ef642_MP81PRDsutvgAEux6YNKa5RsTx_4mJmjD1xzl5Y-9EmAJ_YkYaobql0spGQPOHNNlvqQoCXk4Yw2wA39ofo6JMN0R6aAtrMrxSoOnjn7nBVW7IpUeNwfPWBF__XTmVjmtr703-k45IU5jvF7zlZjq-0.png)

  
In our case, we filter the results to the AWS provider, since we want to provision an AWS S3 bucket.

![](https://assets-global.website-files.com/63eb9bf7fa9e2724829607c1/65d73c9cc06242d5eb7a764b_xOaTeGP189-uc1yP8qlxGX4k5qe4zQsBa0nqx7Wncw-4f7xaqBvUWnl4KZRHLJHnitNMQrevfXLJ4htvL2EdOzGexUc-hnSfeFod1jdiu7Il6l0WdYkJuRV975xvtMmorwlXL9M-KIgZw-pnPyqYF6s.png)

### **2\. Review and Select**

Once we have found a module that meets our requirements, it is important to review its documentation, usage examples, and version information. 

In our case, we can see that the module is published by **terraform-aws-modules**, which is supported by the HashiCorp community. To further examine our parameters, we need to check the **Inputs** section.

![](https://assets-global.website-files.com/63eb9bf7fa9e2724829607c1/65d73c9c99dbe8b446402d5c_gzOA1xRJsKdv0qi5MQT3xhJNbDa4FXuuY3LsCkoLcG0QmUM6QPkEYn0q74kmwVQIX_E-774XTiHW7OShq2rs2DWG3bejI35KR8tfmad6NKNbaDQVf25_XDbCIhU0J-_ab2jjxdOKdG8GVIyVmXjyMCg.jpeg)

Scroll down to check whether the module allows us to define the **SSE** and **versioning** input variables so that we can add these parameters to our S3 module block configuration. We see that it allows us to define these parameters.

![](https://assets-global.website-files.com/63eb9bf7fa9e2724829607c1/65d73c9c30ce491e36c9b71c_SsTfcXQK4GOtrT5hZ194-BlBqMElZCN8aBPbvo8FbRCGQ_DBkL7Jxo67xEbgIfmrYulC8vCiiItWB5WFZSoQ6O6Rkfa07pa-DaaXzlqU3pMmrBahHjuGYRUzlH8X8LwVtdX8qhO3Oc8dPJrRot87lsY.png)

### **3\. Import Module into Terraform Code**

Use the module in your Terraform configuration by referencing it in your **.tf** files. Specify the source of the module (its URL in the Terraform Registry). The basic syntax looks like this:

    module "module_name" {
      source  = "namespace/module/provider"
      version = "version"
      # Additional required variables
    }
    

In our case, we have defined the S3 bucket module in our **main.tf** file.

    module "s3-bucket" {
      source  = "terraform-aws-modules/s3-bucket/aws"
      version = "4.1.0"
      bucket = "env0"
      versioning = {
        enabled = true
      }
      server_side_encryption_configuration = {
        rule = {
          apply_server_side_encryption_by_default = {
            sse_algorithm = "AES256"
          }
        }
      }
    }
    

### **4\. Run Terraform workflow**

Run [`terraform init`](https://www.env0.com/blog/terraform-init) to initialize the Terraform project, which will download and install the specified S3 module and AWS provider it depends on. 

![](https://assets-global.website-files.com/63eb9bf7fa9e2724829607c1/65d73dc2744f77c4189a72f8_7dN7SiisoAhXWrZOQdPkI7WwHqHQzbrUN8j8gBb1PUglyiHE26rDdeF6vmhx5eoi_9APfHAq6oQ00-0h4BhHg4yn5P_-IrKEBmtZ6DeSebpOeUEVCJpyd-v4B3V1h1YvJCL3_yhMy0tAV_4_Qfe3qZU.png)

Run the [`terraform plan`](https://www.env0.com/blog/terraform-plan) command to review the changes Terraform will make to your infrastructure based on the S3 module we included. 

![](https://assets-global.website-files.com/63eb9bf7fa9e2724829607c1/65d73dc2b4a7982070385175_Auy9oa1zNkZtH8eaM0zj_-r0i1UAb5WrZH7uIlrbSyE8KCPZT74uiLWB4a8RQrlKKZULYzNTHY6S-F_1PsYRzK_xvFMXbHW6EOaSplaeqAvxVXQzoH3j_syE0aTBmJD6zkyHv8iCJwF-R7la7XxrSK4.png)

Then, use [`terraform apply`](https://www.env0.com/blog/terraform-apply-guide-command-options-and-examples) to spin up the S3 bucket, confirming the changes with a **yes**. 

![](https://assets-global.website-files.com/63eb9bf7fa9e2724829607c1/65d73dc284c44d9803e0ae00__MlL73C1vTkqPNhHWwMt7hn2JrDr5EEgnfLUt7vmac5hqFbmy_FlwNzrpSOYjlH4gjcxCG5jxR49vIR8IeEpBE7zD9Yx3OY6L16RmNF_7irdsYJ9TP0BPBxGQ7XFzY-xWBB7MTUlHnfNmegkHlYvOhc.png)

After running [`terraform apply`](https://www.env0.com/blog/terraform-apply-guide-command-options-and-examples), we have successfully provisioned our S3 bucket (**env0**).

![](https://assets-global.website-files.com/63eb9bf7fa9e2724829607c1/65d73dc3aaa57bc9d9e8898e_6Y1wINlIaV7qU9PJ0TRtwr58T51MYHuO9_NkvpR58wbwH_V1DgvORHXqIuTrb2F5NsX-J1zfzQYhwdxjZC-OhdBWVVZ2-WKm8AGYn95vOG1TuJi8PzFlOyp4v-EPJ5wsQllbkTubGTmlFNUzvCKCXUY.png)

> **Note: Understanding Verified Modules**
> By default, only verified modules are shown in search results.  
> HashiCorp reviews the modules, ensuring they meet their standards for quality and reliability.  
>   
> Three major benefits of verified modules:
> **- Reviewed by HashiCorp:** Closely examined by HashiCorp to ensure they follow best practices in code quality, documentation, and module design. The verified badge appears next to modules that are published by a verified source, like HashiCorp.
> **- Actively Maintained:** Contributors typically actively maintain verified modules, ensuring that they stay up to date with the latest Terraform versions and features.
> **- Trust and Reliability:** Choosing a verified module means you're using a trusted component that is more likely to be reliable and secure for your infrastructure.

**Example: Publishing Modules to the Terraform Public Registry**
----------------------------------------------------------------

The next example I want to share will focus on adding your own module to the public registry.  
To do that, imagine you've written Terraform code for an S3 bucket and you want to transform this code into a module, to enhance its reusability inside and outside your organization.  

First and foremost, create a repository in your public Github account with an appropriate naming convention. The naming convention for repositories should be `terraform-<provider-name>-<module-name>`. 

Therefore, with respect to the naming convention, the given name of the module is kept as `terraform-aws-s3-sse-versioning`.

![](https://assets-global.website-files.com/63eb9bf7fa9e2724829607c1/65d73dc2dd38dac29b4faa1d_s9ME3pWLWjRFlvliVCSvCmDdAvLwRMACk34ZuFkzS5SOgTejo8KE2D_aDUuZwdgdsmWg3xfJ3acmxNAkgXT73FHdrC-khJLa96ciDIp057zAsMvOoZ9xRj0OGc0EJq8B_fztebW0KIkE5OHccMMRrxA.png)

After pushing the source code, the next important step is to tag our repository. To do that, head on to the **Releases** section and create a tag. We have created the tag **1.0.0**. Select **Publish Release** after creating the tag.

![](https://assets-global.website-files.com/63eb9bf7fa9e2724829607c1/65d73dc222f32c56f2d2ee85_Dfc7jHPJ8tagcihnqF86rSq57wb8WDDDbK8nMYcicC18SES5n7LnrLZhlV_YYjRcacLuumOkf17DUaR2SRh-hxtxGadaMOi9Q-5Fo_OPtMVFCWE-LomeFolX6lixCMNuBE8nWZ3vQH_U6p35p6L9yhA.png)

![](https://assets-global.website-files.com/63eb9bf7fa9e2724829607c1/65d73dc2ab093718f136d82f_K5H6a6E-01GzaXwuyWFcghqo4VlpQhO76SRB9cD_5YZPhVpAG5H6I8uZRZApi64E82iKbf2SS_H6kSYHq_LlhA4tBUdbwW5RwICh9kYjVYkbAlI1YMESxx_lvxzVIi_PhMF7pxu4EsuzEaNnfeANe-w.png)

To begin publishing your modules, navigate to the Terraform Registry and click on **Publish Modules** under the **Publish** dropdown. You will then be prompted to Sign In with GitHub. This step allows the Terraform registry to access and identify the repository where your module source code is located.

![](https://assets-global.website-files.com/63eb9bf7fa9e2724829607c1/65d73dc2918b1b8f5084c4f3_vSFaivRpjt7PZFU-JXnI_sbdZI-idqq5Lhkolsy1OPALT9nhri2IM7KtmgEwdwplTmYMYAFL1vBfAtOOrgrSNxTcrfYs3jSrqJXv9P4XulkxKPUDKFpeT4pDDbSEgPodqOVUFwM1OmVBLe4fm08vCVw.png)

After authorizing your own registry with Github, (selecting **Publish dropdown > Module**), you’ll be prompted to select the repository for hosting the module. Choose the repo and select **Publish Module.**

![](https://assets-global.website-files.com/63eb9bf7fa9e2724829607c1/65d73dc39f4a49620cd1a6c8_4b2_3tvS62AfnOilIczxkyNCjOnvCHZjnEAhw4yv3KXhdq_6btP0_lrJnbKCqHld39KIN3qihj8IB3cnRqulSFWUHQTGJS3NTJEZDYsF1gA02zlJocgzNfMtkycTcMFzkTE0Z4lpT3d0Vbu2lB4m8lQ.png)

Bingo! Within a few minutes, we can see that our module has been successfully published, which means you can pick up your existing terraform code and package it into a module.

![](https://assets-global.website-files.com/63eb9bf7fa9e2724829607c1/65d73dc22a1c3d88065caef3_eY0m5YqZcg_fU7I9HZGb_axIi1gJdIBZEerX6LuuwycmZmiKwfYn2AORYhNJpc-4szCU1ItrsjPY62mZyO78hTmei9rVuNq_6RNFtBRObQWaIyvQWLsY8We8bjkwTF_p7qBiTRXtRVUkFWlo1I7Lr3E.png)

**env0 Private Registry**
-------------------------

env0 offers two types of registries for your organization: Provider Registry and Module Registry.

### **Provider Registry**

env0 Provider Registry is a feature that allows you to privately share and reuse Terraform providers within your organization. 

You can easily switch between different versions of the code with minimal changes. Moreover, within env0, authentication is seamlessly managed for you, requiring no extra steps or configurations.

It also enforces the use of RBAC policies to control access to the Provider Registry. For instance, users with **“View Providers”** have the privilege to only view the providers. As an administrator, you always have “**Create and Edit”** access.

Check out the [Provider registry](https://docs.env0.com/docs/providers) for more detailed information.

### **Module Registry**

The env0 Module Registry is a private registry for Terraform modules, allowing you to privately share and reuse Terraform modules within your organization.

Creating and using a module with the env0 module registry is seamless.

1.  In your env0 account, go to `Registry > Modules section > Create a Module`.
2.  Give a suitable name for your module and the provider name.

![](https://assets-global.website-files.com/63eb9bf7fa9e2724829607c1/65d73dc2473c9f3f1976d452_Nn4ek24tWasFgCNyvbdXQOkRIbRn5cidbTONWlmivTB-u23-n8QOclS6g9SV8pydHoSa1kOaaMtLAcABBXQnTFmoZiPBESjzDeQqf64onKAKuXAMieVG_LhtKJna4gwYpd2qwLWZZA0ISQpavSxbuSM.png)

3.  I’m leaving the tag prefix (env0 auto-detected repo tag, in our case) and module folder (as the module resides in the root folder) empty.

![](https://assets-global.website-files.com/63eb9bf7fa9e2724829607c1/65d73dc2e442a81b1a317961_sXhGccdyUeaC1RwsKZe_1eFH7P0KVKz6l1Qk7ghLbCOuwlURjLmeGvXwldADqtHxl4JE-WOQm4V073f41AWCG6QQNgBKOcZ95xOs7D2VAjUjcN-yTAB6Ms-HDg15boPTUIr0RPrw59bDu6aId0OFarc.png)

4.  The private module has now been created, and the team in your organization can import the module using the appropriate [format](https://docs.env0.com/docs/modules#using-a-module-in-your-code).

![](https://assets-global.website-files.com/63eb9bf7fa9e2724829607c1/65d73dc2b6e8f89ea0b92936_iR6V1kXZxtGUTFFikVjAfS5bQbLzCtFvKhel9PiFk5a0vj3v15SzlSGx9reDlNfPh398YHj6iMmrLeT2fdiIOTdvW7-05JhjF0WQgtPIDYHLHAcPK71WU2LMpRibYKWACt6QFwePtl-2QNfxjyhuxX8.png)

env0 has also rolled out its new [CI Testing](https://www.env0.com/blog/celebrating-opentofu-ga-with-our-new-ci-testing-feature) feature. This feature was specifically designed by env0 to incorporate the OpenTofu testing capabilities into their platform.

The OpenTofu testing feature ([`tofu test`](https://opentofu.org/docs/cli/commands/test/)), validates your OpenTofu configuration (including modules) by creating real infrastructure and checking if the conditions (or assertions) for that provisioned infrastructure are met.

Tests suite is defined in **\*.tftest.hcl** files and the **run** blocks should be where the test conditions are defined.

Each test run validates the following:

*   All assertions pass
*   None of the checks are failing
*   The _tofu plan/apply_ has finished successfully

For more information on how this feature works, check out the `tofu test` command.

Coming back to CI testing, this feature effortlessly integrates OpenTofu testing capabilities into your private module registry, acting as a health monitor for your modules and initiating tests with every change. Information is conveniently available in env0 and your VCS for a clear overview of your module status. This facilitates the mitigation of issues early on, improving user experience.

**Frequently Asked Questions/FAQs**
-----------------------------------

#### **Q. Is the Terraform registry free?**

Yes, Terraform's public registry is freely accessible to the general public, offering a wide range of providers and modules. 

#### **Q. Is the Terraform registry open-sourced?**‍

No. Terraform Registry is the property of HashiCorp. In 2023, following the [license change of HashiCorp’s product](https://www.env0.com/blog/hashicorp-lisence-change-community-response-to-opentf), the company also updated the registry’s terms of service (TOS) for the Terraform Registry to limit its community usage, stating that: “_You may download or copy the Content (and other items displayed on the Services for download) for personal non-commercial use only, provided that you maintain all copyright and other notices contained in such content.”_**‍**

#### **Q.**  **What registry is used by OpenTofu?** 

OpenTofu, Linux-foundation’s backed open-source Terraform alternative,  maintains its [own registry,](https://github.com/opentofu/registry/) offering access to a comprehensive set of providers and modules, including _all_ the providers and modules currently available in the Terraform registry. 

#### **Q. How do I publish a module to a private registry?**

As discussed in this blog, publishing a module to a private registry is similar to publishing a module to the public registry. The process involves writing your own module, pushing it to your VCS (Version Control System) with semantic version tags, and then integrating your VCS with the private registry (e.g., Terraform Cloud, env0, etc.) to select and publish the module.

#### **Q. Can I use multiple providers in Terraform, and where are providers stored?**

Yes, you can use multiple providers in Terraform for provisioning infrastructure in different cloud environments. After you define the provider within the _terraform_ block and run _terraform init,_ Terraform downloads the respective provider plugin and stores it in the **.terraform/providers** folder in your local environment.

#### **Q. What is the difference between Terraform providers and modules?**

Providers in Terraform are plugins that interface with the API of a service provider (such as AWS, Google Cloud Platform, Azure, etc.) to manage resources. For example, the AWS provider can manage resources like virtual machines, databases, networks, etc., on AWS.  
  
Modules, on the other hand,  can be used to create reusable templates for common infrastructure setups, like setting up a VPC network architecture on AWS.