AWS Day 2: Automating Infrastructure with Terraform

In our previous guide, "AWS Startup Guide: Building a Secure Foundation from Day One," we established the critical first steps for your AWS journey. We created a secure management account, protected your root credentials, and set up proper administrative access through IAM Identity Center. You now have a solid security foundation with a non-root administrative user that follows AWS best practices.

Now it's time to take the next significant step in your cloud journey: automating your infrastructure through code. In this guide, we'll move beyond the AWS Management Console to embrace the tools and practices that enable true infrastructure automation. By the end of this tutorial, you'll have a completely programmable AWS environment that forms the backbone of your startup's cloud strategy.

The architecture we’re shooting for at the end of this series. The management account controls users and policies, and configures new accounts with control tower.

What We'll Cover

This guide will walk you through:

  1. Installing and Configuring the AWS CLI - Setting up command-line access to your AWS environment for programmatic control
  2. Installing Terraform - Preparing your development environment for Infrastructure as Code
  3. Creating Your First Terraform Configuration - Building the code foundation for your AWS Organization

Why This Matters for Your Startup

While clicking through the AWS console might seem faster for initial setup, transitioning to Infrastructure as Code immediately creates substantial long-term advantages:

  • Eliminates Manual Errors: Human configuration mistakes become a thing of the past
  • Creates Reproducibility: Every environment is built from the same templates
  • Enables Version Control: Track changes, understand history, and collaborate effectively
  • Simplifies Scaling: Add new accounts and resources with minimal effort
  • Improves Security: Enforce consistent security controls across all accounts
  • Accelerates Onboarding: New team members can understand your infrastructure through code
  • Automation: Infrastructure changes can be deployed without human assistance

Prerequisites

Before starting this guide, ensure you have:

  • Completed the steps in our "Day 1 Setup" guide

  • Access to your non-root administrative user credentials

  • A development machine (Windows, macOS, or Linux) with administrative privileges

  • Basic familiarity with command-line interfaces

  • A text editor for code editing (I use JetBrains IDEs, but anything will work)

  • Ideally, some knowledge of version control

By embracing automation from day one, you're setting your startup on a path that aligns with industry best practices and positions you for efficient growth. Let's get started building a cloud infrastructure that scales alongside your business vision.

Installing the AWS CLI

The AWS Command Line Interface (CLI) provides direct access to AWS services from your terminal, enabling scripting and automation of AWS tasks. We're using it to handle logging into AWS and making our credentials available in a terminal session.

For macOS:

# Using Homebrew
brew install awscli

# Verify installation
aws --version

For Windows:

  1. Download the official MSI installer from the AWS CLI website

  2. Run the downloaded MSI file and follow the installation wizard

  3. Open Command Prompt or PowerShell and verify with `aws --version`

For Linux (Ubuntu/Debian):

# Update package lists
sudo apt update

# Install AWS CLI
sudo apt install awscli

# Verify installation
aws --version

For Linux (Amazon Linux/RHEL/CentOS):

# Install AWS CLI
sudo yum install awscli

# Verify installation
aws --version

Configuring AWS CLI with AWS SSO

