<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: kvendingoldo</title>
    <description>The latest articles on Forem by kvendingoldo (@kvendingoldo).</description>
    <link>https://forem.com/kvendingoldo</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1249689%2F43b908e1-83fd-4575-9f25-0f435abdb044.jpeg</url>
      <title>Forem: kvendingoldo</title>
      <link>https://forem.com/kvendingoldo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/kvendingoldo"/>
    <language>en</language>
    <item>
      <title>How to create AWS Serverless Valkey via OpenTofu</title>
      <dc:creator>kvendingoldo</dc:creator>
      <pubDate>Fri, 01 Aug 2025 11:01:50 +0000</pubDate>
      <link>https://forem.com/aws-builders/how-to-create-aws-serverless-valkey-via-opentofu-40n5</link>
      <guid>https://forem.com/aws-builders/how-to-create-aws-serverless-valkey-via-opentofu-40n5</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;AWS introduced Amazon ElastiCache Serverless in November 2023. However, many developers still rely on the older hosted Redis clusters - which can be a real pain in the back to manage and scale.&lt;/p&gt;

&lt;p&gt;In this tutorial, we will set up ElastiCache Serverless with the Valkey engine by using OpenTofu.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Open Source stack focus&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This guide is based entirely on an open source stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Valkey instead of Redis&lt;/strong&gt;. Redis is still technically open source, but due to the license change (SSPL), it is no longer a safe or sustainable option for many applications. Valkey is the community-driven alternative that remains completely open.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OpenTofu instead of Terraform&lt;/strong&gt; for the same reason: Terraform is no longer entirely open source due to the transition to the BSL license.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Despite that, you can still use Redis and Terraform if they suit your needs in scope of this guide.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Prerequisites&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Before you begin, make sure you have the following set up:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;AWS Account&lt;/strong&gt; with the sufficient IAM permissions to create ElastiCache resources. If you don't already have it, you can &lt;a href="https://aws.amazon.com/free" rel="noopener noreferrer"&gt;sign up&lt;/a&gt; for an AWS Free Tier account.
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;AWS CLI installed and configured&lt;/strong&gt; with valid credentials. You can follow &lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/getting-started-quickstart.html" rel="noopener noreferrer"&gt;the official AWS CLI setup guide&lt;/a&gt; if needed.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A working directory for your code.&lt;/strong&gt; In this guide, I’ll use directory &lt;code&gt;elasticache_guide&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Install OpenTofu to your machine&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Since we’ll be working with &lt;strong&gt;OpenTofu&lt;/strong&gt;, the first step is installing it.&lt;/p&gt;

&lt;p&gt;Instead of installing OpenTofu directly, we’ll use &lt;a href="https://github.com/tofuutils/tenv" rel="noopener noreferrer"&gt;&lt;code&gt;tofuutils/tenv&lt;/code&gt;&lt;/a&gt; — a powerful version manager for OpenTofu, Terraform, Terragrunt, Terramate, and Atmos, written in Go.&lt;/p&gt;

&lt;p&gt;We're starting with tenv because OpenTofu evolves rapidly, and having a version manager makes it much easier to switch between versions and stay up to date.&lt;/p&gt;

&lt;p&gt;To install &lt;code&gt;tenv&lt;/code&gt; follow the instructions in the &lt;a href="https://github.com/tofuutils/tenv" rel="noopener noreferrer"&gt;tenv GitHub README&lt;/a&gt; for your operating system. Once &lt;code&gt;tenv&lt;/code&gt; is set up, you can install a specific version of OpenTofu by running: &lt;br&gt;
&lt;code&gt;$ tenv tofu install 1.10.3&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;That’s it — you now have OpenTofu ready to use!&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Create AWS Elasticache OpenTofu module&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In this guide, we’ll adhere to Terraform and OpenTofu best practices by creating a dedicated OpenTofu module to provision ElastiCache Serverless.&lt;/p&gt;

&lt;p&gt;If you're new to the Terraform modules or want a refresher on best practices, check out &lt;a href="https://devopscube.com/terraform-module-best-practices/" rel="noopener noreferrer"&gt;Terraform Module Best Practices by DevOpsCube&lt;/a&gt; article.&lt;/p&gt;

&lt;p&gt;Let’s walk through the process step by step.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 1
&lt;/h3&gt;

&lt;p&gt;Create a new directory for the module inside your working folder:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ mkdir -p elasticache_guide/modules/elasticache_serverless&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 2
&lt;/h3&gt;

&lt;p&gt;Inside the &lt;code&gt;elasticache_guide/modules/elasticache_serverless&lt;/code&gt; directory, create a file named &lt;a href="http://main.tf" rel="noopener noreferrer"&gt;&lt;code&gt;main.tf&lt;/code&gt;&lt;/a&gt;. This file provides a basic specification of the ElastiCache cluster.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_elasticache_serverless_cache"&lt;/span&gt; &lt;span class="s2"&gt;"this"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt; &lt;span class="err"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

 &lt;span class="nx"&gt;engine&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;engine&lt;/span&gt;
 &lt;span class="nx"&gt;name&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cache_name&lt;/span&gt;

 &lt;span class="nx"&gt;dynamic&lt;/span&gt; &lt;span class="s2"&gt;"cache_usage_limits"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;for_each&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cache_usage_limits&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="err"&gt;?&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cache_usage_limits&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
   &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nx"&gt;dynamic&lt;/span&gt; &lt;span class="s2"&gt;"data_storage"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="nx"&gt;for_each&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;try&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;cache_usage_limits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data_storage&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;
       &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="nx"&gt;maximum&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;try&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data_storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maximum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="nx"&gt;minimum&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;try&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data_storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;minimum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="nx"&gt;unit&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;try&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data_storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;unit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"GB"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
       &lt;span class="p"&gt;}&lt;/span&gt;
     &lt;span class="p"&gt;}&lt;/span&gt;

     &lt;span class="nx"&gt;dynamic&lt;/span&gt; &lt;span class="s2"&gt;"ecpu_per_second"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="nx"&gt;for_each&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;try&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;cache_usage_limits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ecpu_per_second&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;
       &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="nx"&gt;maximum&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;try&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ecpu_per_second&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maximum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="nx"&gt;minimum&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;try&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ecpu_per_second&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;minimum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
       &lt;span class="p"&gt;}&lt;/span&gt;
     &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
 &lt;span class="nx"&gt;daily_snapshot_time&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;daily_snapshot_time&lt;/span&gt;
 &lt;span class="nx"&gt;description&lt;/span&gt;              &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;coalesce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Serverless Cache"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="nx"&gt;kms_key_id&lt;/span&gt;               &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kms_key_id&lt;/span&gt;
 &lt;span class="nx"&gt;major_engine_version&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;major_engine_version&lt;/span&gt;
 &lt;span class="nx"&gt;security_group_ids&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;security_group_ids&lt;/span&gt;
 &lt;span class="nx"&gt;snapshot_arns_to_restore&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;snapshot_arns_to_restore&lt;/span&gt;
 &lt;span class="nx"&gt;snapshot_retention_limit&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;snapshot_retention_limit&lt;/span&gt;
 &lt;span class="nx"&gt;subnet_ids&lt;/span&gt;               &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subnet_ids&lt;/span&gt;
 &lt;span class="nx"&gt;user_group_id&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_elasticache_user_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;

 &lt;span class="nx"&gt;timeouts&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;create&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;try&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;timeouts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"40m"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="nx"&gt;delete&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;try&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;timeouts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"80m"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="nx"&gt;update&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;try&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;timeouts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;update&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"40m"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;

 &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tags&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3
&lt;/h3&gt;

&lt;p&gt;Create the &lt;code&gt;access.tf&lt;/code&gt; file. Here, we will manage ElastiCache users.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"random_string"&lt;/span&gt; &lt;span class="s2"&gt;"auth_user_password"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nx"&gt;for_each&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="nx"&gt;in&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;access_users&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;k&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="nx"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;try&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;generate_password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

 &lt;span class="nx"&gt;length&lt;/span&gt;           &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;
 &lt;span class="nx"&gt;special&lt;/span&gt;          &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
 &lt;span class="nx"&gt;override_special&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"/@£&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;# Regenerate auth_user / access_u2g_mapping&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="nx"&gt;locals&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nx"&gt;access_users&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="nx"&gt;in&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;access_users&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;k&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nx"&gt;generated_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"%s-%s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cache_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="nx"&gt;access_string&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"access_string"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
     &lt;span class="nx"&gt;auth_type&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"auth_type"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
     &lt;span class="nx"&gt;engine&lt;/span&gt;         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"engine"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
     &lt;span class="nx"&gt;passwords&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;try&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"generate_password"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;?&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;random_string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;auth_user_password&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;try&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"passwords"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_elasticache_user"&lt;/span&gt; &lt;span class="s2"&gt;"main"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nx"&gt;for_each&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;access_users&lt;/span&gt;

 &lt;span class="nx"&gt;user_id&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;each&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"generated_name"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
 &lt;span class="nx"&gt;user_name&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;each&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"generated_name"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
 &lt;span class="nx"&gt;access_string&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;each&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"access_string"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
 &lt;span class="nx"&gt;engine&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;each&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"engine"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

 &lt;span class="nx"&gt;authentication_mode&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;type&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;each&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"auth_type"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
   &lt;span class="nx"&gt;passwords&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;each&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"passwords"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;

 &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tags&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_elasticache_user_group"&lt;/span&gt; &lt;span class="s2"&gt;"main"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nx"&gt;user_group_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cache_name&lt;/span&gt;
 &lt;span class="nx"&gt;engine&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;engine&lt;/span&gt;

 &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tags&lt;/span&gt;

 &lt;span class="nx"&gt;lifecycle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;ignore_changes&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;user_ids&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_elasticache_user_group_association"&lt;/span&gt; &lt;span class="s2"&gt;"main"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nx"&gt;for_each&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;access_users&lt;/span&gt;

 &lt;span class="nx"&gt;user_group_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_elasticache_user_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user_group_id&lt;/span&gt;
 &lt;span class="nx"&gt;user_id&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_elasticache_user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;each&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;user_id&lt;/span&gt;

 &lt;span class="nx"&gt;depends_on&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
   &lt;span class="nx"&gt;aws_elasticache_user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="nx"&gt;aws_elasticache_user_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;
 &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pay attention, that when you’re working with AWS ElastiCache Serverless, there are two primary ways to access and manage your cluster:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;IAM Authentication:&lt;/strong&gt; Authenticate connections to ElastiCache for Valkey using AWS IAM identities. This method improves your security posture and simplifies administrative tasks, especially when operating within the AWS ecosystem.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Traditional password-based authentication:&lt;/strong&gt; Each cache user has a long-lived password that is used directly with the &lt;code&gt;AUTH&lt;/code&gt; command to authenticate client connections. This method is straightforward but requires careful credential management to maintain security.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 4
