API & Automation·7 min read·

Infrastructure as Code: Declarative, Testable, Reviewable

Apply the four IaC principles — declarative, version-controlled, reviewable, testable — to stop infrastructure drift and sketchy manual changes.

NB

Netbay Infrastructure Team

Netbay Engineering

On this page

Infrastructure as Code (IaC) is less about a tool and more about a habit: describing your servers, networks, and applications in files that live in version control, change through review, and can be verified before they touch reality. Teams that adopt the habit stop treating their cloud as an undocumented sketch and start treating it like a codebase. This post distills the four principles that make that work.

Declarative, Not Scripted

Declarative configuration states what you want; imperative scripts spell out how to get there. The difference shows up in a single resource declaration:

hcl
resource "hcloud_server" "app" {
  name        = "app01"
  server_type = "cx22"
  image       = "ubuntu-24.04"
}

Compare that to an imperative script that must create the server, remember its ID, then write config files in exactly the right order, and hope nobody moves the goalposts in between. With a declarative file, Terraform or any similar tool derives the steps, and re-running it converges back to the same end state. The how is the tool's problem; the what is yours and the reviewer's.

Version-Controlled and Reviewable

If your infrastructure exists only on a running machine, it cannot be reviewed, rolled back, or blamed for that incident last Tuesday. Version control fixes all three: every change is a diff someone approves, every approved change is an entry in history, and re-producing an environment is a checkout plus an apply. The reviewable artifact matters most: a plan diff shows add, change, or destroy counts and the exact lines, so a merge request on infrastructure reads like a code review rather than a leap of faith.

Testable Before It Touches Production

The same gates that protect application code protect infrastructure code, on the way from laptop to production:

bash
# Static sanity checks before anything runs
terraform fmt -recursive
terraform validate
terraform plan -out ci.tfplan

# And the classic drift detector
terraform plan -detailed-exitcode
echo "exit code 2 means drift has been found"

A plan that exits 2 in your pipeline means reality has drifted from the committed configuration — usually someone pressed a manual button somewhere. Catching that in CI turns drift from a mystery into a routine alert you can respond to.

Environments, Not Snowflakes

The final principle is repeatability across environments with the same code and different inputs. Staging is production's rehearsal: same playbooks, same Terraform, different variable files. When a change has been applied, verified, and reverted in staging without a single CLI click, applying it to production stops being an adventure. Every environment that differs from the code is a snowflake that will eventually behave differently under load — and the whole point of IaC is that a snowflake cannot appear unnoticed, because the diff would expose it.

The IaC loop commit to version control review the plan diff apply on a test env promote to production drift detected in CI plan exit code 2 back to a fix commit

Takeaway

The four principles reinforce each other: declarative files make review fast, review keeps quality high, tests keep changes honest, and environments prove changes work before production sees them. None of them requires a fancy platform — a git repository and a small toolchain are enough to start. Practicing with real VPS instances is the fastest way to internalize the loop, and provisioning throwaway boxes on netbayhosts.in keeps the whole cycle cheap and safe to rehearse.

Keep reading

Follow along on a real VPS

Deploy Linux in under 60 seconds

These guides are written against Ubuntu, Debian, and RHEL-family images — the same ones on NetBay.

Deploy an instance