Since you've set up AWS SSO (IAM Identity Center) in your management account, you'll need to configure the AWS CLI to use SSO authentication:

  1. Log in to the AWS Management Console using your non-root administrator account
  2. Navigate to IAM Identity Center > Settings
  3. Note your Identity Center URL (you'll need this for CLI configuration)

Now configure the AWS CLI:

aws configure sso

# When prompted, enter:
# - SSO session name: YourCompanyName-SSO (or any name you prefer)
# - SSO start URL: https://your-sso-portal.awsapps.com/start (from step 3 above)
# - SSO region: your-region (e.g., us-east-1)
# - SSO registration scopes: [press Enter for default]

# Browser will open for authentication
# After authenticating, select your account and role
# Configure the default output format (json recommended)
# Configure the default region (select your primary AWS region)

To verify your configuration works correctly:

# Check if you can list S3 buckets (may be empty for new accounts)
aws s3 ls

# Verify your identity
aws sts get-caller-identity

Your AWS CLI is now properly configured with SSO authentication. Because I have many AWS profiles, I like using this oh-my-zsh alias to quickly switch profiles or login again with `asp {profile}` or `asp {profile} login` when the token expires.

Embracing Terraform: The Foundation of Your Cloud Strategy

What is Terraform?

Now that we have the AWS CLI configured for programmatic access to our AWS environment, it's time to introduce the tool that will fundamentally transform how you build and manage cloud infrastructure: Terraform.

Terraform is an open-source Infrastructure as Code (IaC) tool created by HashiCorp that allows you to define and provision infrastructure using a declarative configuration language. Unlike imperative scripting, which focuses on how to achieve a result, Terraform's declarative approach lets you specify what your infrastructure should look like, and it handles the complex task of making it happen.

At its core, Terraform works by:

  1. Reading configuration files you write that describe your desired infrastructure state
  2. Generating an execution plan that shows what changes will be made
  3. Building or modifying your infrastructure to match your configuration
  4. Tracking the state of your infrastructure in state files for future operations

Why Terraform is Essential for Startups

For early-stage startups, every technology decision must balance immediate needs with long-term implications. Terraform represents one of those rare tools where the investment immediately pays dividends while setting you up for sustainable growth.

Avoiding the "Technical Debt Trap"

One of the most common patterns we see with startups is the accumulation of "click-ops" technical debt. In the rush to launch, founders and early engineers manually configure cloud resources through web consoles. While this appears faster initially, it creates several hidden costs:

  • Undocumented knowledge: Critical infrastructure decisions live only in the minds of those who clicked the buttons
  • Configuration inconsistency: Slight differences between environments cause difficult-to-trace bugs
  • Scaling challenges: Manual processes that work for one service become unmanageable across dozens
  • Onboarding friction: New team members can't easily understand how the infrastructure is built
  • Disaster recovery risk: Manually built systems are much harder to rebuild after failures

By implementing Terraform from day one, you avoid this trap entirely. Your infrastructure becomes self-documenting, consistent, repeatable, and resilient.

The Multi-Cloud Reality

While you may be starting on AWS today, the future of cloud computing is increasingly multi-cloud. Whether driven by specific service offerings, cost optimization, or risk mitigation, many startups eventually adopt services across multiple cloud providers.

Terraform was designed with this reality in mind. Its provider-based architecture means the same configuration language and workflows you learn for AWS can later extend to other providers like Google Cloud, Azure, or specialized services like Cloudflare, MongoDB Atlas, or Datadog. This consistency creates powerful operational efficiencies as your infrastructure grows.

Version Control for Infrastructure

Just as version control systems like Git revolutionized software development, Terraform brings these same benefits to infrastructure management:

  • Change history: Track who changed what, when, and why
  • Collaboration: Multiple team members can work on infrastructure simultaneously
  • Rollbacks: Quickly revert to previous states when needed
  • Branching: Test infrastructure changes in isolation before applying them
  • Code review: Apply software engineering best practices to infrastructure changes

This approach transforms infrastructure from a black box into a transparent, collaborative process that aligns with modern development workflows.

Security by Design

For startups that may eventually work with enterprise customers or in regulated industries, security and compliance are critical concerns. Terraform helps build security into your infrastructure from the beginning:

  • Policy as code: Encode security requirements directly in your configurations
  • Consistency enforcement: Ensure all environments follow the same security standards
  • Least privilege: Precisely define permissions without excess access
  • Audit readiness: Maintain complete records of infrastructure changes
  • Compliance documentation: Generate evidence of controls for certification processes

These capabilities become increasingly valuable as your startup matures and faces more stringent security requirements from customers and regulators.

Terraform and AWS: A Powerful Combination

Terraform's AWS provider is one of its most mature and feature-complete integrations, offering support for virtually every AWS service. This deep integration enables you to:

  • Manage your complete AWS Organization structure
  • Define Security Control Policies (SCPs) that enforce guardrails
  • Create and configure accounts for different environments and workloads
  • Set up cross-account roles and access patterns
  • Implement networking and security controls consistently
  • Deploy and configure services across your entire cloud footprint

The AWS-specific modules available in the Terraform Registry also provide pre-built configurations for common patterns, accelerating your implementation of best practices.

The Long-Term Advantage

Perhaps the most compelling reason for startups to adopt Terraform early is the compounding advantage it creates. Each piece of infrastructure you define in code becomes a reusable building block for future work. As your library of modules grows, your team's velocity increases—new environments, services, or features can be deployed by assembling existing components rather than starting from scratch.

This approach creates a virtuous cycle where infrastructure becomes an enabler rather than a constraint on your business growth. As your startup evolves, your infrastructure can evolve alongside it without the painful migrations and re-architectures that plague many growing companies.

In the next section, we'll install Terraform and create our first configuration file to manage our AWS Organization programmatically.

Installing Terraform

Terraform is the Infrastructure as Code tool you'll use to define and provision your AWS infrastructure.

For macOS:

# Using Homebrew
brew tap hashicorp/tap
brew install hashicorp/tap/terraform

# Verify installation
terraform -version

For Windows:

  1. Download the appropriate zip file from the [Terraform downloads page](https://www.terraform.io/downloads)

  2. Extract the zip file to a directory of your choice

  3. Add this directory to your system PATH

  4. Open Command Prompt or PowerShell and verify with `terraform -version`

For Linux (Ubuntu/Debian):

# Add HashiCorp GPG key
wget -O- https://apt.releases.hashicorp.com/gpg | gpg --dearmor | sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg

# Add HashiCorp repository
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list

# Update and install
sudo apt update && sudo apt install terraform

# Verify installation
terraform -version

For Linux (Amazon Linux/RHEL/CentOS):

# Add HashiCorp repository
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
sudo yum -y install terraform

# Verify installation
terraform -version

Setting Up Your Terraform Foundation

Now that you have both the AWS CLI and Terraform installed, let's create a solid foundation for managing your AWS infrastructure as code. We'll establish a clean directory structure and set up the initial configuration files.

Creating Your Directory Structure

Start by creating a structured directory for your Terraform files. This organization will help you scale as you add more accounts and environments.

# Create the base directory structure
mkdir -p tf/environments/management

# Move into the management account directory
cd tf/environments/management

This directory structure separates your Terraform configurations by environment, starting with your management account. As you add more accounts (like development, testing, or production), you'll create additional directories at the same level as "management".

Creating Your Initial Configuration Files

Next, let's create the two essential files you'll need to get started:

1. Create config.tf

This file defines your Terraform settings and AWS provider configuration:

terraform {
  backend "local" {
    path = "terraform.tfstate"
  }
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.88.0"
    }
  }
}