&lt;/h3&gt;

&lt;p&gt;Create the &lt;code&gt;outputs.tf&lt;/code&gt; file. It’s the default file for OpenTofu module outputs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"arn"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"The amazon resource name of the serverless cache"&lt;/span&gt;
 &lt;span class="nx"&gt;value&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;try&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;aws_elasticache_serverless_cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;this&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;arn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"create_time"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Timestamp of when the serverless cache was created"&lt;/span&gt;
 &lt;span class="nx"&gt;value&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;try&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;aws_elasticache_serverless_cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;this&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;create_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"endpoint"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;" Represents the information required for client programs to connect to a cache node"&lt;/span&gt;
 &lt;span class="nx"&gt;value&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;try&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;aws_elasticache_serverless_cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;this&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"full_engine_version"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"The name and version number of the engine the serverless cache is compatible with"&lt;/span&gt;
 &lt;span class="nx"&gt;value&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;try&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;aws_elasticache_serverless_cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;this&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;full_engine_version&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"major_engine_version"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"The version number of the engine the serverless cache is compatible with"&lt;/span&gt;
 &lt;span class="nx"&gt;value&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;try&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;aws_elasticache_serverless_cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;this&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;major_engine_version&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"reader_endpoint"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Represents the information required for client programs to connect to a cache node"&lt;/span&gt;
 &lt;span class="nx"&gt;value&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;try&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;aws_elasticache_serverless_cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;this&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;reader_endpoint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"status"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"The current status of the serverless cache. The allowed values are CREATING, AVAILABLE, DELETING, CREATE-FAILED and MODIFYING"&lt;/span&gt;
 &lt;span class="nx"&gt;value&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;try&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;aws_elasticache_serverless_cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;this&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"access_users"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;access_users&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 5
&lt;/h3&gt;

&lt;p&gt;Create the &lt;code&gt;variables.tf&lt;/code&gt; file. It’s the file for OpenTofu module variables, where we pre-defined some default values.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"create"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Determines whether serverless resource will be created."&lt;/span&gt;
 &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;bool&lt;/span&gt;
 &lt;span class="nx"&gt;default&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"cache_name"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"The name which serves as a unique identifier to the serverless cache."&lt;/span&gt;
 &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
 &lt;span class="nx"&gt;default&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"cache_usage_limits"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Sets the cache usage limits for storage and ElastiCache Processing Units for the cache."&lt;/span&gt;
 &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="nx"&gt;default&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"daily_snapshot_time"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"The daily time that snapshots will be created from the new serverless cache. Only supported for engine type `redis`. Defaults to 0."&lt;/span&gt;
 &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
 &lt;span class="nx"&gt;default&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"description"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"User-created description for the serverless cache."&lt;/span&gt;
 &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
 &lt;span class="nx"&gt;default&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"engine"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Name of the cache engine to be used for this cache cluster. Valid values are `memcached` or `redis`."&lt;/span&gt;
 &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
 &lt;span class="nx"&gt;default&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"redis"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"kms_key_id"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ARN of the customer managed key for encrypting the data at rest. If no KMS key is provided, a default service key is used."&lt;/span&gt;
 &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
 &lt;span class="nx"&gt;default&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"major_engine_version"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"The version of the cache engine that will be used to create the serverless cache."&lt;/span&gt;
 &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
 &lt;span class="nx"&gt;default&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"security_group_ids"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"One or more VPC security groups associated with the serverless cache."&lt;/span&gt;
 &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="nx"&gt;default&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"snapshot_arns_to_restore"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"The list of ARN(s) of the snapshot that the new serverless cache will be created from. Available for Redis only."&lt;/span&gt;
 &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="nx"&gt;default&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"snapshot_retention_limit"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"(Redis only) The number of snapshots that will be retained for the serverless cache that is being created."&lt;/span&gt;
 &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;
 &lt;span class="nx"&gt;default&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"subnet_ids"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"A list of the identifiers of the subnets where the VPC endpoint for the serverless cache will be deployed."&lt;/span&gt;
 &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="nx"&gt;default&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"timeouts"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Define maximum timeout for creating, updating, and deleting serverless resources."&lt;/span&gt;
 &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="nx"&gt;default&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"tags"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"A map of tags to add to all resources"&lt;/span&gt;
 &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="nx"&gt;default&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;# Access&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"access_users"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nx"&gt;default&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 6
&lt;/h3&gt;

&lt;p&gt;Create the &lt;code&gt;versions.tf&lt;/code&gt; file. It’s metadata file with OpenTofu and providers versions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;terraform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nx"&gt;required_version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&amp;gt;= 1.0"&lt;/span&gt;

 &lt;span class="nx"&gt;required_providers&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;aws&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nx"&gt;source&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"hashicorp/aws"&lt;/span&gt;
     &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&amp;gt;= 5.77"&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it - you’ve created your own module for managing AWS ElastiCache Serverless! Now, let’s move on to building the dependent infrastructure that we will use this guide.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Create dependent AWS infrastructure&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The AWS ElastiCache module is insufficient for our guidance; to use the cluster, we must construct additional infrastructure such as vpc, subnets, kms, and security groups. Let's build all of it in the &lt;code&gt;elasticache_guide/main.tf&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"vpc"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nx"&gt;source&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"terraform-aws-modules/vpc/aws"&lt;/span&gt;
 &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 5.0"&lt;/span&gt;

 &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"kvendingoldo-demo-elasticache-serverless"&lt;/span&gt;
 &lt;span class="nx"&gt;cidr&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"10.0.0.0/16"&lt;/span&gt;

 &lt;span class="nx"&gt;azs&lt;/span&gt;             &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"us-east-1a"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"us-east-1b"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
 &lt;span class="nx"&gt;private_subnets&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"10.0.1.0/24"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"10.0.2.0/24"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

 &lt;span class="nx"&gt;enable_dns_hostnames&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
 &lt;span class="nx"&gt;enable_dns_support&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"security_groups"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nx"&gt;source&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"terraform-aws-modules/security-group/aws"&lt;/span&gt;
 &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 5.0"&lt;/span&gt;

 &lt;span class="nx"&gt;name&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"kvendingoldo-demo-elasticache-serverless"&lt;/span&gt;
 &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Security group for ElastiCache Serverless"&lt;/span&gt;
 &lt;span class="nx"&gt;vpc_id&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;vpc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;vpc_id&lt;/span&gt;

 &lt;span class="nx"&gt;security_group_rules&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;ingress_self&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ingress"&lt;/span&gt;
     &lt;span class="nx"&gt;from_port&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;6379&lt;/span&gt;
     &lt;span class="nx"&gt;to_port&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;6379&lt;/span&gt;
     &lt;span class="nx"&gt;protocol&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"tcp"&lt;/span&gt;
     &lt;span class="nx"&gt;self&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
     &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Allow self-traffic"&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="nx"&gt;egress_all&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"egress"&lt;/span&gt;
     &lt;span class="nx"&gt;from_port&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
     &lt;span class="nx"&gt;to_port&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
     &lt;span class="nx"&gt;protocol&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"-1"&lt;/span&gt;
     &lt;span class="nx"&gt;cidr_blocks&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"0.0.0.0/0"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
     &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Allow all egress"&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"kms_elasticache_serverless"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nx"&gt;source&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"terraform-aws-modules/kms/aws"&lt;/span&gt;
 &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 1.0"&lt;/span&gt;

 &lt;span class="nx"&gt;alias&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"kvendingoldo-demo-elasticache-serverless"&lt;/span&gt;
 &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"KMS key for ElastiCache Serverless encryption"&lt;/span&gt;

 &lt;span class="nx"&gt;enable_key_rotation&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"elasticache_serverless"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"./modules/elasticache_serverless"&lt;/span&gt;

 &lt;span class="nx"&gt;engine&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"valkey"&lt;/span&gt;
 &lt;span class="nx"&gt;cache_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"kvendingoldo-demo-elasticache-serverless"&lt;/span&gt;

 &lt;span class="nx"&gt;cache_usage_limits&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;data_storage&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nx"&gt;maximum&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="c1"&gt;# 2Gb&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="nx"&gt;ecpu_per_second&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nx"&gt;maximum&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt; &lt;span class="c1"&gt;# Approximate for 2 vCPUs (1000 per vCPU)&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;

 &lt;span class="nx"&gt;daily_snapshot_time&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"22:00"&lt;/span&gt;
 &lt;span class="nx"&gt;description&lt;/span&gt;         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Valkey serverless cluster for kvendingoldo demo"&lt;/span&gt;

 &lt;span class="nx"&gt;kms_key_id&lt;/span&gt;           &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kms_elasticache_serverless&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;key_arn&lt;/span&gt;
 &lt;span class="nx"&gt;major_engine_version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"7"&lt;/span&gt;
 &lt;span class="nx"&gt;security_group_ids&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
   &lt;span class="k"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;security_groups&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"elasticache_serverless"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
 &lt;span class="p"&gt;]&lt;/span&gt;
 &lt;span class="nx"&gt;subnet_ids&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;vpc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;private_subnets&lt;/span&gt;

 &lt;span class="nx"&gt;snapshot_retention_limit&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;

 &lt;span class="nx"&gt;access_users&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="s2"&gt;"admin-iam"&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nx"&gt;access_string&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"on ~* +@all"&lt;/span&gt;
     &lt;span class="nx"&gt;engine&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"valkey"&lt;/span&gt;
     &lt;span class="nx"&gt;auth_type&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"iam"&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="s2"&gt;"admin-pwd"&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nx"&gt;access_string&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"on ~* +@all"&lt;/span&gt;
     &lt;span class="nx"&gt;engine&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"valkey"&lt;/span&gt;
     &lt;span class="nx"&gt;auth_type&lt;/span&gt;         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"password"&lt;/span&gt;
     &lt;span class="nx"&gt;generate_password&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"elasticache_serverless_endpoint"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;elasticache_serverless&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;endpoint&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"elasticache_serverless_users"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;elasticache_serverless&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;access_users&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, this file partially uses community modules from the Internet to create the VPC, KMS, and security group. If you like, you can use &lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs" rel="noopener noreferrer"&gt;native AWS Terraform resources&lt;/a&gt; instead.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Apply the OpenTofu code&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Before applying our AWS resources, we need to initialize OpenTofu. During this step, OpenTofu will create the state file and download all required providers.&lt;/p&gt;

