HomeRoadmapsTerraform Day 2
DevOps Track Β· Day 2 Parameterization Β· 20 min

HCL Variables & Outputs
DevOps Terraform Sprint β€” Day 2

Parameterize local infrastructure using variables.tf, outputs.tf, and terraform.tfvars files for environment flexibility

πŸ› οΈ Tooling: Terraform 1.5+ & Docker🎭 Role: DevOps & Infrastructure Quality Engineer
TerraformHCLVariablesOutputstfvars
About Today's 20-Minute Lab

On Day 1, we hardcoded container names and port numbers in main.tf. Hardcoding values makes infrastructure rigid and prone to duplication. Today on Day 2, you will decouple configuration from execution by creating input variables (variables.tf), environment override files (terraform.tfvars), and structured outputs (outputs.tf).

🎬 Day 2 Video Walkthrough
⚑In a rush? Watch a quick knowledge bit in under 1 minute on today's lesson!
Watch Reel πŸ“Έ
πŸ“¦Sample Codebase & Working Solution (Day 2)Available Now
View on GitHub

The official reference codebase for Day 2 is hosted in our private GitHub repository. Clone the repository and navigate to the day-2-variables directory to run the working solution.

Git Clone β€” Private Monorepo Solution
git clone https://github.com/letstrnsfrm-ai/devops-terraform-roadmap.git
cd devops-terraform-roadmap/day-2-variables
1

Input Variable Declarations (variables.tf)

GOAL
Define strongly typed input variables with default values, validation rules, and descriptions.
VARIABLES.TF
Create a file named variables.tf in your Day 2 lab folder:
HCL β€” variables.tf
variable "container_name" {
  type        = string
  default     = "qe_devops_web_app"
  description = "Name of the local Docker container"
}

variable "external_port" {
  type        = number
  default     = 8081
  description = "Host port bound to the web container"

  validation {
    condition     = var.external_port >= 1024 && var.external_port <= 65535
    error_message = "The external_port must be a non-privileged port between 1024 and 65535."
  }
}

variable "image_tag" {
  type        = string
  default     = "alpine"
  description = "Nginx image tag tag to deploy"
}
🏭Production Context & Enterprise Real-World Implementation
πŸ’‘ Why We Are Doing This: Strongly typed input variables with built-in validation rules prevent misconfigurations (such as assigning privileged system ports or invalid instance types) before plan execution.
🏒 Real-World Production Usecase: Financial cloud architectures (like Stripe or Robinhood) use validation rules on CIDR blocks and instance sizes to prevent developers from accidentally deploying unapproved instance types in production.
βš™οΈ How Implemented in Production: Production HCL code uses custom validation blocks to enforce strict naming conventions (e.g. `can(regex('^prod-', var.env))`) and allowable numeric ranges across all modules.
2

Refactored Blueprint & Output Declarations

GOAL
Update main.tf to reference your input variables and declare structured outputs in outputs.tf.
MAIN.TF
Update main.tf to consume var.* references:
HCL β€” main.tf
terraform {
  required_providers {
    docker = {
      source  = "kreuzwerker/docker"
      version = "~> 3.0.1"
    }
  }
}

provider "docker" {}

resource "docker_image" "app_image" {
  name         = "nginx:${var.image_tag}"
  keep_locally = false
}

resource "docker_container" "app_container" {
  image = docker_image.app_image.image_id
  name  = var.container_name

  ports {
    internal = 80
    external = var.external_port
  }
}
OUTPUTS.TF
Create outputs.tf to expose container connection parameters:
HCL β€” outputs.tf
output "container_id" {
  value       = docker_container.app_container.id
  description = "Unique ID of the provisioned Docker container"
}

output "web_url" {
  value       = "http://localhost:${var.external_port}"
  description = "HTTP URL endpoint to access the running web service"
}
🏭Production Context & Enterprise Real-World Implementation
πŸ’‘ Why We Are Doing This: Outputs expose provisioned resource identifiers and endpoints to downstream automation pipelines, CI test runners, and monitoring systems.
🏒 Real-World Production Usecase: Microservice platforms (like Spotify or Slack) export database connection URIs, Kubernetes ingress hostnames, and load balancer DNS names via Terraform outputs to trigger post-deployment verification jobs.
βš™οΈ How Implemented in Production: In production, outputs are consumed by CI/CD workflows using `terraform output -json` to inject dynamic server IPs into Playwright E2E integration test suites.
3

Environment Overrides with terraform.tfvars

GOAL
Override default variables using a terraform.tfvars file without editing HCL source code.
TFVARS
Create terraform.tfvars:
HCL β€” terraform.tfvars
container_name = "qe_staging_web_service"
external_port  = 9090
image_tag      = "alpine"
APPLY WORKFLOW
Run Terraform plan and apply to verify parameter substitution:
Terminal β€” Plan & Apply
terraform init
terraform plan
terraform apply -auto-approve
🏭Production Context & Enterprise Real-World Implementation
πŸ’‘ Why We Are Doing This: Separating environment parameters (`terraform.tfvars`) from core infrastructure blueprints (`main.tf`) enforces the DRY (Don't Repeat Yourself) principle across Dev, Staging, and Production environments.
🏒 Real-World Production Usecase: Enterprise SaaS platforms run identical HCL infrastructure modules across Dev, Staging, and Prod, varying only `dev.tfvars`, `staging.tfvars`, and `prod.tfvars` files.
βš™οΈ How Implemented in Production: Production secrets (like database passwords or API keys) are never checked into `tfvars` files in Git. They are injected at runtime via environment variables (`TF_VAR_db_password`) or AWS Secrets Manager.
4

Output Verification & Cleanup

GOAL
Verify output values using terraform output and curl the custom port 9090.
OUTPUT CHECK
Query state outputs and test endpoint:
Terminal β€” Verify Outputs & Curl
# 1. Read Terraform outputs
terraform output

# 2. Curl the port overridden by tfvars (9090)
curl -I http://localhost:9090

# 3. Clean up
terraform destroy -auto-approve
EXPECTED OUTPUT
Verification Success
web_url = "http://localhost:9090"
HTTP/1.1 200 OK returned on custom port 9090.
🏭Production Context & Enterprise Real-World Implementation
πŸ’‘ Why We Are Doing This: Programmatic verification confirms that dynamic parameter substitution produced working, accessible network services before marking pipeline deployments successful.
🏒 Real-World Production Usecase: Global cloud platforms verify that dynamic load balancer listener ports and SSL certificates respond correctly during automated canary releases.
βš™οΈ How Implemented in Production: Production validation scripts query `terraform output -json web_url`, pass the URL to automated health checkers, and trigger automatic blue-green traffic switches upon receiving `200 OK` status.