provider "aws" {
  region = "us-east-1"
  allowed_account_ids = [
    "REPLACE_WITH_YOUR_MANAGEMENT_ACCOUNT_ID"
  ]
}

Important: Replace REPLACE_WITH_YOUR_MANAGEMENT_ACCOUNT_ID with your actual AWS management account ID. This prevents accidental deployments to the wrong account.

2. Create an empty main.tf

This file will eventually contain your resource definitions, but we'll start with an empty file:

touch main.tf

3. Create a .gitignore file

To prevent committing sensitive state files to your repository:

cat > .gitignore << 'EOF'
# Local .terraform directories
**/.terraform/*

# .tfstate files
*.tfstate
*.tfstate.*

# Crash log files
crash.log
crash.*.log

# Exclude all .tfvars files, which are likely to contain sensitive data
*.tfvars
*.tfvars.json

# Ignore override files as they are usually used for local development
override.tf
override.tf.json
*_override.tf
*_override.tf.json

# Ignore CLI configuration files
.terraformrc
terraform.rc
EOF

Initialize Your Terraform Configuration

With your files in place, initialize Terraform to download the necessary providers:

terraform init

You should see a message indicating that Terraform has been successfully initialized.

Understanding This Approach

Why are we starting with local state storage instead of jumping straight to remote state in S3?

  1. Bootstrapping Solution: This resolves the classic "chicken and egg" problem—you need Terraform to create your infrastructure, but ideally, your Terraform state should be stored in that infrastructure.
  2. Temporary Foundation: We're only using local state temporarily. In our next guide, we'll create a dedicated operations account and migrate to remote state storage in S3 with DynamoDB locking.
  3. Management Account Focus: For now, we'll use this configuration to manage only organization-level resources like AWS accounts, policies, and users—keeping our management account focused solely on governance.

What's Next

With this foundation in place, you're ready to begin defining your AWS Organization structure in code. In our next guide, we'll:

  1. Create your first resources in main.tf to set up AWS Organizations
  2. Configure organization policies and security guardrails
  3. Provision additional accounts for operations, security, and logging
  4. Migrate from local state to remote state in S3

This step-by-step approach ensures you're building on a solid foundation from day one, following AWS best practices while keeping the process manageable.

Next
Next

AWS Startup Infrastructure: Day 1 Setup