&lt;p&gt;To do this, run the following command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ tofu init&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Next, let's see what OpenTofu plans to do by generating an execution plan using the following command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ tofu plan&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;After reviewing the plan, it’s finally time to apply our configuration using the following command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ tofu apply -auto-approve&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Once completed, OpenTofu will display the details of the provisioned ElastiCache Valkey instance.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Connect to the cluster&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Get an endpoint
&lt;/h3&gt;

&lt;p&gt;As mentioned earlier, you’ll see the connection details in the OpenTofu output. Alternatively, you can retrieve the endpoint using the AWS CLI with the following command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;aws elasticache describe-serverless-caches --query "serverlessCaches[?cacheName=='kvendingoldo-demo-elasticache-serverless'].endpoint"&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Connect by redis-cli
&lt;/h3&gt;

&lt;p&gt;Valkey is compatible with Redis clients. You can use your preferred client to connect to the endpoint on the default Redis port &lt;code&gt;6379&lt;/code&gt;. In my case, I use &lt;code&gt;redis-cli&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;redis-cli -h &amp;lt;serverless_endpoint&amp;gt; -p 6379 -a &amp;lt;your_password&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Run a simple command to confirm connection: &lt;code&gt;ping&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You should get a response: &lt;code&gt;PONG&lt;/code&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Cleaning up resources&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;After the checking that everything works you can destroy the created resources when they are no longer needed  to avoid unnecessary costs by the following command&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ tofu destroy -auto-approve&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This will remove the ElastiCache instance and all related resources.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In this guide, we walked through creating a dedicated OpenTofu module to provision AWS ElastiCache Serverless with the Valkey engine, following best practices for infrastructure as code. We covered setting up OpenTofu, building reusable modules, and connecting to your Valkey instance.&lt;/p&gt;

&lt;p&gt;By leveraging OpenTofu and Valkey, you gain a fully open source and flexible solution for managing serverless caching on AWS, helping you avoid licensing pitfalls and maintain control over your infrastructure.&lt;/p&gt;

&lt;p&gt;Feel free to extend the module to fit your needs and explore additional automation opportunities. If you have any questions or want to dive deeper into related topics, just let me know!&lt;/p&gt;

&lt;p&gt;Happy caching!&lt;/p&gt;

</description>
      <category>elasticache</category>
      <category>opensource</category>
      <category>opentofu</category>
      <category>terraform</category>
    </item>
    <item>
      <title>Fix InvalidParameterValueException for AWS Lambda docker images built by GitHub Actions</title>
      <dc:creator>kvendingoldo</dc:creator>
      <pubDate>Mon, 31 Mar 2025 09:37:00 +0000</pubDate>
      <link>https://forem.com/aws-builders/fix-invalidparametervalueexception-for-aws-lambda-docker-images-built-by-github-actions-32p9</link>
      <guid>https://forem.com/aws-builders/fix-invalidparametervalueexception-for-aws-lambda-docker-images-built-by-github-actions-32p9</guid>
      <description>&lt;p&gt;If you're using GitHub Actions to build Docker images for AWS Lambda functions, you might encounter the following error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;InvalidParameterValueException: The image manifest, config or layer media type for the source image \*\*\*.dkr.ecr.\*\*\*.amazonaws.com/myrepository/myimage:latest is not supported.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This error is confusing at first glance — especially if you’ve successfully used the same image with EKS, ECS or other docker-based environments. Here’s what’s going on under the hood.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;GitHub Actions (&lt;code&gt;docker/build-push-action@v4&lt;/code&gt;) builds OCI images by default with &lt;code&gt;provenance&lt;/code&gt; and &lt;code&gt;sbom&lt;/code&gt; enabled. However, AWS Lambda only supports Docker v2 manifests — &lt;em&gt;not&lt;/em&gt; OCI. To fix the error, disable those features in your GitHub action step:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;provenance: false 
sbom: false
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Root Cause: OCI vs Docker Image Format
&lt;/h2&gt;

&lt;p&gt;Starting with version 4, &lt;a href="https://github.com/docker/build-push-action" rel="noopener noreferrer"&gt;&lt;code&gt;docker/build-push-action&lt;/code&gt;&lt;/a&gt; &lt;strong&gt;builds images using the OCI format by default&lt;/strong&gt;. OCI (Open Container Initiative) is the modern standard that is supported by &lt;strong&gt;AWS ECR.&lt;/strong&gt; However, &lt;strong&gt;AWS Lambda does &lt;em&gt;not&lt;/em&gt; support OCI image manifests&lt;/strong&gt;. Lambda only accepts the older Docker v2 schema: &lt;code&gt;application/vnd.docker.distribution.manifest.v2+json&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;That’s why your image may push to ECR fine but still fail at deployment to Lambda with &lt;code&gt;InvalidParameterValueException&lt;/code&gt; error. After pushing the image to ECR, you will see something like this in the metadata:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmf0qrch8l754vn5fi6bq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmf0qrch8l754vn5fi6bq.png" alt="Metadata for OCI image in ECR UI" width="800" height="455"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Lambda Doesn’t Support OCI
&lt;/h2&gt;

&lt;p&gt;While ECR and ECS support OCI images, Lambda does not— and here’s why:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lambda implemented container image support in 2020&lt;/strong&gt;, using the Docker v2 image spec, which was the most stable and frequently used format at the time.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance and security constraints&lt;/strong&gt;: Lambda is designed for quick cold starts and strict security. Supporting full OCI manifests (particularly with SBOMs and provenance metadata) may raise complexity, slow down startup, or expose new attack vectors.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lambda is not a general container runtime&lt;/strong&gt;: Lambda's runtime mechanism is restricted, unlike ECS or EKS, which are designed to execute arbitrary containers. Supporting a wider range of image formats is not a priority.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;p&gt;To remedy the image manifest format issue, modify the docker/build-push-action@v4 step in your GitHub job file as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- name: Build and push Lambda image
 uses: docker/build-push-action@v4
 with:
   context: .
   push: true
   tags: |
     latest
   provenance: false
   sbom: false
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Setting both &lt;code&gt;provenance: false&lt;/code&gt; and &lt;code&gt;sbom: false&lt;/code&gt; disables features that require OCI format, thereby enabling Docker v2 manifest compatibility.&lt;/p&gt;

&lt;p&gt;This results in your image being built with the proper media type,&lt;code&gt;application/vnd.docker.distribution.manifest.v2+json&lt;/code&gt; which Lambda can consume without trouble.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp7oucaya0aw9jbpaar8g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp7oucaya0aw9jbpaar8g.png" alt="Metadata for Docker V2 image in ECR UI" width="800" height="361"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What are &lt;code&gt;provenance&lt;/code&gt; and &lt;code&gt;sbom&lt;/code&gt; options?
&lt;/h2&gt;

&lt;p&gt;In GitHub Actions, the Docker Buildx plugin now enables two features by default:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;provenance: true&lt;/code&gt; — enables Software Supply Chain Provenance, which attaches build metadata to the image (as per &lt;a href="https://slsa.dev/" rel="noopener noreferrer"&gt;SLSA&lt;/a&gt; standards).
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sbom: true&lt;/code&gt; — enables generation of SBOMs (Software Bill of Materials), a key part of software supply chain security.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Service Compatibility Overview&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2qiqio7xs9m9h3cm7qfa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2qiqio7xs9m9h3cm7qfa.png" alt="AWS services compatibility with Docker" width="800" height="114"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Final Thoughts&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;While OCI represents the future of container image standards, AWS Lambda has yet to catch up to it. If you're deploying Lambda functions using GitHub Actions, make sure your image builds are Docker-compatible via modifying the provenance and sbom settings.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>docker</category>
      <category>lambda</category>
      <category>github</category>
    </item>
    <item>
      <title>Top Terraform/OpenTofu tools to Use in 2025</title>
      <dc:creator>kvendingoldo</dc:creator>
      <pubDate>Tue, 04 Feb 2025 08:20:56 +0000</pubDate>
      <link>https://forem.com/kvendingoldo/top-terraformopentofu-tools-to-use-in-2025-4o8h</link>
      <guid>https://forem.com/kvendingoldo/top-terraformopentofu-tools-to-use-in-2025-4o8h</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn2dft0xtiz6055vgi91x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn2dft0xtiz6055vgi91x.png" alt="Image description" width="800" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Overview
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Infrastructure-as-Code (IaC)&lt;/strong&gt; has become a trusted approach for managing and provisioning infrastructure. As the field evolves, the number of IaC tools continues to grow, with frequent updates, new features, and improvements being introduced.&lt;/p&gt;

&lt;p&gt;One of the most popular tools in this space is &lt;strong&gt;Terraform&lt;/strong&gt;, a leader in the IaC ecosystem. There is a wide range of smaller tools that work alongside Terraform, adding extra features and making it even more powerful.&lt;/p&gt;

&lt;p&gt;In this article, we’ll dive into the top &lt;strong&gt;most useful Terraform tools for 2025&lt;/strong&gt;—a curated selection of tools that stand out for their active maintenance, ongoing development, and exceptional user experience.&lt;/p&gt;

&lt;p&gt;Pay attention, that last year, Terraform changed its license, leading the community to create a fork called &lt;strong&gt;OpenTofu&lt;/strong&gt;, licensed under MPL-2.0 license. All the tools discussed in this article are fully compatible with both &lt;strong&gt;Terraform&lt;/strong&gt; and &lt;strong&gt;OpenTofu&lt;/strong&gt; and can be used together in mixed environments.&lt;/p&gt;

