DEV Community

Cover image for My First Real Terraform Project, Two Environments, One Storage Account, And A Few Lessons I Did Not See Coming
Ipadeola Taiwo
Ipadeola Taiwo

Posted on

My First Real Terraform Project, Two Environments, One Storage Account, And A Few Lessons I Did Not See Coming

A few days ago I said I was starting Infrastructure as Code. Today I actually sat down and wrote my first proper Terraform project, and I want to walk you through exactly what I built, what confused me at first, and what broke along the way, because the broken parts taught me more than the parts that just worked.

What I Set Out To Build

The idea was simple on paper. A small payments project needs two separate environments, one for development and one for staging, each represented by its own resource group in Azure. On top of that, the development environment needed a storage account with a blob container inside it, the kind of setup you would actually see on a real team, where dev and staging are kept apart on purpose.

Nothing here was complicated in terms of what Azure resources were involved. What made it worth doing was doing it the Terraform way, writing it once as code, and letting Terraform figure out how to create everything in the right order.

The Part That Actually Confused Me At First, Variables

Before I even got to writing resources, I had to deal with variables, and this is the part I really want to talk about, because it caught me off guard in a way I was not expecting.

If you come from a general programming background, even a light one, you are used to variables needing to be exported and imported somehow. You define something in one file, and if you want to use it somewhere else, you usually have to explicitly export it, then import it wherever you need it. That is just how most languages work.

So naturally, when I created a separate file just for my variables, my first thought was, how do I export this so my other files can actually see it. I genuinely sat there for a moment trying to figure out the Terraform equivalent of an export statement.

Turns out, there isn't one, and there does not need to be.

In Terraform, every file inside the same working directory is automatically part of the same configuration. It does not matter if your variables live in variables.tf, your resources live in main.tf, and your outputs live in outputs.tf. Terraform reads every .tf file in that folder as one combined configuration. Once a variable is declared, anywhere in that folder, you can reference it anywhere else in that same folder, just by calling var.whatever_you_named_it.

No import statement. No export keyword. No file path linking one file to another. The folder itself is the boundary, not the individual file.

Once that clicked, it actually made the whole language feel simpler than I expected. Splitting files apart in Terraform is purely for organization and readability, not because the tool needs you to wire files together the way you would in something like JavaScript or Python.

Setting The Foundation, Provider And Variables

Every Terraform project needs to know which provider it is talking to, in this case Azure, and which version of that provider to use. I pinned mine to a specific version rather than leaving it open ended, so the project behaves the same way every time it runs, regardless of what the latest provider release happens to be on a given day.

Then came the three variables that would drive the whole project, the project name, the Azure region, and an owner tag, each with a sensible default so I would not have to retype the same values across every resource.

Building The Actual Infrastructure

With the foundation in place, I defined four resources. Two resource groups, one for dev and one for staging, a storage account sitting inside the dev resource group, and a storage container sitting inside that storage account.

What I liked here is how naturally Terraform expresses the relationship between resources. I did not have to manually tell the storage account which resource group it belonged to using some ID I copied from somewhere. I just referenced the resource group resource directly, and Terraform understood the dependency and the order to create things in, entirely on its own.

Where It Actually Broke, And What Each Break Taught Me

I want to be upfront about this part, because I think it is the most useful part of this whole post. Nothing here worked perfectly on the first attempt, and I think that is normal, and worth documenting honestly rather than pretending it all went smoothly.

The first error showed up right at terraform init. Terraform told me it could not find a provider called hashcorp/azurerm. I stared at that for longer than I want to admit before I noticed the actual issue, the error was missing a letter. The real provider is hashicorp, not hashcorp. One missing letter somewhere in my configuration was enough to send Terraform looking for a provider that does not exist. Fixing the spelling and running init again solved it immediately.

The second error happened during terraform plan. This one looked scarier than it actually was. Terraform said it ran into a problem while trying to automatically register an Azure resource provider called Microsoft.Kusto, something I was not even using directly, and the process got interrupted. I simply ran the plan again, and it went through cleanly the second time. Turns out Terraform tries to register a whole set of Azure resource providers behind the scenes the first time you use certain resource types, and on a lighter subscription that step can be slow enough to get cut off.

The third error was the most straightforward, but the easiest to overlook. Azure rejected my storage account name because it contained a hyphen. Storage account names in Azure have to be lowercase letters and numbers only, no hyphens allowed, which is different from resource group names, where hyphens are perfectly fine. I had used the same naming pattern across both without realizing storage accounts play by different rules. Removing the hyphen fixed it right away.

None of these were difficult once I understood what was actually happening, but each one forced me to slow down and actually read the error message properly instead of assuming I already knew what went wrong.

Confirming It Actually Worked

Once everything applied successfully, I did not just trust the terminal output. I went into the Azure Portal directly and checked every piece, both resource groups showing up correctly under the right region, the storage account sitting inside the correct resource group, and the container present inside that storage account with the access level I had configured. Seeing it match exactly what Terraform said it created was a genuinely satisfying moment.

Tearing It Down

Since this was a lab and not something meant to run permanently, I finished by running a full destroy, and watched Terraform take everything down in the correct reverse order, the container first, then the storage account, then both resource groups, all cleanly removed with a single command and a typed confirmation.

What This Project Actually Taught Me

Beyond the individual errors, the biggest shift for me was realizing how much Terraform handles on its own once you describe what you want clearly. I did not have to think about ordering. I did not have to manually track dependencies between resources. I described the end state, and Terraform figured out how to get there, and how to safely undo it later.

I also learned something small but important while wrapping up, my working folder had files sitting there that should never end up in version control, the local state files and the provider cache directory in particular, since state files can end up holding sensitive information about the resources they track. That is going straight into a .gitignore before this project touches GitHub properly.

This is only the first project in what I expect will be a much longer run with Terraform. If you have worked with it longer than I have, and there is something you wish someone had told you this early on, I would genuinely like to hear it in the comments.

Below is link to my github repo

Understand the 4 Core Files

Every Terraform project has this structure:

azure-terraform-lab/ ├── main.tf # Your resources live here ├── variables.tf # Input variables (reusable values) ├── outputs.tf # What Terraform prints after running └── providers.tf # Which cloud you are connecting to

Terraform command to use daily

1. Download the Azure provider plugin

terraform init

2. Preview what Terraform WILL do — never skip this

terraform plan

3. Actually build the infrastructure

terraform apply

4. Destroy everything safely when done

terraform destroy




Top comments (0)