Choosing a Better Tool

Scenario: Every apply SSHs to servers to install packages, making infrastructure changes slow and dependent on a live package repository.

Bake machine images for immutable server contents; use cloud-init for first-boot bootstrap; use Ansible or another configuration manager for ongoing host convergence; use Kubernetes or a deployment platform for applications; use provider resources for API objects; use CI for notifications and artifact publication. Terraform should pass identifiers and endpoints across boundaries, not absorb every operational step.

Analogy: A city planner creates roads and parcels; restaurant managers run kitchens. Giving one office every job creates neither clarity nor resilience.

A worked configuration

# Terraform creates infrastructure and publishes a narrow handoff.
output "inventory" {
  value = { for k, v in fakecloud_server.node : k => v.address }
}

The production test is failure ownership: which system can detect drift, retry safely, report status, and roll back the action? Put the work where those lifecycle capabilities exist.

Note: Treat the plan as a change contract: understand every create, update, replacement, and destroy before approving it.
Goal: Reinforce this lesson in the tf-first-apply Terraform lab. Open /labs/terraform and choose slug tf-first-apply; the lab runs real Terraform against the offline FakeCloud provider.