AWS
Provisioning an AWS Landing Zone with OpenTofu and Spacelift
This article walks you through building a secure, scalable AWS landing zone using OpenTofu and Spacelift.
Jubril Oyetunji
May 28, 2025
Published on
May 28, 2025
Read More
Divine Odazie
19 Jan, 2025
This article walks you through building a secure, scalable AWS landing zone using OpenTofu and Spacelift.

In the context of cloud infrastructure, a landing zone represents a pre-configured, well-architected set of cloud resources, network configurations, security controls, and governance policies that enable organizations to quickly and safely deploy and manage their cloud-based applications and services. 

As more and more teams look to adopt OpenTofu in deploying their cloud resources, it is only natural that landing zones are developed to streamline and standardize cloud infrastructure deployments with OpenTofu.

In this article, we'll walk through building a practical template for creating an AWS landing zone using OpenTofu and leveraging Spacelift for seamless deployment. 

Foreword by James Humphries at Spacelift (Supporters of OpenTofu)

OpenTofu makes it easy to deploy infrastructure to any cloud, with a rich ecosystem of providers and modules ready to support any need. Spacelift extends that power, helping teams manage infrastructure as code at any scale with confidence, control, and flexibility. Together, OpenTofu and Spacelift offer a rock-solid foundation for modern, scalable IaC. - James Humphries (Head of Open Source @ Spacelift and Core Contributor at OpenTofu

Why do you need a landing zone?

If you've worked in a large organization with multiple development teams all trying to utilize cloud resources, you've likely witnessed the chaos that can ensue without proper structure. Landing zones aren't just a nice-to-have—they form a foundation for any organization looking to scale its infrastructure deployments. 

However, a core challenge most organizations face is striking the right balance between providing enough structure to ensure security and compliance while giving teams autonomy to develop their own infrastructure.

A well-designed landing zone addresses this by:

  • Creating guardrails rather than roadblocks
  • Standardizing the elements that should be consistent across environments
  • Allowing flexibility where teams need it most
  • Centralizing governance without creating bottlenecks

Enabling multi-account strategies

Most mature AWS implementations utilize a multi-account strategy to create strong isolation boundaries between workloads and teams.

Without a landing zone approach, managing 10, 50, or even hundreds of accounts becomes virtually impossible. Landing zones provide a link between these accounts, ensuring consistent policies, centralized logging, proper network connectivity, and standardized access controls.

How does a landing zone differ from a module?

At this stage, you're likely wondering how a landing zone differs from a regular OpenTofu/Terraform module. After all, both seem to package infrastructure as code, so what's the distinction?

Here are two key differences:

Scope and purpose

The fundamental difference lies in scope and purpose. A module is a technical implementation detail—a way to package reusable code that provisions specific resources. You might have modules for creating EC2 instances, S3 buckets, or VPC configurations. Modules are the building blocks, the tactical components that solve discrete infrastructure problems.

A landing zone, on the other hand, is a strategic approach to cloud adoption. It's a comprehensive blueprint that brings together multiple modules, policies, and organizational patterns to create a complete foundation for your cloud environment. 

Implementation details

Landing zones are often implemented using modules. The landing zone is the overall architecture and approach, while modules are one of the key tools used to implement that architecture in a consistent, repeatable way.

In essence, modules are an essential implementation detail of landing zones—they're how you achieve the consistency and repeatability that make landing zones valuable. However, the landing zone itself is the overarching framework that gives those modules purpose and context.

How does Spacelift help?

Spacelift takes a different approach to orchestrating Infrastructure as Code compared to traditional CI/CD pipelines. Rather than just executing your OpenTofu code, it wraps intelligent guardrails around the entire workflow.

For developers, this means they can confidently work within pre-defined boundaries that align with your landing zone architecture. Instead of needing to understand every nuance of your cloud governance model, they can rely on the guardrails to prevent problematic changes.

When these policies detect issues—maybe a security group that's too permissive or a resource that doesn't follow tagging standards—they can block the deployment before it ever reaches your environment. This creates a feedback loop that naturally guides teams toward best practices.

Demo overview

This demo will primarily focus on deploying a landing zone while using Spacelift to manage the lifecycle of making changes and applying updates to it. 

Imagine a growing startup that's been using a smaller cloud provider but is now hitting limitations as they scale. They've decided to migrate to AWS to take advantage of its broader service offerings and better integration capabilities.

Architecture

The startup has a relatively straightforward architecture:

  • Their primary application runs in containers
  • They serve static assets (images, CSS, JS files) from cloud storage
  • They need to maintain proper security and access controls as they grow

Translating the architecture to AWS, our OpenTofu module:

  1. Creates a VPC spanning two availability zones with public and private subnets, NAT gateways, and appropriate routing tables to ensure secure network traffic flow.
  2. Provisions an ECS cluster with two Fargate services for running containerized applications.
  3. Sets up an S3 bucket with restrictive access policies.

Prerequisites

In order to follow along with this tutorial, you will need the following: 

  • A Spacelift account: This allows you to manage and provision the OpenTofu code. 
  • An AWS account: This account should have sufficient permissions to provision and destroy resources.
  • AWS CLI: This allows you to interact with AWS through the command line.

Step 1: Cloning the OpenTofu template 

To streamline the process, fork the sample repository containing all the OpenTofu code for the module explained above:

git clone git@github.com:yourgithub
/opentofu-lz.git && opentofu-lz

The repository structure is organized into modules that each handle specific parts of the landing zone:

Step 2: Creating a Spacelift stack

Stacks are one of the core concepts in Spacelift. A stack is an isolated, independent entity. You can think of a stack as a combination of source code and the current state of the managed infrastructure (e.g., the OpenTofu state file). 

Before provisioning the infrastructure, you need to create a stack. Within your Spacelift dashboard, click on stacks in the top right corner. This will open a new menu where you can create a new stack.

Follow the prompts and select the repository forked earlier. 

Step 3: Configure AWS integration 

With a stack created, you will need to provide Spacelift with your AWS credentials. Things get interesting here, as instead of providing your AWS access and secret keys, Spacelift can generate ephemeral credentials. 

Ephemeral credentials offer enhanced security because they automatically expire after a short period, thus eliminating the risks associated with long-lived access keys. These temporary credentials are generated on-demand and exist only for the duration of a specific operation.

Begin by setting environment variables for your AWS and Spacelift accounts:

export AWS_ACCOUNT_ID=YOUR_AWS_ACCOUNT_ID 
export SPACELIFT_ACCOUNT_NAME=<your Spacelift account name> 

Next, create a policy that allows Spacelift to assume an IAM role in your AWS account using STS:AssumeRole

cat > iam.json << EOF
{
  "Version": "2012-10-17",
  "Statement": [
	{
  	"Action": "sts:AssumeRole",
  	"Condition": {
    	"StringLike": {
      	"sts:ExternalId": "${SPACELIFT_ACCOUNT_NAME}@*"
    	}
  	},
  	"Effect": "Allow",
  	"Principal": {
    	"AWS": "${AWS_ACCOUNT_ID}"
  	}
	}
  ]
}
EOF

Create the IAM role

aws iam create-role  --role-name SpaceliftRole  --assume-role-policy-document file://iam.json

Attach the AdministratorAccess policy to the role

aws iam attach-role-policy \
  --role-name SpaceliftRole \
  --policy-arn arn:aws:iam::aws:policy/AdministratorAccess

Finally, obtain the ARN of the role you just created

aws iam get-role --role-name SpaceliftRole --query 'Role.Arn' --output text

You will need this shortly. 

Step 4: Create a new Spacelift integration 

With the role created, the next step is to create an AWS integration that uses the IAM role. 

1. Within your Spacelift dashboard, click on Cloud integrations:

2. Select AWS, and you will be presented with another menu:

3. Provide a name as well as the ARN of the IAM role you created earlier and click Create:

Step 5: Connecting AWS to your Spacelift stack

With an integration created, you can now link your AWS account to the stack created earlier.  Within the stacks tab, click on the overflow menu to reveal the settings tab:

1. Click on the overflow menu:

2. Within the settings tab, click on the integrations option and select attach new integration in the top right corner:

This will bring up a new menu in which you can select the integration you created earlier.


3.  Copy the Trust relationship:

Check the write and read options as we want Spacelift to provision the infrastructure, this will also provide you with a statement to add to the trust relationship of your IAM role, this will enable Spacelift generate those ephemeral credentials we talked about.

4. Head to your AWS dashboard and locate the IAM role you created earlier:

5. Click on Trust relationship and select Edit trust policy:


6. Update the role with the statement from your Spacelift dashboard and save.

Step 6: Triggering stack creation

With credentials set up the next step is to trigger an execution of the stack, this can be done by pushing a commit or opening a pull request. To keep things simple, trigger the execution through the dashboard. 

Head back to the Spacelift dashboard and trigger a run, as shown in the video below:

https://drive.google.com/file/d/1GsdImjpK_Zkq4lEw0McjqnWKG-xLYWX9/view?usp=drive_link

In a few minutes, you should see the output of tofu plan command, which gives you a quick view of what would be provisioned.

By default Autodeploy is turned off which means you will need to approve each deployment before it is applied. To approve this run. 

Click on Confirm to approve this run:

Once the run completes, your dashboard should look similar to:

Step 7: Verify the run

You can verify that all the resources were created by looking through the AWS console. Spacelift provides a neat interface to view all the resources created within a specific run. 

As shown in the video above, each resource provisioned is shown in a neat interface along with the corresponding module.

Embracing open automation 

For many teams building a landing zone is half the battle, scaling your deployments across multiple environments and accounts is where challenges emerge. Using stacks in combination with Spacelift’s AWS integration we showed how you can provision and monitor your infrastructure without having to build complex deployment pipelines.  

Looking to do more with OpenTofu and Spacelift? Here are some ideas: 

Stay ahead with the latest updates, exclusive insights, and tailored solutions by joining our newsletter.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
What is your email addres?
Featured posts
Managing the AWS Cloud Secrets - The Best Possible Way
This is some text inside of a div block.
This is some text inside of a div block.

Stay ahead with the latest updates, exclusive insights, and tailored solutions by joining our newsletter.

We care about your data in our privacy policy.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
ABOUT THE AUTHOR