DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Terraform Type Constraints: Best Practices for Enterprise-Scale AWS
  • The Terraform State Locking Migration You Need to Know About: Moving Beyond DynamoDB
  • Implement Amazon S3 Cross-Region Replication With Terraform
  • Streamlining HashiCorp Cloud Platform (HCP) Deployments With Terraform

Trending

  • Microservices Architecture in Production: 7 Engineering Decisions That Determine Success or Failure
  • The Trust Surface: The Missing Complement to Attack Surface
  • Common REST Design Pattern
  • Observability for AI Agents and Multi-Agent Systems: When Your System Can't Tell You Why It Did That
  1. DZone
  2. Software Design and Architecture
  3. Cloud Architecture
  4. LocalStack and Terraform: A Clean Local AWS Setup Guide

LocalStack and Terraform: A Clean Local AWS Setup Guide

LocalStack mocks AWS services locally, while Terraform provisions them. Together, they let you test infrastructure code instantly, without cloud costs or internet.

By 
Ammar Ekbote user avatar
Ammar Ekbote
·
Aug. 13, 26 · Analysis
Likes (0)
Comment
Save
Tweet
Share
132 Views

Join the DZone community and get the full member experience.

Join For Free

Running AWS resources locally is a game-changer for engineering velocity, cost optimization, and developer autonomy. Traditionally, testing cloud infrastructure required deploying directly to a staging or sandbox AWS account. This workflow introduced painful friction points: waiting for slow cloud provisioning cycles, tracking down orphaned resources that inflate the monthly bill, and requiring a constant, high-speed internet connection.

LocalStack solves this by emulating core AWS services, such as  S3, SQS, DynamoDB, and other services directly on your local machine inside a Docker container.  When paired with Terraform, you can safely write, plan, and apply infrastructure-as-code (IaC) configuration blueprints against this local simulator. 

This guide walks you through the definitive "happy path" for configuring LocalStack and Terraform, followed by a robust troubleshooting handbook for common architecture-specific and container networking errors. This allows you to provision these mock resources cleanly. This allows testing Terraform code with local resources without incurring real AWS costs, requiring internet connectivity, or dealing with slow cloud provisioning cycles.

The Happy Path Setup

Step 1: Setting the Stage: Launching LocalStack With Docker

To get started, we need our local AWS cloud stack running inside a container. We will pull the official LocalStack image, set up our credentials, and spin up the container. 

First, pull the latest official image to your local machine:

Pull the latest official image to your local machine

Before firing up the container, head over to the LocalStack Web App Dashboard to grab your personal access token (PAT). While LocalStack offers an open-source community edition, advanced features or specific emulated APIs may check for a valid token.

Set up your Hobby acocunt

Getting started

Export this token into your shell environment so the container can authenticate and activate premium features on startup:

Shell
 
export LOCALSTACK_AUTH_TOKEN="ls-..."


Now, launch the container. We need to map the primary edge gateway port (4566), which routes all inbound AWS API requests, along with the standard range of ports used by individual internal services (4510-4559). We also pass our token as an environment variable:

Shell
 
docker run --rm -it \
  -p 4566:4566 \
  -p 4510-4559:4510-4559 \
  -e LOCALSTACK_AUTH_TOKEN=$LOCALSTACK_AUTH_TOKEN \
  localstack/localstack


Keep an eye on your terminal logs. LocalStack will quickly validate your token, pull your license configuration, and initialize the mock runtimes. You will see a clear notification when the edge proxy is fully ready to handle incoming API requests.

You'll receive a notification when the edge proxy is fully ready to handle incoming API requests

Step 2: The S3 Sanity Check: Talking to LocalStack

Before configuring our automation toolchain, let's run a quick manual sanity check using the standard AWS CLI. Because LocalStack runs entirely on your machine, we must override the default cloud routing by passing a custom --endpoint-url pointing to our local edge proxy. To verify that LocalStack is running and reachable, create a local S3 bucket and upload a test file using the AWS CLI. 

