A curated collection of articles exploring this topic in depth.
Infrastructure as Code Without Heroics
Why declarative infrastructure is valuable for small systems, and how Terraform acts as executable documentation for this blog.
Infrastructure as Code (IaC) is often marketed as an enterprise tool, essential for managing thousands of servers but might be considered unnecessary for a single-author blog. This view frames IaC as a solution to scale, when its more fundamental value is clarity.
For this project, I chose to manage every AWS resource using Terraform. While this is a useful development exercise, the primary goal was to ensure that the environment is reproducible, documented, and stable.
Beyond the Console
A common alternative (and quite frankly simpler) for a small site is "Console-driven development" (or ClickOps): manually clicking through the AWS Management Console to create buckets and distributions. While fast initially, this approach has several failure modes:
- Hidden state: It is impossible to see the entire system at a glance. You have to navigate through dozens of screens to verify a single security setting.
- Fragility: One accidental click can break the site, with no easy way to revert or even identify what changed.
- Knowledge rot: In six months, you will likely forget why a specific policy was added or which certificate is being used.
Terraform replaces this ambiguity with a declarative record of intent.
Terraform as Executable Documentation
When infrastructure is defined in code, the codebase becomes the single source of truth for how the system is constructed.
For example, looking at the s3.tf file tells me exactly how the storage layer is configured:
resource "aws_s3_bucket_public_access_block" "site" {
bucket = aws_s3_bucket.site.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}I don't need to log into the AWS Console to verify that public access is blocked. The code confirms it. If I need to change a policy, I change the code, review the plan, and apply it. The documentation and the reality are always in sync because the documentation is the deployment mechanism.
Declarative vs Imperative
A common question in the IaC space is whether to use a declarative tool like Terraform or an imperative/construct-based tool like the AWS Cloud Development Kit (CDK).
For this blog, I chose Terraform because it is strictly declarative. It describes the what, not the how.
Imperative tools allow you to use full programming languages (like TypeScript) to define infrastructure. While flexible, this can introduce "heroic" complexity through loops, conditionals, and abstractions that make it harder to see the final state of the system. In a small system like this, my goal is transparency. Terraform’s HCL (HashiCorp Configuration Language) is designed to be readable and boring, which is exactly what you want for infrastructure documentation.
Drift Prevention and State
One of the most valuable features of Terraform is state management. Terraform maintains a terraform.tfstate file that maps your code to the actual resources in AWS.
When you run terraform plan, the tool compares your local code against the state and the live environment. If someone (or some script) has manually changed a setting in AWS, Terraform will detect this "drift" and offer to correct it.
This provides a level of integrity that is impossible with manual configuration. The system is self-healing in the sense that it can always be returned to its known-good state.
Small Systems, Serious Discipline
Using Terraform for a personal blog might seem like using a sledgehammer to crack a nut, but it is actually about reducing the long-term cognitive load. By investing a few hours in writing the initial modules, I have ensured that I never have to "debug" my infrastructure in the console again.
The infrastructure layer is now a stable foundation that requires almost no maintenance. I can focus on writing content, knowing that the delivery and security of that content are defined in a clear, version-controlled, and reproducible format.
In the next post, we will look at how this declarative approach allows us to define strict security boundaries, ensuring that our small system follows the principle of least privilege.