SMS Blog

SMS Engineering is Keeping a Close Eye on OpenTofu

SMS has more than 50 person-years of experience leveraging infrastructure as code (IaC) technologies to address the complex requirements of our public and private sector customers working in cloud environments, including Amazon Web Services and Microsoft Azure, as well as in on-premises environments utilizing technologies like VMWare VCenter. IaC is an essential tool for SMS and our clients as it enables the automation of infrastructure provisioning and management, leading to greater consistency, efficiency, and fewer errors. In May of 2022, SMS further cemented its commitment to supporting customers seeking to leverage IaC by partnering with Gruntwork to enable their clients to adopt the Gruntwork IaC Reference Architecture and IaC Library. A foundational technology underpinning the IaC efforts at SMS is HashiCorp Terraform, which is why SMS is closely watching the recent emergence of OpenTofu as an alternative to Terraform.

A Brief History of Terraform

In 2014, HashiCorp’s Terraform became a pioneer in the Infrastructure as Code (IaC) space. Its popularity stemmed from two key capabilities:

  1. Open-source license: This allowed for transparent management and encouraged community contributions.
  2. Human-readable HCL syntax: HCL (HashiCorp Configuration Language) made it easy for users to define infrastructure configurations as code. This approach proved valuable not only for managing infrastructure across various cloud providers but also for other technologies where configuration management is crucial. Examples include networking and application deployments. Terraform’s ability to define infrastructure as code that could then be tracked in version control systems like GitHub further boosted its adoption. As a result, Terraform became the go-to solution for many organizations.

However, in August 2023, HashiCorp switched Terraform’s license to the Business Source License (BSL). This change caused concern within the community. The BSL’s ambiguity regarding commercial use sparked worries about potential licensing costs and a shift towards a more closed-source future for Terraform. Adding to concerns regarding Terraform’s future, IBM announced plans to acquire Hashicorp in April 2024. It remains to be seen how this acquisition will play out and what impact it may have on Terraform’s future.

OpenTofu: A Community-Driven Alternative

In response to the Terraform licensing change, a group of companies and developers spearheaded the creation of OpenTofu. Launched in September 2023, OpenTofu is a fork of Terraform version 1.5.6. It maintains Terraform’s core functionalities and HCL syntax while remaining genuinely open-source under the Mozilla Public License (MPL).

Why Consider OpenTofu?

So, why would an organization choose OpenTofu over Terraform? Here are some compelling reasons:

  • Open-source commitment: The MPL license offers greater transparency and freedom for commercial use. Organizations can contribute to the project’s development and shape its future.
  • Community-driven development: OpenTofu benefits from a dedicated community that is actively working on improvements and bug fixes. This collaboration fosters faster innovation and a more responsive development cycle.
  • Backward compatibility: OpenTofu is designed to be a drop-in replacement for Terraform. Migrating existing Terraform configurations to OpenTofu is relatively straightforward.
  • Linux Foundation backing: OpenTofu is an official project of the Linux Foundation, a trusted non-profit organization with a proven track record of fostering open-source collaboration on critical infrastructure projects. This association lends credibility to OpenTofu’s long-term sustainability and governance.

Given these advantages, it is not surprising that many organizations are currently evaluating OpenTofu. Understanding the basic migration process will be helpful as a first step in this evaluation.

Migrating from Terraform to OpenTofu: A Sample Project

Let’s demonstrate the migration process using a simple example.

Creating an AWS S3 Bucket Using Terraform

We will start by creating an S3 bucket in AWS using Terraform:

1. Install Terraform: https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli

2. Create a new TF file (s3_bucket.tf):

// Generate a random string so that the name of the s3 bucket is unique 
resource "random_string" "random" {
  length  = 6
  special = false
  lower   = true
  upper   = false
}

// Create a new s3 bucket
resource "aws_s3_bucket" "my_bucket" {
  bucket = "test-bucket-${random_string.random.result}"

  tags = {
    Name        = "TF test Bucket"
    Deployed_by = "Terraform"
  }
}

💡 Note: To proceed with the following steps, you will need to install the AWS CLI on your system and configure it with the credentials for your AWS account.

3. Run terraform init

4. Run terraform plan. You should see the following output:

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_s3_bucket.my_bucket will be created
  + resource "aws_s3_bucket" "my_bucket" {
      + acceleration_status         = (known after apply)
      + acl                         = (known after apply)
      + arn                         = (known after apply)
      + bucket                      = (known after apply)
      + bucket_domain_name          = (known after apply)
      + bucket_prefix               = (known after apply)
      + bucket_regional_domain_name = (known after apply)
      + force_destroy               = false
      + hosted_zone_id              = (known after apply)
      + id                          = (known after apply)
      + object_lock_enabled         = (known after apply)
      + policy                      = (known after apply)
      + region                      = (known after apply)
      + request_payer               = (known after apply)
      + tags                        = {
          + "Deployed_by" = "Terraform"
          + "Name"        = "TF test Bucket"
        }
      + tags_all                    = {
          + "Deployed_by" = "Terraform"
          + "Name"        = "TF test Bucket"
        }
      + website_domain              = (known after apply)
      + website_endpoint            = (known after apply)
    }

  # random_string.random will be created
  + resource "random_string" "random" {
      + id          = (known after apply)
      + length      = 6
      + lower       = true
      + min_lower   = 0
      + min_numeric = 0
      + min_special = 0
      + min_upper   = 0
      + number      = true
      + numeric     = true
      + result      = (known after apply)
      + special     = false
      + upper       = false
    }

Plan: 2 to add, 0 to change, 0 to destroy.

─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform
apply" now.

The plan Terraform generates should match what is shown above. After you have reviewed the plan, proceed to the next step.

5. Run terraform apply after generating the same plan; Terraform will show you the following prompt:

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: 

Enter yes at the prompt to create the new s3 bucket. After the apply process finishes, feel free to log in to the AWS console to confirm that the s3 bucket was created.

Update a Tag on the s3 Bucket Using OpenTofu

Now, switch to OpenTofu and update the deployment by following these steps:

1. Install OpenTofu: follow the directions for your operating system at https://opentofu.org/

2. Run tofu init

3. Run tofu plan. You should see a message that indicates that no changes to the infrastructure are required. This is what we would expect because the infrastructure in AWS matches what we defined in the s3_bucket.tf file.

4. Next, update the TF file (s3_bucket.tf) as shown here:

// Generate a random string so that the name of the s3 bucket is unique 
resource "random_string" "random" {
  length  = 6
  special = false
  lower   = true
  upper   = false
}

// Create a new s3 bucket
resource "aws_s3_bucket" "my_bucket" {
  bucket = "test-bucket-${random_string.random.result}"

  tags = {
    Name        = "TF test Bucket"
    Deployed_by = "OpenTofu"  //CHANGE THIS LINE
  }
}

The only change you are making is to update the tag value for Deployed_by . Change the value to OpenTofu. No other changes are required. Don’t forget to save your changes after you update the file.

5. Run tofu plan. In the output, note that OpenTofu has detected the change made in the TF file and shows that it will apply that change to the s3 bucket tag in AWS if you run the apply command. Your output should be similar to the following, except the name of your bucket will be different.

random_string.random: Refreshing state... [id=5y7erg]
aws_s3_bucket.my_bucket: Refreshing state... [id=test-bucket-5y7erg]

OpenTofu used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  ~ update in-place

OpenTofu will perform the following actions:

  # aws_s3_bucket.my_bucket will be updated in-place
  ~ resource "aws_s3_bucket" "my_bucket" {
        id                          = "test-bucket-5y7erg"
      ~ tags                        = {
          ~ "Deployed_by" = "Terraform" -> "OpenTofu"
            "Name"        = "TF test Bucket"
        }
      ~ tags_all                    = {
          ~ "Deployed_by" = "Terraform" -> "OpenTofu"
            # (1 unchanged element hidden)
        }
        # (9 unchanged attributes hidden)

        # (3 unchanged blocks hidden)
    }

Plan: 0 to add, 1 to change, 0 to destroy.

─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Note: You didn't use the -out option to save this plan, so OpenTofu can't guarantee to take exactly these actions if you run "tofu apply"
now.

The plan OpenTofu generates should be similar to what is shown above. After you have reviewed the output, proceed to the next step.

6. Run tofu apply after generating the same plan; OpenTofu will show you the following prompt:

Plan: 0 to add, 1 to change, 0 to destroy.

Do you want to perform these actions?
  OpenTofu will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: 

Enter yes at the prompt to update the tag value on the s3 bucket. After the apply process finishes, feel free to log in to the AWS Console to confirm that the apply command updated the tag on the s3 bucket.

7. Run tofu destroy and confirm the change to remove the bucket from AWS by typing yes at the prompt.

For this example, the code is identical between Terraform and OpenTofu. The migration process is straightforward for a simple project. However, SMS recommends caution and careful testing before broader-scale adoption of OpenTofu, as any issues encountered during a deployment could potentially impact production infrastructure.

💡 We encourage you to review the additional guidance on migrating to OpenTofu provided on the OpenTofu website.

Conclusion

The rise of OpenTofu reflects the importance of open-source principles in the IaC space. While Terraform remains a powerful tool, OpenTofu offers a compelling alternative with its community-driven approach, a solid commitment to open source, and backing by the Linux Foundation. Staying informed about OpenTofu’s development is crucial for making informed decisions about infrastructure management strategies in the future. SMS Engineering will continue closely monitoring developments in OpenTofu and related IaC technologies.


Leave a Comment