1. Create a Bucket

Shell
 
aws s3 \
mb s3://demo-bucket \
--endpoint-url=http://localhost:4566 \
--region us-east-1


2. Upload an Object

Create a dummy text file and copy it into your new mock bucket:

Shell
 
aws s3 \
cp /tmp/demo.txt s3://demo-bucket \
--endpoint-url=http://localhost:4566 \
--region us-east-1


3. List Objects

Verify the object is safely stored inside the mock container:

Shell
 
aws s3 \
ls s3://demo-bucket \
--endpoint-url=http://localhost:4566 \
--region us-east-1



Step 3: Writing the Blueprint: Configuring the Terraform Provider

Now let's automate things. To instruct Terraform to deploy resources to our local simulator instead of the real AWS cloud, we must customize the AWS provider block. We enforce dummy credentials, bypass cloud-only identity validations, and explicitly force all API endpoints to route directly to http://localhost:4566.

Providers Configuration

Create a file named providers.tf with the following content:

Markdown
 
terraform {
  backend "local" {
    path = "terraform.tfstate"
  }

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region                      = "us-east-1"
  access_key                  = "mock_access_key"
  secret_key                  = "mock_secret_key"
  skip_credentials_validation = true
  skip_metadata_api_check     = true
  skip_requesting_account_id  = true
  s3_use_path_style           = true

  # Redirect all endpoints to LocalStack's edge port
  endpoints {
    apigateway     = "http://localhost:4566"
    cloudwatch     = "http://localhost:4566"
    dynamodb       = "http://localhost:4566"
    ec2            = "http://localhost:4566"
    iam            = "http://localhost:4566"
    lambda         = "http://localhost:4566"
    rds            = "http://localhost:4566"
    s3             = "http://localhost:4566"
    secretsmanager = "http://localhost:4566"
    sns            = "http://localhost:4566"
    sqs            = "http://localhost:4566"
    ssm            = "http://localhost:4566"
    sts            = "http://localhost:4566"
  }
}


SQS Resource Definition

Next, define the SQS queue we want to provision. Create a file named main.tf:

Markdown
 
resource "aws_sqs_queue" "local_queue" {
  name                      = "my-local-queue"
  delay_seconds             = 90
  max_message_size          = 2048
  message_retention_seconds = 86400
  receive_wait_time_seconds = 10
}

output "queue_url" {
  value = aws_sqs_queue.local_queue.id
}


Step 4: The Moment of Truth: Initializing and Applying Configuration

With our configuration defined, we can run Terraform. Ensure you are executing a native binary that matches your host system architecture (such as a native darwin_arm64 binary if you are working on an Apple Silicon machine) to prevent execution overhead.

Initialize Terraform

First, initialize the working directory to download the AWS provider plugins:

Initialize Terraform


Generate and Review the Plan

Next, generate and review an execution plan. The plan output will detail our local queue configuration without attempting to connect to actual AWS endpoints:

Generate and review plan

Apply the Plan

Apply the plan to deploy the queue directly to LocalStack. Upon completion, Terraform will write your state file locally and output your new mock SQS queue URL:

Apply plan


Step 5: Taking It for a Spin: Sending and Receiving SQS Messages

To confirm that our Terraform-provisioned SQS queue is fully operational, let's capture the output URL and push a real message through it using the AWS CLI.

1. Send a Message

Shell
 
 export QUEUE_URL="http://sqs.us-east-1.localhost.localstack.cloud:4566/000000000000/my-local-queue"

 aws sqs send-message \
     --endpoint-url=http://localhost:4566 \
     --region us-east-1 \
     --queue-url $QUEUE_URL \
     --message-body "Hello from LocalStack SQS"


2. Receive the Message

