linuxlab.io
Tutorials▾
  • Linux & networking
    File system, processes, TCP/IP, BGP and OSPF
    →
  • Terraform & IaC
    HCL, state, plan/apply on a LocalStack sandbox
    →
  • Git & GitHub
    Object model, plumbing, branching, GitHub Actions
    →
All tutorials →
PricingAboutSign inCreate account
/
Intro
Lessons
Footer
linuxlab-TutorialsPricingAboutPrivacy & cookies
Copyright © 2026 LinuxLab. All rights reserved.
linuxlab.io
Tutorials▾
  • Linux & networking
    File system, processes, TCP/IP, BGP and OSPF
    →
  • Terraform & IaC
    HCL, state, plan/apply on a LocalStack sandbox
    →
  • Git & GitHub
    Object model, plumbing, branching, GitHub Actions
    →
All tutorials →
PricingAboutSign inCreate account
/
  • Introduction
  • Lessons
  • How it works
  • Knowledge base
  • Cheat sheet
  • Capstone
  • Interview prep
home/terraform/kb/Variables & outputs/tf-locals

kb/variables ── Variables & outputs ── beginner

locals: computed internal names

locals is a block with names visible only inside HCL (not input, not output). Useful for DRY: compute a common prefix or tag set once, then use it everywhere via local.x. Do not confuse with variable (input) and output (output).

view as markdown

variable vs locals vs output

Three related but distinct things:

  • variable, input. The value comes from outside (CLI, .tfvars, env).
  • locals, internal. Computed from other values; visible only within this HCL.
  • output, output. The value is visible after apply or to other modules.

If a value comes from outside, use variable. If you use it in several places after computing it, use locals. If you want to expose it externally, use output.

Basic syntax

hcl
variable "env" {
  type    = string
  default = "dev"
}
variable "app_name" {
  type    = string
  default = "my-app"
}
locals {
  name_prefix = "${var.app_name}-${var.env}"
  common_tags = {
    Project     = var.app_name
    Environment = var.env
    ManagedBy   = "terraform"
  }
}
resource "aws_s3_bucket" "logs" {
  bucket = "${local.name_prefix}-logs"
  tags   = local.common_tags
}
resource "aws_s3_bucket" "data" {
  bucket = "${local.name_prefix}-data"
  tags   = local.common_tags
}

Each resource uses the shared prefix and shared tags without repeating itself.

The reference is local.name (no s!). The declaration is locals { ... } (with s).

Locals can reference other locals

hcl
locals {
  base_name   = "${var.app_name}-${var.env}"
  bucket_name = "${local.base_name}-bucket"
  log_prefix  = "${local.bucket_name}/logs/"
}

The chain is resolved automatically. Terraform builds a graph and resolves dependencies.

Locals can hold complex expressions

hcl
locals {
  enable_https = var.env == "prod" || var.env == "staging"
  azs = data.aws_availability_zones.available.names
  instance_count = var.env == "prod" ? 3 : 1
  subnet_cidrs = [
    for i in range(local.instance_count) :
    cidrsubnet(var.vpc_cidr, 8, i)
  ]
}

Conditions, loops, functions, anything allowed in HCL expressions is fair game. See tf-conditional-expression and tf-functions-collection.

Multiple locals blocks are fine

hcl
# general.tf
locals {
  name_prefix = "${var.app_name}-${var.env}"
}
# tags.tf
locals {
  common_tags = {
    Project     = var.app_name
    Environment = var.env
  }
}
# network.tf
locals {
  public_subnet_count = 3
}

A project can have as many locals blocks as needed. Terraform merges them into a single local.* namespace. This is convenient for splitting definitions across files.

One constraint: names across different locals blocks must not collide. local.foo = "a" in one file and local.foo = "b" in another is a validation error.

When to use locals

Good cases:

  • Shared name prefix. ${local.name_prefix}-bucket, ${local.name_prefix}-role, and so on.
  • Shared tags. One map of project tags applied to every resource.
  • Computations from multiple variables. Building an ARN from env and region, for example.
  • Conditional logic. local.enable_https = var.env == "prod".
  • Aliases. local.azs = data.aws_availability_zones.available.names as a short name for a long expression.

When you do not need locals:

  • If a value is used only once, write it inline.
  • If the value comes from outside, it is a variable.

Pitfalls

  • Locals are not for secrets. They are stored in state in plain text, with no sensitive marker (sensitive exists only on variable and output).

  • Locals cannot reference themselves. local.x = local.x + 1 is an error. Terraform is not a programming language with iterative state.

  • Do not overuse them. If half the HCL file is a locals block, the code becomes harder to follow. That is a sign some values belong in variables instead.

  • local vs locals: a common mix-up. The declaration is locals { ... } (plural). The reference is local.x (singular, no s). Never write locals.x with an s.

  • Locals are not available in .tfvars. Only variables go in .tfvars. Locals are computed inside HCL.

  • Renaming a local: does it appear in the diff? No. Locals are not stored in state, only in expressions. Change the name, Terraform recomputes all references, and nothing is sent to the cloud (as long as the resulting value stays the same).

§ команды

bash
terraform console

Interactive REPL: use it to check the value of local.x in expressions. Handy for debugging complex expressions.

bash
terraform plan

The plan output shows the final values that locals resolved to, which lets you confirm the prefix was assembled correctly.

§ см. также

  • tf-variableThe variable block: input to your configurationA variable is a parameter that receives its value from outside the configuration (CLI, environment variable, .tfvars file). You declare it in HCL with type, default, description, and validation, then reference it as var.name. Variables remove hardcoded values and let one HCL configuration serve multiple environments.
  • tf-outputThe output block: what Terraform exposes to the outsideAn output is a value that Terraform displays after apply and stores in state. Use it to (a) show the user the ID or ARN of a created resource, (b) pass values between modules, or (c) feed values to scripts via `terraform output -raw`.
  • tf-referencesReferences in HCL: how to read aws_s3_bucket.demo.bucketAny value in HCL is reachable through an address: var.x, local.x, aws_s3_bucket.demo.arn, module.net.vpc_id, data.aws_region.current.name. Knowing this syntax is half of your productivity in Terraform.
  • tf-interpolation${...}: substituting values into strings${expression} inside a string substitutes the value of that expression. ${var.env}, ${aws_s3_bucket.demo.id}. When the expression is the entire value of an argument (no surrounding string), modern HCL lets you write it without ${...}.
Footer
linuxlab-
Copyright © 2026 LinuxLab. All rights reserved.
Tutorials
Pricing
About
Privacy & cookies