&lt;p&gt;Ready to dive in? Let’s explore these tools and how they can supercharge your IaC workflows.&lt;/p&gt;

&lt;h1&gt;
  
  
  tenv
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;tenv&lt;/strong&gt; is a version manager for Terraform, OpenTofu, Terragrunt, and Atmos, written in Go developed by &lt;strong&gt;tofuutils&lt;/strong&gt; team. It simplifies the management of multiple tool versions. Initially developed as a successor to &lt;strong&gt;tfenv&lt;/strong&gt; and &lt;strong&gt;tofuenv&lt;/strong&gt;, tenv reduces the complexity of versioning, allowing developers and DevOps professionals to focus on building and deploying infrastructure without worrying about versioning issues.&lt;/p&gt;

&lt;p&gt;While many users rely on &lt;strong&gt;asdf&lt;/strong&gt; for version management, &lt;strong&gt;tenv&lt;/strong&gt; is specifically tailored for the Terraform ecosystem. It offers advanced features such as HCL parsing for precise version detection and seamless management across supported tools. Besides that &lt;strong&gt;tenv&lt;/strong&gt; is faster, platform-independent (thanks to its binary delivery), and prioritizes enhanced security through features like checksum and signature verification.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Versatile Version Management&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Supports managing multiple versions of Terraform, OpenTofu, Terragrunt, and Atmos.
&lt;/li&gt;
&lt;li&gt;Allows easy switching between tool versions to suit different project requirements.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Simple Installation&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Simple installation via Homebrew, Choco, Nix, Yay, Scoop, APT, Snapcraft, Docker or many more package managers and options.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Performance &amp;amp; Cross-Platform Compatibility&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;tenv is written in Go. It supplies an extensive list of features such as fast speed, efficiency, and uniform support for all main operating systems, including Linux, MacOS, Windows, FreeBSD, OpenBSD, and Solaris.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Signature Verification&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Verifies downloads using &lt;a href="https://github.com/sigstore/cosign" rel="noopener noreferrer"&gt;cosign&lt;/a&gt; and PGP (via &lt;a href="https://github.com/ProtonMail/gopenpgp" rel="noopener noreferrer"&gt;gopenpgp&lt;/a&gt;), ensuring the integrity and authenticity of tool binaries.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;a href="https://semver.org/" rel="noopener noreferrer"&gt;Semver 2.0.0&lt;/a&gt; &lt;strong&gt;Compatibility&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Tenv utilizes &lt;a href="https://github.com/hashicorp/go-version" rel="noopener noreferrer"&gt;go-version&lt;/a&gt; for semantic versioning and &lt;a href="https://github.com/hashicorp/hcl" rel="noopener noreferrer"&gt;HCL&lt;/a&gt; parsing to extract version constraints from files like &lt;a href="https://github.com/tofuutils/tenv#required_version" rel="noopener noreferrer"&gt;required_version&lt;/a&gt; in Terraform/OpenTofu or Terragrunt HCL files.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Backwards Compatibility&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Fully supports version files used by &lt;strong&gt;tfenv&lt;/strong&gt; (&lt;code&gt;.terraform-version&lt;/code&gt;), &lt;strong&gt;tofuenv&lt;/strong&gt; (&lt;code&gt;.opentofu-version&lt;/code&gt;), &lt;strong&gt;asdf&lt;/strong&gt; (&lt;code&gt;.tool-versions&lt;/code&gt;), and so on.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Callable as a&lt;/strong&gt; &lt;a href="https://go.dev/" rel="noopener noreferrer"&gt;Go&lt;/a&gt; &lt;strong&gt;Module&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Includes a &lt;a href="https://semver.org/#summary" rel="noopener noreferrer"&gt;Semver compatibility promise&lt;/a&gt; via the &lt;a href="https://github.com/tofuutils/tenv/tree/main/versionmanager/tenvlib" rel="noopener noreferrer"&gt;tenvlib&lt;/a&gt; wrapper package for seamless integration (details available in &lt;a href="https://github.com/tofuutils/tenv/blob/main/TENV_AS_LIB.md" rel="noopener noreferrer"&gt;TENV_AS_LIB.md&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Can be used as a library to download OpenTofu with minimum dependencies.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Link&lt;/strong&gt;: &lt;a href="https://github.com/tofuutils/tenv" rel="noopener noreferrer"&gt;https://github.com/tofuutils/tenv&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Aiac
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Aiac&lt;/strong&gt; is an Artificial Intelligence Infrastructure-as-Code Generator developed by &lt;strong&gt;Firefly.ai&lt;/strong&gt;. Implemented as a library and command-line tool (CLI), Aiac leverages Large Language Models (&lt;a href="https://en.wikipedia.org/wiki/Large_language_model" rel="noopener noreferrer"&gt;LLM&lt;/a&gt;) to generate Infrastructure as Code (IaC) templates, configurations, utilities, queries, and more.&lt;/p&gt;

&lt;p&gt;The CLI allows users to ask a model to generate templates for different scenarios (e.g. "get terraform for AWS EC2" or “generate GKE autopilot terraform code”). It composes an appropriate request to the selected provider, and stores the resulting code to a file, and/or prints it to standard output.&lt;/p&gt;

&lt;p&gt;Users can define multiple "backends" targeting different LLM providers and environments using a simple configuration file. This automation significantly reduces the time and effort required for routine tasks, empowering cloud engineers to focus on high-value work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Support for Multiple LLM Providers&lt;/strong&gt;: It includes &lt;a href="https://openai.com/" rel="noopener noreferrer"&gt;OpenAI&lt;/a&gt;, &lt;a href="https://aws.amazon.com/bedrock/" rel="noopener noreferrer"&gt;Amazon Bedrock&lt;/a&gt; and &lt;a href="https://ollama.ai/" rel="noopener noreferrer"&gt;Ollama&lt;/a&gt;.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Versatile Code Generation:&lt;/strong&gt; Terraform code / CICD pipelines / OPA policies / Dockerfiles and more.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simplified Workflow:&lt;/strong&gt; Allows users to generate IaC templates using simple prompts, and automatically composes requests to the selected LLM provider and saves the output to a file or prints it to standard output.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time-Saving Automation&lt;/strong&gt;: Helps to reduce cloud engineers time by simple prompts that do a typical toil.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Link&lt;/strong&gt;: &lt;a href="https://aiac.dev" rel="noopener noreferrer"&gt;https://aiac.dev&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Atmos
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Atmos&lt;/strong&gt; is a cutting-edge framework designed by &lt;strong&gt;Cloud Posse&lt;/strong&gt; specifically for native Terraform, enabling teams to streamline and optimize their infrastructure management processes.&lt;/p&gt;

&lt;p&gt;With Atmos, you can break down your cloud architecture into reusable &lt;strong&gt;components&lt;/strong&gt;, implemented using Terraform "root modules." These components are seamlessly tied together using &lt;strong&gt;stack configurations&lt;/strong&gt; defined in YAML, offering a clear and organized way to manage complex infrastructure setups.&lt;/p&gt;

&lt;p&gt;This tool promotes a modular, scalable, and efficient approach to infrastructure management, making it ideal for handling even the most intricate deployments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://atmos.tools/cli" rel="noopener noreferrer"&gt;Terminal UI&lt;/a&gt;: A polished interface that simplifies interaction with Terraform, workflows, and commands.
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://atmos.tools/cli/commands/terraform/usage" rel="noopener noreferrer"&gt;Native Terraform Support:&lt;/a&gt; Streamlines orchestration, backend generation, and varfile creation while maintaining full compatibility with vanilla Terraform.
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://atmos.tools/core-concepts/stacks" rel="noopener noreferrer"&gt;Stacks:&lt;/a&gt; Provides a powerful abstraction layer, defined in YAML, for orchestrating and deploying components efficiently.
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://atmos.tools/core-concepts/components" rel="noopener noreferrer"&gt;Components:&lt;/a&gt; A flexible abstraction for deployable units, such as Terraform "root" modules, promoting reusability and scalability.
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://atmos.tools/core-concepts/vendor" rel="noopener noreferrer"&gt;Vendoring:&lt;/a&gt; Supports immutable infrastructure by pulling dependencies from remote sources for consistent deployments.
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://atmos.tools/core-concepts/custom-commands" rel="noopener noreferrer"&gt;Custom Commands:&lt;/a&gt; Extends Atmos’s capabilities by integrating custom commands into stack configurations for enhanced flexibility.
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://atmos.tools/core-concepts/workflows" rel="noopener noreferrer"&gt;Workflow Orchestration:&lt;/a&gt; Comprehensive lifecycle management for cloud infrastructure, from initiation to maintenance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Link&lt;/strong&gt;: &lt;a href="https://github.com/cloudposse/atmos" rel="noopener noreferrer"&gt;https://github.com/cloudposse/atmos&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Terragrunt
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Terragrunt&lt;/strong&gt; is a widely used open-source tool, often referred to as a "thin wrapper" for Terraform. It enhances Terraform’s capabilities by providing additional tools to keep your configurations &lt;strong&gt;DRY&lt;/strong&gt; ("Don't Repeat Yourself").&lt;/p&gt;

&lt;p&gt;Developed by &lt;strong&gt;Gruntwork&lt;/strong&gt;, Terragrunt simplifies managing remote states, handling multiple environments, and executing custom code before or after running Terraform. Beyond these features, it helps maintain a clean, organized codebase, making infrastructure as code more manageable and efficient.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DRY Principle&lt;/strong&gt;: Adheres to the "Don't Repeat Yourself" principle, it simplify Terraform configurations by reducing repetitive code. This approach enhances code maintainability and improves human readability.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Remote State Management&lt;/strong&gt;: Efficiently manages Terraform's remote state configurations, ensuring stability and scalability. Terragrunt can automatically organize and store state files in popular storage solutions like &lt;strong&gt;AWS S3&lt;/strong&gt;, &lt;strong&gt;Google Cloud Storage&lt;/strong&gt;, &lt;strong&gt;Azure Blob Storage&lt;/strong&gt;, or any other Terraform-supported backends.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dependency Handling&lt;/strong&gt;: Simplifies the management of complex module dependencies, especially when execution order is critical.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-Module Efficiency&lt;/strong&gt;: Optimizes workflows for large-scale deployments involving multiple modules, making it easier to handle extensive infrastructure setups.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Environment-Specific Configuration:&lt;/strong&gt; Supports the creation of environment-specific configurations (e.g., dev, staging, prod) using HCL (HashiCorp Configuration Language) interpolation, enabling consistent and organized environment management.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secrets Management:&lt;/strong&gt; Integrates seamlessly with external secrets management tools like AWS Secrets Manager and HashiCorp Vault, ensuring sensitive data is handled securely.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configurable Hooks:&lt;/strong&gt; Supports pre- and post-Terraform hooks, allowing you to execute custom scripts or commands before or after running Terraform commands for greater flexibility and automation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Link&lt;/strong&gt;: &lt;a href="https://terragrunt.gruntwork.io" rel="noopener noreferrer"&gt;https://terragrunt.gruntwork.io&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Checkov
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Checkov&lt;/strong&gt; is a robust static code analysis (SCA) tool designed for Infrastructure as Code and software composition analysis (SCA). It ensures that your Terraform and other IaC configurations are secure and compliant before deployment.&lt;/p&gt;

&lt;p&gt;Similar to &lt;strong&gt;Terrascan&lt;/strong&gt;, Checkov utilizes a Python-based policy-as-code framework, differing from the Rego syntax used in OPA. Its extensive support for multiple technologies makes it a popular choice for teams managing complex cloud and containerized environments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Extensive Built-in Policies&lt;/strong&gt;: &lt;a href="https://github.com/bridgecrewio/checkov/blob/main/docs/5.Policy%20Index/all.md" rel="noopener noreferrer"&gt;Over 1000 built-in policies&lt;/a&gt; cover security and compliance best practices for major cloud providers like AWS, Azure, and Google Cloud.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Versatile Technology Support:&lt;/strong&gt; compatible with a wide range of technologies, including:  Terraform, Terraform Plan, Terraform JSON, CloudFormation, AWS SAM, Kubernetes, Helm, Kustomize, Dockerfile, Serverless framework, Ansible, Bicep, ARM, OpenTofu  and more.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Comprehensive Analysis:&lt;/strong&gt; Uses graph-based scanning to identify misconfigurations, security vulnerabilities, and compliance issues across your IaC.
&lt;/li&gt;
&lt;li&gt;Support of Terraform and Terraform plan analysis
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SCA Capabilities&lt;/strong&gt;: Performs software composition analysis to detect vulnerabilities in open-source packages and container images.
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.prismacloud.io/prisma/cloud/secrets-security" rel="noopener noreferrer"&gt;&lt;strong&gt;Secrets Detection&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; Identifies exposed secrets using techniques like regular expressions, keyword matching, and entropy-based detection.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CI/CD Integration:&lt;/strong&gt; Seamlessly integrates with CI/CD pipelines, enabling pre-deployment security checks for continuous delivery workflows.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Provides&lt;/strong&gt; &lt;a href="https://github.com/bridgecrewio/checkov/blob/main/docs/2.Basics/Reviewing%20Scan%20Results.md" rel="noopener noreferrer"&gt;output&lt;/a&gt; &lt;strong&gt;in multiple formats:&lt;/strong&gt; CLI, &lt;a href="https://cyclonedx.org/" rel="noopener noreferrer"&gt;CycloneDX&lt;/a&gt;, JSON, JUnit XML, CSV, SARIF, GitHub markdown, and links to remediation &lt;a href="https://docs.prismacloud.io/en/enterprise-edition/policy-reference/" rel="noopener noreferrer"&gt;guides&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Link&lt;/strong&gt;: &lt;a href="https://github.com/bridgecrewio/checkov" rel="noopener noreferrer"&gt;https://github.com/bridgecrewio/checkov&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Trivy
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Trivy&lt;/strong&gt; is a comprehensive, all-in-one open-source security scanner developed by aquasecurity and designed to detect vulnerabilities (CVEs), misconfigurations, secrets, and generate SBOMs across a wide range of resources, including code repositories, Terraform code,  binary artifacts, container images, and Kubernetes clusters. &lt;/p&gt;

&lt;p&gt;By integrating &lt;strong&gt;Terraform misconfiguration scanning&lt;/strong&gt; into its robust ecosystem, Trivy empowers teams to proactively identify and resolve vulnerabilities, ensuring secure and compliant infrastructure deployments. Its ability to streamline security checks across various stages of development and deployment makes it an indispensable tool for modern DevOps workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Misconfiguration Detection:&lt;/strong&gt; Scans for security misconfigurations in Kubernetes clusters, Terraform files, Dockerfiles, and other IaC templates.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integrated IaC Security:&lt;/strong&gt; Combines the capabilities of &lt;strong&gt;tfsec&lt;/strong&gt; with Trivy’s broader security features, offering a unified tool for scanning Infrastructure as Code templates, including Terraform, Kubernetes manifests, and Dockerfiles.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pre-Deployment Validation:&lt;/strong&gt; Ensures that Terraform configurations are secure and compliant before deployment, reducing risks in production environments.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vulnerability Scanning&lt;/strong&gt; Identifies known vulnerabilities in:

&lt;ul&gt;
&lt;li&gt;Container images
&lt;/li&gt;
&lt;li&gt;Filesystems
&lt;/li&gt;
&lt;li&gt;Repositories
&lt;/li&gt;
&lt;li&gt;Cloud services like AWS S3 and Lambda.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Cloud Security Scanning:&lt;/strong&gt; Supports scanning cloud services for security misconfigurations and vulnerabilities, ensuring robust cloud infrastructure security.
&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Comprehensive Database:&lt;/strong&gt; Leverages a frequently updated vulnerability database, ensuring that the latest CVEs and security advisories are included in scans.
&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Rich Ecosystem:&lt;/strong&gt; Offers seamless integration with CI/CD pipelines, enabling automated security checks during development and deployment stages.
&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Community and Support:&lt;/strong&gt; Backed by &lt;strong&gt;Aqua Security&lt;/strong&gt; and a vibrant open-source community, Trivy benefits from continuous updates, extensive documentation, and dedicated resources&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Link&lt;/strong&gt;: &lt;a href="https://aquasecurity.github.io/trivy/" rel="noopener noreferrer"&gt;https://aquasecurity.github.io/trivy/&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Infracost
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Infracost&lt;/strong&gt; empowers teams to adopt a &lt;strong&gt;shift-left approach&lt;/strong&gt; for cloud cost management by providing cost estimates for Terraform resources before deployment. It also evaluates compliance with &lt;strong&gt;FinOps best practices&lt;/strong&gt;, ensuring alignment with &lt;strong&gt;Well-Architected Frameworks&lt;/strong&gt; from cloud vendors and your organization's tagging policies. This proactive approach saves money, fosters cost-conscious discussions early in the development workflow, and prevents cost surprises after deployment.&lt;/p&gt;

&lt;p&gt;As cloud spending continues to be a significant concern for organizations, understanding the financial impact of infrastructure changes is more critical than ever. Infracost provides &lt;strong&gt;precise cost estimates&lt;/strong&gt; for Terraform-managed resources, enabling informed decision-making before deploying changes. With support for AWS, Azure, and Google Cloud, it integrates seamlessly into your engineering processes, offering detailed cost breakdowns in development environments, terminals, VS Code, or pull requests.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cost Awareness:&lt;/strong&gt; Displays detailed cost breakdowns directly within development environments such as Terminals, Visual Studio Code, GitHub Pull requests
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CI/CD Integration:&lt;/strong&gt; Extends functionality through Infracost Cloud, offering centralized cost dashboards,cost policies management, integrations with tools like Jira
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Proactive Budget Management:&lt;/strong&gt; Identifies cost impacts early in the development process, promoting effective budget control and informed decision-making.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Policy Enforcement:&lt;/strong&gt; Supports &lt;a href="https://www.infracost.io/docs/infracost_cloud/tagging_policies/" rel="noopener noreferrer"&gt;Tagging policies&lt;/a&gt; and &lt;a href="https://www.infracost.io/docs/infracost_cloud/finops_policies/" rel="noopener noreferrer"&gt;FinOps policies&lt;/a&gt; to ensure adherence to your organization’s best practices and standards.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Link&lt;/strong&gt;: &lt;a href="https://github.com/infracost/infracost" rel="noopener noreferrer"&gt;https://github.com/infracost/infracost&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Tfmigrate
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Tfmigrate&lt;/strong&gt; is a powerful tool designed for &lt;strong&gt;Terraform state management&lt;/strong&gt;, optimized to complement &lt;strong&gt;GitOps workflows&lt;/strong&gt;. It simplifies state changes by enabling users to write state commands like &lt;strong&gt;move (mv)&lt;/strong&gt;, &lt;strong&gt;remove (rm)&lt;/strong&gt;, and import in HCL, making state migrations structured, version-controlled, and transparent.&lt;/p&gt;

&lt;p&gt;With Tfmigrate, teams can maintain clean and well-organized Terraform states, making it easier to manage and scale infrastructure while ensuring safe and efficient state modifications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;State Migration:&lt;/strong&gt; facilitates seamless resource migration between Terraform states, ideal for mono-repo setups used in managing and refactoring complex infrastructures.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dry Run Mode:&lt;/strong&gt; allows users to simulate state operations using a temporary local state. This ensures safe migrations by previewing changes without impacting remote states.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitOps-Friendly Workflow:&lt;/strong&gt; supports writing Terraform state mv/rm/import commands directly in HCL. Users can plan and apply these changes as part of their version-controlled workflows.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monorepo Style Support:&lt;/strong&gt; enables resource movement across Terraform states, simplifying tasks like splitting or merging states during refactoring.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dry Run Migration:&lt;/strong&gt; simulates state migrations with a temporary local state and validates the changes by running &lt;code&gt;terraform plan&lt;/code&gt; to ensure there are no unintended modifications before updating the remote state.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Migration History:&lt;/strong&gt; tracks applied migrations and ensures all unapplied migrations are executed in sequence, providing an auditable and organized approach to state changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Link&lt;/strong&gt;: &lt;a href="https://github.com/minamijoyo/tfmigrate" rel="noopener noreferrer"&gt;https://github.com/minamijoyo/tfmigrate&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Tfmv
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;tfmv&lt;/strong&gt; is a powerful CLI tool specifically designed to simplify the process of renaming Terraform resources, data sources, and modules, while automatically generating the necessary moved blocks. &lt;/p&gt;

&lt;p&gt;This ensures seamless state transitions and minimizes manual intervention, making &lt;strong&gt;tfmv&lt;/strong&gt; an indispensable tool for teams looking to refactor and reorganize their Terraform configurations efficiently.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Resource Renaming:&lt;/strong&gt; Simplifies the process of renaming resources, data sources, and modules in Terraform configurations.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automatic Moved Blocks:&lt;/strong&gt; Generates &lt;code&gt;moved&lt;/code&gt; blocks to ensure smooth state transitions during resource renaming.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Streamlined Refactoring:&lt;/strong&gt; Makes it easier to refactor Terraform code, improving maintainability and reducing manual effort.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Link&lt;/strong&gt;: &lt;a href="https://github.com/suzuki-shunsuke/tfmv" rel="noopener noreferrer"&gt;https://github.com/suzuki-shunsuke/tfmv&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  TFLint
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;TFLint&lt;/strong&gt; is a &lt;strong&gt;pluggable linter for Terraform&lt;/strong&gt;, designed to help developers enforce coding standards and detect potential issues in their configurations. By ensuring that Terraform code is clean, optimized, and compliant with best practices, TFLint reduces errors and improves the quality of infrastructure as code before deployment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Error Detection:&lt;/strong&gt; TFLint entifies potential issues, such as:

&lt;ul&gt;
&lt;li&gt;Invalid instance types for major cloud providers like AWS, Azure, and Google Cloud.
&lt;/li&gt;
&lt;li&gt;Misconfigurations that could lead to deployment failures.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Syntax Warnings:&lt;/strong&gt; It aerts developers about:

&lt;ul&gt;
&lt;li&gt;Deprecated Terraform syntax.
&lt;/li&gt;
&lt;li&gt;Unused declarations, ensuring clean and efficient code.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Custom Rules:&lt;/strong&gt; Supports plugins for defining custom rules, allowing teams to tailor linting checks to their specific coding standards and policies.
&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Best Practices Enforcement:&lt;/strong&gt; Encourages adherence to best practices, including naming conventions and consistent configuration styles, improving maintainability and readability.
&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Cloud Provider Support:&lt;/strong&gt; Delivers specialized linting for cloud providers such as AWS, Azure, and GCP, ensuring compatibility and optimal configurations.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Link&lt;/strong&gt;: &lt;a href="https://github.com/terraform-linters/tflint" rel="noopener noreferrer"&gt;https://github.com/terraform-linters/tflint&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Terratest‍
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Terratest&lt;/strong&gt; is a Go library developed by &lt;strong&gt;Gruntwork&lt;/strong&gt; for testing Infrastructure as Code. With first-class support for tools like Terraform, Packer, Docker, Kubernetes, and major cloud providers such as AWS, GCP, and Azure, Terratest enables developers to write automated tests to validate their infrastructure.&lt;/p&gt;

&lt;p&gt;By automating infrastructure testing, Terratest ensures that your Terraform configurations and other IaC implementations work as intended, giving you confidence in your deployments. Gruntwork provides an official guide for testing infrastructure code with Terratest in &lt;a href="https://terratest.gruntwork.io/#test-infrastructure-code-with-terratest-in-4-steps" rel="noopener noreferrer"&gt;&lt;strong&gt;four simple steps&lt;/strong&gt;&lt;/a&gt;, making it accessible and efficient for teams.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Automated Testing:&lt;/strong&gt; Seamlessly integrates into CI/CD pipelines to detect issues early in the development lifecycle, reducing risks and improving deployment stability.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Programmatic Test Definition:&lt;/strong&gt; Leverages the Go programming language for writing expressive, code-based test cases that interact directly with Terraform-managed resources.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Comprehensive Testing Coverage:&lt;/strong&gt; Supports a range of testing levels, from &lt;strong&gt;unit tests&lt;/strong&gt; and &lt;strong&gt;integration tests&lt;/strong&gt; to &lt;strong&gt;end-to-end scenarios&lt;/strong&gt;, ensuring a thorough validation of your infrastructure.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-Cloud Support:&lt;/strong&gt; Compatible with major cloud providers like AWS, Azure, and Google Cloud, enabling testing across diverse cloud platforms.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Infrastructure Testing Automation:&lt;/strong&gt; Automates testing for Terraform, streamlining the validation of cloud resources and configurations for greater consistency and efficiency.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Early Issue Detection:&lt;/strong&gt; Identifies potential problems before deployment, enhancing the reliability of your infrastructure and promoting stable, secure environments.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Broad Tool Compatibility:&lt;/strong&gt; Works with tools like Terraform, Docker, Kubernetes, Packer, and more, making it suitable for a wide range of IaC workflows.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Link&lt;/strong&gt;: &lt;a href="https://terratest.gruntwork.io" rel="noopener noreferrer"&gt;https://terratest.gruntwork.io&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Atlantis
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Atlantis&lt;/strong&gt; is a &lt;strong&gt;pull request automation tool&lt;/strong&gt; purpose-built for Terraform, designed to enhance collaboration and standardize workflows in infrastructure management. &lt;/p&gt;

&lt;p&gt;Supporting multiple version control systems (GitHub, Bitbucket, GitLab, Azure DevOps) and workflows for both Terraform and Terragrunt, Atlantis empowers teams to streamline their infrastructure workflows. Running as a Golang binary or Docker image, Atlantis can be deployed on platforms like VMs, Kubernetes, and Fargate. This self-hosted solution ensures that infrastructure changes are well-documented, reviewed, and executed consistently.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Integration with CI/CD Systems&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Automatically triggers Terraform commands (e.g., plan, apply) for pull requests.
&lt;/li&gt;
&lt;li&gt;Allows reviewers to make informed decisions by providing detailed outputs within the pull request.
&lt;/li&gt;
&lt;li&gt;Seamlessly integrates with CI/CD pipelines for automated testing and deployment of Terraform changes.
&lt;/li&gt;
&lt;li&gt;Posts the output of Terraform commands directly in pull requests.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Environment management&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Provides a locking mechanism to prevent conflicting operations during provisioning.
&lt;/li&gt;
&lt;li&gt;Ensures stability by stopping concurrent changes in shared environments.
&lt;/li&gt;
&lt;li&gt;Manages separate workspaces for environments like staging and production.
&lt;/li&gt;
&lt;li&gt;Ensures changes are tested in staging before being applied to production.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Scaling Infrastructure Management&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Simplifies the process of managing increasing infrastructure complexity.
&lt;/li&gt;
&lt;li&gt;Streamlines workflows for large-scale projects and multi-environment setups.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Self-Hosted Solution&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Runs entirely within your infrastructure, ensuring full control and security.
&lt;/li&gt;
&lt;li&gt;Protects sensitive credentials by executing Terraform operations in isolated environments.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Custom Workflows and Policies&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Supports custom workflows and policies for Terraform commands.
&lt;/li&gt;
&lt;li&gt;Enforces organizational standards, such as requiring approvals before applying changes.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Link&lt;/strong&gt;: &lt;a href="https://www.runatlantis.io" rel="noopener noreferrer"&gt;https://www.runatlantis.io&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Burrito
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Burrito&lt;/strong&gt; is a &lt;strong&gt;TACoS (Terraform Automation Collaboration Software)&lt;/strong&gt; Kubernetes Operator, purpose-built to manage and automate Infrastructure as Code within Kubernetes environments. Often described as the &lt;strong&gt;"ArgoCD for Infrastructure as Code",&lt;/strong&gt; Burrito brings powerful automation and collaboration features to Terraform workflows, aligning them with Kubernetes-native practices.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Burrito&lt;/strong&gt; is a tool for teams seeking to enhance efficiency, collaboration, and alignment between Terraform and Kubernetes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Continuous Planning and Applying:&lt;/strong&gt; Automates Terraform workflows with built-in PR/MR (Pull Request/Merge Request) integration, eliminating the need to manually configure CI/CD pipelines for Terraform. Burrito handles:

&lt;ul&gt;
&lt;li&gt;State lock management
&lt;/li&gt;
&lt;li&gt;Terraform versioning
&lt;/li&gt;
&lt;li&gt;Saving Terraform plan logs and results
&lt;/li&gt;
&lt;li&gt;Auditing tool integration (e.g., Checkov)
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Kubernetes-Native:&lt;/strong&gt; Operates as a Kubernetes Operator, seamlessly embedding Terraform automation into Kubernetes environments for a unified workflow.
&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;State Drift Detection and Resolution:&lt;/strong&gt; Continuously plans and applies Terraform code to ensure infrastructure remains in sync with its configuration. Detects and resolves state drift early, a critical feature for teams with multiple collaborators working on the same Terraform codebase.
&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Terraform State Navigation&lt;/strong&gt;: Features a curated UI for visualizing and navigating Terraform state, including resources and dependencies. This provides a clear understanding of the impact of changes before they are applied.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Link&lt;/strong&gt;: &lt;a href="https://github.com/padok-team/burrito" rel="noopener noreferrer"&gt;https://github.com/padok-team/burrito&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Terraform-docs
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;terraform-docs&lt;/strong&gt; is an essential utility for generating clear, comprehensive, and up-to-date documentation from &lt;strong&gt;OpenTofu&lt;/strong&gt;/&lt;strong&gt;Terraform&lt;/strong&gt; modules in a variety of output formats. It automatically extracts and formats information about inputs, outputs, providers, and resources, ensuring that infrastructure-as-code (IaC) projects remain well-documented and easy to maintain.&lt;/p&gt;

&lt;p&gt;By leveraging &lt;strong&gt;terraform-docs&lt;/strong&gt;, teams can maintain transparency, simplify collaboration, and improve the manageability of their IaC projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Automatic Documentation:&lt;/strong&gt; Automatically generates detailed and accurate documentation directly from Terraform modules, minimizing manual effort.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexible Output Formats:&lt;/strong&gt; Supports a wide range of output formats to suit different documentation needs, including: &lt;strong&gt;Asciidoc&lt;/strong&gt;, &lt;strong&gt;Markdown&lt;/strong&gt;, &lt;strong&gt;JSON, Pretty, TFVars&lt;/strong&gt; (HCL and JSON), &lt;strong&gt;TOML, XML, YAML&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Streamlined Workflows:&lt;/strong&gt; Simplifies the process of maintaining consistent and accessible Terraform documentation across teams and projects.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extensible:&lt;/strong&gt; Supports plugins, allowing users to build custom formatters to tailor documentation generation to specific requirements.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CI-Friendly:&lt;/strong&gt; Integrates seamlessly with CI/CD pipelines, enabling automated documentation generation in pull requests via GitHub Actions or other CI tools.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Link&lt;/strong&gt;: &lt;a href="https://terraform-docs.io" rel="noopener noreferrer"&gt;https://terraform-docs.io&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Terramate
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Terramate CLI&lt;/strong&gt; is an &lt;strong&gt;open-source Infrastructure as Code orchestration and code generation tool&lt;/strong&gt; designed for Terraform, OpenTofu, and Terragrunt. Terramate simplifies and automates IaC workflows, making them more efficient, scalable, and manageable.&lt;/p&gt;

&lt;p&gt;With &lt;strong&gt;Terramate&lt;/strong&gt;, you can:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Simplify complex codebases by breaking large state files into manageable stacks, reducing runtime and blast radius, while keeping configurations DRY with native code generation.
&lt;/li&gt;
&lt;li&gt;Automate and orchestrate Terraform, OpenTofu, and Terragrunt workflows in any CI/CD system using Pull Request automation, GitOps blueprints, and workflow tooling with zero-configuration orchestration and change detection.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Orchestration&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Run any command or workflow in stacks with unlimited concurrency.
&lt;/li&gt;
&lt;li&gt;Configurable workflows tailored to specific IaC needs.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Change Detection&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Automatically execute only the stacks with changes.
&lt;/li&gt;
&lt;li&gt;Detect changes in referenced Terraform/OpenTofu modules or Terragrunt dependencies for efficient updates.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Code Generation&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Generate HCL, JSON, and YAML code to maintain DRY principles.
&lt;/li&gt;
&lt;li&gt;Supports global variables and functions to streamline stack management.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Automation Blueprints&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Pre-configured GitOps workflows for GitHub, GitLab, Bitbucket, and Atlantis.
&lt;/li&gt;
&lt;li&gt;Enables Pull Request automation with plan previews, seamlessly integrating into your CI/CD pipelines.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Drift Management&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Detect and reconcile drift using scheduled workflows, ensuring infrastructure remains consistent with IaC definitions.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Observability and Insights&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Gain actionable insights and observability into stacks, deployments, and resources.
&lt;/li&gt;
&lt;li&gt;Provides enhanced visibility for informed decision-making.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Link&lt;/strong&gt;: &lt;a href="https://github.com/terramate-io/terramate" rel="noopener noreferrer"&gt;https://github.com/terramate-io/terramate&lt;/a&gt;  &lt;/p&gt;

&lt;h1&gt;
  
  
  Terratag
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Terratag&lt;/strong&gt; is a CLI tool that simplifies the process of applying tags or labels across an entire set of OpenTofu/Terraform files. The tools is developed by &lt;a href="https://www.env0.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;env0&lt;/strong&gt;&lt;/a&gt;, and designed to ensure consistent tagging for resources in AWS, GCP, and Azure environments, Terratag helps teams improve resource visibility, enforce tagging standards, and streamline cloud resource management.&lt;/p&gt;

&lt;p&gt;Terratag is a must-have tool for teams looking to improve resource visibility and enforce tagging standards efficiently across their Terraform-managed infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cross-Platform Tagging:&lt;/strong&gt; supports tagging and labeling for resources across AWS, GCP, and Azure.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automation-Friendly:&lt;/strong&gt; easily integrates into existing workflows and CI/CD pipelines, enabling automated tagging processes and reducing manual effort.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enhanced Resource Organization:&lt;/strong&gt; Promotes better organization and management of cloud resources through consistent and standardized tagging practices, improving visibility and traceability.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Link&lt;/strong&gt;: &lt;a href="https://github.com/env0/terratag" rel="noopener noreferrer"&gt;https://github.com/env0/terratag&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;That’s a quick overview of some of the most popular Terraform tools to help you manage your infrastructure management tasks effectively. As mentioned earlier, all the tools discussed in the article are also compatible with &lt;strong&gt;OpenTofu&lt;/strong&gt;, which is especially useful for users affected by license-related concerns.&lt;/p&gt;

&lt;p&gt;For staying up to date on new Terraform/OpenTofu tools, I recommend keeping watch of curated lists like as&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/shuaibiyy/awesome-tf" rel="noopener noreferrer"&gt;&lt;strong&gt;Awesome Terraform&lt;/strong&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://awesome-opentofu.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;Awesome OpenTofu&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I hope these tools will help you improve collaboration, enhance security, simplify processes, and make your Terraform/OpenTofu journey smoother and more efficient. &lt;strong&gt;Good luck!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>newyearchallenge</category>
      <category>future</category>
      <category>terraform</category>
    </item>
    <item>
      <title>Как настроить зеркало реестров для OpenTofu и Terraform</title>
      <dc:creator>kvendingoldo</dc:creator>
      <pubDate>Thu, 26 Sep 2024 22:56:45 +0000</pubDate>
      <link>https://forem.com/kvendingoldo/kak-nastroit-zierkalo-rieiestrov-dlia-opentofu-i-terraform-277k</link>
      <guid>https://forem.com/kvendingoldo/kak-nastroit-zierkalo-rieiestrov-dlia-opentofu-i-terraform-277k</guid>
      <description>&lt;p&gt;В конце августа проект OpenTofu сначала заблокировал доступ к своему реестру &lt;a href="https://registry.opentofu.org" rel="noopener noreferrer"&gt;https://registry.opentofu.org&lt;/a&gt; для пользователей из России, а затем без ясного объяснения причин удалил несколько российских провайдеров (PR#817, PR#839). Это привело к тому, что даже зеркалирование официального реестра стало бессмысленным и сломало выполнение команды &lt;code&gt;tofu init&lt;/code&gt; для всех, кто только что смигрировал с Terraform на OpenTofu.&lt;/p&gt;

&lt;p&gt;Примечательно, что HashiCorp, который заблокировал доступ к реестру Terraform для российских пользователей еще в 2022 году, не пошел на столь радикальные меры и не удалял российских провайдеров из самого реестра.&lt;/p&gt;

&lt;p&gt;В статье мы рассмотрим варианты обхода блокировки реестра провайдеров как для пользователей Terraform, так и для OpenTofu.&lt;/p&gt;

&lt;h2&gt;
  
  
  Обход блокировки registry.terraform.io
&lt;/h2&gt;

&lt;p&gt;В случае Terraform, обход блокировки осуществляется через конфигурацию стандартного зеркала для реестра провайдеров. Для этого нужно создать файл &lt;code&gt;.terraformrc&lt;/code&gt; в домашнем каталоге вашей операционной системы.&lt;/p&gt;

&lt;p&gt;В самом файле нужно сконфигурировать зеркало следующим образом:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;provider_installation {
  network_mirror {
    url     = "https://terraform-mirror.yandexcloud.net/"
    include = ["registry.terraform.io/*/*"]
  }
  direct {
    exclude = ["registry.terraform.io/*/*"]
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;После этого &lt;code&gt;terraform init&lt;/code&gt; снова будет выполняться без проблем.&lt;/p&gt;

&lt;h2&gt;
  
  
  Обход блокировки registry.opentofu.org
&lt;/h2&gt;

&lt;p&gt;Ситуация с OpenTofu является более сложным, чем с Terraform. Как уже упоминалось ранее, OpenTofu физически удалил метаинформацию о провайдерах из своего реестра. Это означает, что даже настроенное зеркало не сможет помочь при использовании свежих версий плагинов, которые не существовали на момент блокировки.&lt;/p&gt;

&lt;p&gt;По умолчанию OpenTofu использует реестр registry.opentofu.org, если он не указан явно. К счастью, плагины для OpenTofu и Terraform в настоящее время взаимосовместимы, что дает возможность использовать реестр registry.terraform.io с заранее настроенным зеркалом. Для этого достаточно создать в домашнем каталоге вашей файловой системы файл &lt;code&gt;.tofurc&lt;/code&gt; со следующим содержанием:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;provider_installation {
  network_mirror {
    url     = "https://terraform-mirror.yandexcloud.net/"
    include = ["registry.terraform.io/*/*"]
  }
  direct {
    exclude = ["registry.terraform.io/*/*"]
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;После, измените блок &lt;code&gt;terraform&lt;/code&gt; внутри вашего HCL кода. Для каждого описанного провайдера в параметр source необходимо добавить префикс &lt;code&gt;registry.terraform.io/&lt;/code&gt; . Пример блока для конфигурации OpenTofu:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform {
  required_version = "1.8.0"
  required_providers {
    yandex = {
      source  = "registry.terraform.io/yandex-cloud/yandex"
      version = "0.129.0"
    }
    tls = {
      source  = "registry.terraform.io/hashicorp/tls"
      version = "4.0.4"
    }
    random = {
      source  = "registry.terraform.io/hashicorp/random"
      version = "3.4.3"
    }
    null = {
      source  = "registry.terraform.io/hashicorp/null"
      version = "3.2.2"
    }
    aws = {
      source  = "registry.terraform.io/hashicorp/aws"
      version = "5.45.0"
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Это изменение принудительно заставит OpenTofu использовать реестр Terraform через заранее настроенное зеркало.&lt;/p&gt;

&lt;h2&gt;
  
  
  Список доступных зеркал
&lt;/h2&gt;

&lt;p&gt;Как вы, возможно, заметили, в примерах я использовал зеркало &lt;code&gt;terraform-mirror.yandexcloud.net&lt;/code&gt; от компании Яндекс. Это зеркало не отличается высокой стабильностью и частотой обновлений, поэтому, помимо него, можно воспользоваться следующими альтернативами:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://registry.comcloud.xyz/" rel="noopener noreferrer"&gt;https://registry.comcloud.xyz/&lt;/a&gt; (также доступен как &lt;a href="https://registry.nationalcdn.ru/" rel="noopener noreferrer"&gt;https://registry.nationalcdn.ru/&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://tf.org.ru/" rel="noopener noreferrer"&gt;https://tf.org.ru/&lt;/a&gt; (nm.tf.org.ru)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://terraform-mirror.mcs.mail.ru/" rel="noopener noreferrer"&gt;https://terraform-mirror.mcs.mail.ru/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://terraform.cloud.ru/" rel="noopener noreferrer"&gt;https://terraform.cloud.ru/&lt;/a&gt; (документация)&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Tenv v2.0: The Importance of Explicit Behavior for Version Manager</title>
      <dc:creator>kvendingoldo</dc:creator>
      <pubDate>Tue, 02 Jul 2024 10:46:07 +0000</pubDate>
      <link>https://forem.com/kvendingoldo/tenv-v20-the-importance-of-explicit-behavior-for-version-manager-3gh5</link>
      <guid>https://forem.com/kvendingoldo/tenv-v20-the-importance-of-explicit-behavior-for-version-manager-3gh5</guid>
      <description>&lt;p&gt;The explicit behavior of &lt;a href="https://en.wikipedia.org/wiki/Infrastructure_as_code"&gt;IAC&lt;/a&gt; version managers is quite crucial. It is especially critical in the realm of Terraform and OpenTofu because tool upgrades might destroy or corrupt all managed infrastructure. To protect users from unexpected updates, all version managers have to work clearly and without any internal wizardry that cannot be explained without a deep dive into the sources.&lt;/p&gt;

&lt;p&gt;Tenv is a versatile version manager for &lt;a href="https://opentofu.org/"&gt;OpenTofu&lt;/a&gt;, &lt;a href="https://www.terraform.io/"&gt;Terraform&lt;/a&gt;, &lt;a href="https://terragrunt.gruntwork.io/"&gt;Terragrunt&lt;/a&gt;, and &lt;a href="https://atmos.tools/"&gt;Atmos&lt;/a&gt;, written in Go and developed by tofuutils team. This tool simplifies the complexity of handling different versions of these powerful tools, ensuring developers and DevOps professionals can focus on what matters most — building and deploying efficiently. Tenv is a successor of &lt;a href="https://github.com/tofuutils/tofuenv"&gt;tofuenv&lt;/a&gt; and &lt;a href="https://github.com/tfutils/tfenv"&gt;tfenv&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the process of tenv development, our team discovered quite an unpleasant surprise with Terragrunt and tenv, which may have created serious issues. On a fresh install of the Linux system, when one of our users attempted to run Terragrunt, the execution ended up utilizing OpenTofu instead of Terraform, with no warnings in advance. In the production environment, it might cause serious Terraform state corruption, but luckily it was a testing environment. Before we look at the root cause of this issue, I need to explain how the tenv works.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/tofuutils/tenv"&gt;Tenv&lt;/a&gt; manages all tools by wrapping them in an additional binary that serves as a proxy for the original tool. It means you can't install Terraform or OpenTofu on an ordinary Linux machine alongside tenv (except &lt;a href="https://nixos.org/"&gt;NixOS&lt;/a&gt; case). At our tool, we supply a binary with the same name as the tool (Terraform / OpenTofu / Terragrunt / Atmos), within which we implement the proxy pattern. It was required since it simplifies version management and allows us to add new capabilities to automatic version discovery and installation handling.&lt;/p&gt;

&lt;p&gt;So, knowing that tenv is based on a downstream proxy architecture, we are ready to return to the problem. Why was our user's execution performed using OpenTofu rather than Terraform? The answer has two parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Terragrunt started to use OpenTofu as the default IAC tool, however, this was not a major release; instead, it was provided as a patch and users didn't expect to have any differences in the behavior. The original problem may be found &lt;a href="https://github.com/gruntwork-io/terragrunt/issues/3172"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;When Terragrunt called OpenTofu in the new default behavior, it used tenv's proxy to check the required version of OpenTofu and install it automatically.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Although the &lt;code&gt;TERRAGRUNT_TFPATH&lt;/code&gt; setting might control the behavior, users were unaware of the Terragrunt breaking change and were surprised to see OpenTotu at the end of execution. But why did OpenTofu execute if users did not have it in their system? Here we are dealing with the second issue that has arisen. At the start of tenv development, we replicated many features from the tfenv tool. One of these features was automatic tool installation, which is controlled by the &lt;code&gt;TFENV_AUTO_INSTALL&lt;/code&gt; environment variable and is enabled by default. Tenv also has the &lt;code&gt;TENV_AUTO_INSTALL&lt;/code&gt; variable, which is also was true by default unless the mentioned case hasn't been discovered.&lt;/p&gt;

&lt;p&gt;Users who used Terraform / OpenTofu without Terragrunt via tenv may have encountered the auto-install when, for example, switching the version of the tool with the following command:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;tenv tf use 1.5.3&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tenv tofu use 1.6.1&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The use command installed the required version even if it wasn’t present in the operation system locally.&lt;/p&gt;

&lt;p&gt;After a brief GitHub &lt;a href="https://github.com/orgs/tofuutils/discussions/4"&gt;discussion&lt;/a&gt;, our team decided to disable auto-install by default and release this minor change as a new, major version of tenv. We made no major changes to the program, did not update the framework of the language version, and only updated the default variable, deciding that users should understand that one of the most often utilised and crucial behaviors had changed.&lt;/p&gt;

&lt;p&gt;It's interesting that during the discussion, we disagreed on whether users should read the &lt;strong&gt;README.md&lt;/strong&gt; or documentation, but whether you like it or not, it's true that people don't read the docs unless they're in difficulty. As the tofuutils team, we cannot accept the possibility that a user will mistakenly utilize OpenTofu in a real-world production environment and break the state or the cloud environment.&lt;/p&gt;

&lt;p&gt;Finally, I'd like to highlight a few points once more:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Implement intuitive behavior in your tool.&lt;/li&gt;
&lt;li&gt;Consider user experience and keep in mind that many people don't read manuals.&lt;/li&gt;
&lt;li&gt;Do not worry about releasing a major version if you made the breaking change.&lt;/li&gt;
&lt;li&gt;In programming, explicit is preferable to implicit, especially when dealing with state-sensitive tools.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>infrastructureascode</category>
      <category>terraform</category>
      <category>softwaredevelopment</category>
      <category>opentofu</category>
    </item>
    <item>
      <title>How to Manage Terraform Versions</title>
      <dc:creator>kvendingoldo</dc:creator>
      <pubDate>Mon, 17 Jun 2024 20:32:07 +0000</pubDate>
      <link>https://forem.com/kvendingoldo/how-to-manage-terraform-versions-2e2l</link>
      <guid>https://forem.com/kvendingoldo/how-to-manage-terraform-versions-2e2l</guid>
      <description>&lt;p&gt;The simplest method for handling Terraform versions is to &lt;a href="https://github.com/tofuutils/tenv"&gt;tenv&lt;/a&gt;. &lt;a href="https://github.com/tofuutils/tenv"&gt;tenv&lt;/a&gt; is a version manager for Terraform, OpenTofu, Terragrunt, and Atmos, written in Go. This versatile version manager simplifies the complexity of version control, helping to avoid spending time on IaC tools’ version management and ensuring developers and DevOps can focus on what is important the most - crafting innovative products and driving business value.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why do I need Terraform version manager?
&lt;/h2&gt;

&lt;p&gt;Managing a single Terraform project makes installing, upgrading, or switching to tools like OpenTofu straightforward. However, handling multiple projects with different Terraform versions can be challenging. Regular upgrades and tool switches require careful coordination to maintain functionality and stability across projects. The list of key challenges:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Version Compatibility: Different projects may need specific Terraform versions, which might not be backward compatible.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dependency Management: Dependencies for each project must match the Terraform version of that project.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Environment Consistency: It becomes challenging to maintain consistency throughout the development, staging, and production environments.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tooling and Integration: Various Terraform versions may require modifications to CI/CD pipelines and integrations.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;tenv&lt;/strong&gt; terraform version manager cover all described challenged under the hood in a single binary that helps to manage Terraform versions transparently.&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 tenv installation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  MacOS
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;brew install tenv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Windows
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;choco install tenv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Linux
&lt;/h3&gt;

&lt;p&gt;For Linux, you can install tenv version manager via packaged binaries (.deb, .rpm, .apk, pkg.tar.zst , .zip or .tar.gz format) by visiting the release page or by apk/yay/snap/nix package managers. To get more information about the Linux tenv installation, check &lt;a href="https://github.com/tofuutils/tenv/blob/main/README.md"&gt;README.md&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Manage Terraform versions via tenv version manager
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F44cifcpwr84w47lh0dvd.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F44cifcpwr84w47lh0dvd.jpg" alt="manage terraform version" width="500" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you have tenv version manager installed, you can use it to install specific versions of Terraform. To install Terraform, do the following steps:&lt;/p&gt;

&lt;p&gt;Open a terminal, go to the directory with Terraform code (if you have any) and execute the following command to install terraform version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tenv tf install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Based on .tf code, tenv version manager automatically detect and install the necessary version of Terraform.  If no version detected in sources, the latest version will be installed. &lt;/p&gt;

&lt;p&gt;On the other hand, if necessary, a specific Terraform version can also be installed. Let's try to install Terraform 1.8.5:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tenv tf install 1.8.5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The install command also supports version constraints such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;latest&lt;/code&gt; - the latest available stable version&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;latest-pre&lt;/code&gt; - the latest available version, including unstable ones&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;latest-allowed&lt;/code&gt; or min-required - &lt;a href="https://github.com/tofuutils/tenv"&gt;tenv&lt;/a&gt; will scan your Terraform files to detect which version is maximally allowed or minimally required. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, verify the Terraform version. To do it, use the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. No symlinks, additional commands or download required. To read about more installation cases for Terraform, you can check the official &lt;a href="https://github.com/tofuutils/tenv/blob/main/README.md"&gt;README.md&lt;/a&gt; file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Support Us, Contact Us
&lt;/h2&gt;

&lt;p&gt;If you like this post, support us, download tenv, try to use it and give us feedback in our official &lt;a href="https://github.com/tofuutils/tenv/discussions"&gt;discussions channel&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Press a star 🌟 &lt;a href="https://github.com/tofuutils/tenv"&gt;on GitHub&lt;/a&gt; if you like the tenv version manager.&lt;/p&gt;

</description>
      <category>terraform</category>
      <category>opentofu</category>
      <category>tutorial</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