Shell
 
   aws sqs receive-message \
     --endpoint-url=http://localhost:4566 \
     --region us-east-1 \
     --queue-url $QUEUE_URL

 {
     "Messages": [
         {
             "MessageId": "1235d997-f60a-4e86-b248-aff3f5f41dde",
             "ReceiptHandle": "NzYxOThkMDAtMWJiOC00OGVhLTllMDEtNTU3ZTY3ZGQ5M2I4IGFybjphd3M6c3FzOnVzLWVhc3QtMTowMDAwMDAwMDAwMDA6bXktbG9jYWwtcXVldWUgMTIzNWQ5OTctZjYwYS00ZTg2LWIyNDgtYWZmM2Y1ZjQxZGRlIDE3ODI4OTI2MzcuMjg2ODc1NQ==",
             "MD5OfBody": "88dc2faa42b899c03e12fd3ac96d714b",
             "Body": "Hello from LocalStack SQS"
         }
     ]
 }


Your terminal will return a successful JSON payload containing your message body, confirmation IDs, and MD5 hashes, proving that the local loop is entirely complete.

Terminal will return a successful JSON payload


Event Verification in LocalStack Logs

Checking the LocalStack container console confirms the queue creation, message send, and message fetch operations were handled successfully:

Check the LocalStack container console


Troubleshooting Guide

Even on a happy path, local container networks and mixed system architectures can throw a wrench into your workflow. Here is how to fix the most common bottlenecks.

The Apple Silicon (M1/M2/M3) Rosetta Loop

Symptom: The LocalStack container crashes unexpectedly on startup, or loops endlessly while attempting to launch internal components like local Lambda runtimes, throwing qemu: uncaught target signal 11 errors.

The Cause: LocalStack occasionally spins up secondary processes or helper binaries inside the container. If Docker Desktop is forced to emulate an x86_64 architecture via Virtualization frameworks on an ARM64 Apple Silicon chip, the emulation layer can break during heavy nested execution.

The Fix: Ensure your Docker Desktop configuration has Use Virtualization framework enabled under Settings -> General, and turn on Rosetta for x86/amd64 emulation under the Features in Development tab. Alternatively, force Docker to fetch the native ARM64 container image by updating your execution command to include the specific platform flag:

Shell
 
docker run --platform linux/arm64 --rm -it -p 4566:4566 localstack/localstack


"Port Already in Use"

Symptom: Docker fails to bind ports, displaying an error message like: Bind for 0.0.0.0:4566 failed: port is already allocated.

The Cause: A previous instance of LocalStack didn't shut down cleanly, or another local development tool is monopolizing port 4566.

The Fix:

Option 1: Check for lingering Docker containers

Often, a container crashed or was backgrounded but didn't release the port. Find any container using 4566:

Shell
 
docker ps -a | grep 4566


If a container shows up, stop and remove it (replace <CONTAINER_ID> with your specific ID):

Shell
 
docker stop <CONTAINER_ID>
docker rm <CONTAINER_ID>


Option 2: Kill native background processes

If Docker isn't holding the port, another process on your host machine is. You'll need to find its Process ID (PID) and force-quit it.

Find the PID:

Shell
 
lsof -i :4566


Kill it (look for the number under the PID column):

Shell
 
kill -9 <PID>


Wrapping Up

Combining LocalStack and Terraform gives you a lightning-fast, zero-cost, offline sandbox for cloud infrastructure development. Once your environment is configured correctly with a valid personal access token, precise Docker port mappings, and native toolchains matched to your host CPU, you can prototype, test, and tear down AWS configurations in seconds.

No more waiting for slow cloud deployments or tracking down orphaned cloud resources. Happy local provisioning!

AWS Terraform (software)

Opinions expressed by DZone contributors are their own.

Related

  • Terraform Type Constraints: Best Practices for Enterprise-Scale AWS
  • The Terraform State Locking Migration You Need to Know About: Moving Beyond DynamoDB
  • Implement Amazon S3 Cross-Region Replication With Terraform
  • Streamlining HashiCorp Cloud Platform (HCP) Deployments With Terraform

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook