TutorialsTerraform › main.tf

Terraform Tutorial · File 4 of 9

main.tf

The foundation every other file builds on. Computes a handful of shared names once, and creates the resource group — the labeled Azure folder that every resource this project creates gets placed inside.

Codey the Sr Developer, standing with a pointer, ready to walk through the guide
Blocks → locals · resource Resources created → 1 (resource group) Used by → every other .tf file

Purpose of this file

Compute shared naming values once, and create the resource group that holds every other resource in this project.

Codey pointing to the right
the foundation everything else sits on

In Azure, a resource group is a container used to organize related resources and manage them as one unit — deleting a resource group deletes everything inside it. Every resource this project creates (the database, the web app, the deployment identity) belongs to the one resource group defined here, which is what makes a full teardown with terraform destroy clean and complete.

The full file code sample

terraform/main.tflocals {
  prefix       = "expeditors-${var.user_name}-metals"
  db_user      = "metalsadmin"
  db_name      = "metals"
  oidc_subject = coalesce(var.github_federated_subject, "repo:${var.github_subject_repository}:environment:${replace(var.github_environment, ":", "%3A")}")
}

resource "azurerm_resource_group" "metals" {
  name     = "${local.prefix}-rg"
  location = var.location
}

The locals block shared values

A locals block computes named values once, so the rest of the project can reuse them instead of repeating the same expression — and risking a typo that makes two “identical” values quietly drift apart.

local.prefixthe naming backbone
prefix = "expeditors-${var.user_name}-metals"

Builds a string like "expeditors-dzierzon-metals" by interpolating var.user_name into the middle of a fixed template using ${...} syntax. Every other file appends its own suffix to this same prefix — -rg for the resource group here, -pg for the database, -api for the web app — so all resources in one deployment are instantly recognizable as belonging together, and two different people running this project never collide on the same resource names.

local.db_user and local.db_namefixed values

Plain constants — the PostgreSQL administrator username ("metalsadmin") and database name ("metals"). They're declared once here rather than in database.tf because app_service.tf also needs both values, to build the API's database connection string.

local.oidc_subjecta computed identity string
oidc_subject = coalesce(
  var.github_federated_subject,
  "repo:${var.github_subject_repository}:environment:${replace(var.github_environment, ":", "%3A")}"
)

This builds the exact text string GitHub Actions must present to prove its identity (used in github_oidc.tf). Reading it from the inside out: replace(...) URL-encodes any colon inside the environment name, then the surrounding string stitches together the fixed "repo:" and ":environment:" text with the repository and environment values. coalesce() picks the first argument that isn't null — so if var.github_federated_subject was explicitly set, it's used as-is instead; otherwise the computed value is used.

The resource group the first real resource

resource "azurerm_resource_group" "metals"example
resource "azurerm_resource_group" "metals" {
  name     = "${local.prefix}-rg"
  location = var.location
}
  • resource — the keyword that tells Terraform this block describes something to actually create.
  • "azurerm_resource_group" — the Azure resource type, defined by the azurerm provider.
  • "metals" — the local name other blocks use to refer to this resource inside Terraform, as azurerm_resource_group.metals. It never appears in Azure itself.
  • name — the actual name Azure will show, built from local.prefix plus -rg.
  • location — which Azure region, taken straight from var.location.

Every other resource in this project (see database.tf, app_service.tf, and github_oidc.tf) references azurerm_resource_group.metals.name and .location rather than repeating local.prefix or var.location directly — one more example of defining a value once and reusing it everywhere.

The manual equivalent of everything on this page — and of database.tf and app_service.tf together — is az_create_resources in the Manual Deployment tutorial: the same resources, created one az command at a time.

Key terms for beginners

Resource group
An Azure container for organizing related resources and managing their lifecycle together — deleting the group deletes everything inside it.
Local value
A named expression computed once inside a locals block and reused elsewhere as local.<name>, similar in spirit to a variable but computed rather than supplied as input.
String interpolation
Embedding a value inside a string with ${...}, like "expeditors-${var.user_name}-metals", instead of concatenating pieces manually.
Resource type vs. local name
A resource block always has two labels: the Azure resource type (fixed by the provider) and a local name you choose, used only within Terraform to reference that resource elsewhere.
Codey giving a thumbs up

The resource group is down — next, the database everything else depends on.