← Lessons/Capstone — Build a Stack
← Capstone — Build a Stack

Build it from the brief

Learn

The brief

Build a configuration that satisfies all of these:

  1. A variable server_name, defaulting to "web" — so the server's name is a parameter, not a hard-coded string.
  2. A network — demo_network named main, with cidr "10.0.0.0/16".
  3. A server — demo_server named web that:
    • uses var.server_name for its name, and
    • is attached to the network with network_id = demo_network.main.id (an inter-resource dependency — the server must be created after the network).
  4. Two outputs — server_name (the server's name) and private_ip (the server's computed IP address).

Then run apply. The checks confirm it applied cleanly, uses a variable, wires the server to the network, and surfaces your outputs.

What "good" looks like

You're not just making it work — you're making it clean: the value that changes (the name) is a variable, the dependency is expressed as a reference (not depends_on), and the things a consumer cares about are outputs. That's the shape of every well-written Terraform module.

You've hit the free milestone: you can write, plan, apply, and read state, and you understand drift and recovery. But notice where your state lives — a single local file on this machine. The moment a teammate (or a CI pipeline) needs to apply too, that local file becomes the bottleneck and the risk. Remote state with locking is exactly where the next track begins.

Write the whole stack from the brief: a server_name variable (default "web"), a demo_network named main (cidr "10.0.0.0/16"), a demo_server named web that uses var.server_name and attaches to the network via network_id = demo_network.main.id, plus server_name and private_ip outputs. Then run apply.

Interview prep

A capstone you can talk through is worth more than a dozen tutorials you watched — be ready to walk an interviewer through this stack.

Walk me through the structure of a basic Terraform configuration.

Inputs at the top as variable blocks; the resource blocks that make up the stack, wired together with references so the dependency graph (and creation order) is implicit; and output blocks at the end exposing the values a consumer needs — typically computed attributes like IDs or IPs. Run plan to preview, apply to converge, and the state file records what was built.

Why parameterize with variables and expose outputs instead of hard-coding everything?

Variables make a config reusable across environments without editing the body, and they keep changeable values in one place. Outputs are the documented return values — they let a human, a script, or a parent module consume what the stack produced (an IP, an ARN) without reaching into its internals. Together they turn a one-off snippet into a reusable, composable module.

Loading...

State Inspector

State

Terraform's memory

empty — nothing here yet

Real Infrastructure

the actual world

empty — nothing here yet