Skip to content
Get Started for Free

Terraform

Terraform is an Infrastructure-as-Code (IaC) framework developed by HashiCorp. It enables users to define and provision infrastructure using a high-level configuration language. Terraform uses HashiCorp Configuration Language (HCL) as its configuration syntax. HCL is a domain-specific language designed for writing configurations that define infrastructure elements and their relationships.

LocalStack supports Terraform via the AWS provider through custom service endpoints. You can configure Terraform to use LocalStack in two ways:

  • Using the tflocal wrapper script to automatically configure the service endpoints for you.
  • Manually configuring the service endpoints in your Terraform configuration with additional maintenance.

In this guide, we will demonstrate how you can create local AWS resources using Terraform and LocalStack, by using the tflocal wrapper script and a manual configuration example.

tflocal is a small wrapper script to run Terraform against LocalStack. tflocal script uses the Terraform Override mechanism and creates a temporary file localstack_providers_override.tf to configure the endpoints for the AWS provider section. The endpoints for all services are configured to point to the LocalStack API (http://localhost:4566 by default). It allows you to easily deploy your unmodified Terraform scripts against LocalStack.

Create a new file named main.tf and add a minimal S3 bucket configuration to it. The following contents should be added in the main.tf file:

resource "aws_s3_bucket" "test-bucket" {
bucket = "my-bucket"
}

To install the tflocal command, you can use pip (assuming you have a local Python installation):

Terminal window
pip install terraform-local

After installation, you can use the tflocal command, which has the same interface as the terraform command line.

Terminal window
tflocal --help
Output
Usage: terraform [global options] <subcommand> [args]
...

Start your LocalStack container using your preferred method. Initialize Terraform using the following command:

Terminal window
tflocal init

You can now provision the S3 bucket specified in the configuration:

Terminal window
tflocal apply
Environment VariableDefault valueDescription
TF_CMDterraformTerraform command to call
AWS_ENDPOINT_URL-Hostname and port of the target LocalStack instance
LOCALSTACK_HOSTNAMElocalhost(Deprecated) Host name of the target LocalStack instance
EDGE_PORT4566(Deprecated) Port number of the target LocalStack instance
S3_HOSTNAMEs3.localhost.localstack.cloudSpecial hostname to be used to connect to LocalStack S3
USE_EXEC-Whether to use os.exec instead of subprocess.Popen (try using this in case of I/O issues)
<SERVICE>_ENDPOINT-Setting a custom service endpoint, e.g., COGNITO_IDP_ENDPOINT=http://example.com
AWS_DEFAULT_REGIONus-east-1The AWS region to use (determined from local credentials if boto3 is installed)
CUSTOMIZE_ACCESS_KEY-Enables you to override the static AWS Access Key ID
AWS_ACCESS_KEY_IDtest (accountId: 000000000000)AWS Access Key ID to use for multi-account setups

Instead of using the tflocal script, you have the option to manually configure the local service endpoints and credentials. The following sections will provide detailed steps for this manual configuration.

To begin, you need to define mock credentials for the AWS provider. Specify the following in your main.tf file:

provider "aws" {
access_key = "test"
secret_key = "test"
region = "us-east-1"
}

Next, to prevent routing and authentication issues (which are unnecessary in this context), you should provide some general parameters:

provider "aws" {
access_key = "test"
secret_key = "test"
region = "us-east-1"
# only required for non virtual hosted-style endpoint use case.
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs#s3_use_path_style
s3_use_path_style = true
skip_credentials_validation = true
skip_metadata_api_check = true
skip_requesting_account_id = true
}

Furthermore, it’s necessary to configure the individual services to use LocalStack. For S3, this configuration resembles the following snippet, where we’ve chosen to use the virtual hosted-style endpoint:

endpoints {
s3 = "http://s3.localhost.localstack.cloud:4566"
}

The final minimal configuration for deploying an S3 bucket via a main.tf file should resemble the following:

provider "aws" {
access_key = "mock_access_key"
secret_key = "mock_secret_key"
region = "us-east-1"
s3_use_path_style = true
skip_credentials_validation = true
skip_metadata_api_check = true
skip_requesting_account_id = true
endpoints {
s3 = "http://s3.localhost.localstack.cloud:4566"
}
}
resource "aws_s3_bucket" "test-bucket" {
bucket = "my-bucket"
}

Here’s a configuration example with additional service endpoints. Please note that these provider configurations may not be necessary if you use the tflocal script (as described above). You can save the following configuration in a file named provider.tf and include it in your Terraform configuration.

provider "aws" {
access_key = "test"
secret_key = "test"
region = "us-east-1"
s3_use_path_style = false
skip_credentials_validation = true
skip_metadata_api_check = true
skip_requesting_account_id = true
endpoints {
apigateway = "http://localhost:4566"
apigatewayv2 = "http://localhost:4566"
cloudformation = "http://localhost:4566"
cloudwatch = "http://localhost:4566"
dynamodb = "http://localhost:4566"
ec2 = "http://localhost:4566"
es = "http://localhost:4566"
elasticache = "http://localhost:4566"
firehose = "http://localhost:4566"
iam = "http://localhost:4566"
kinesis = "http://localhost:4566"
lambda = "http://localhost:4566"
rds = "http://localhost:4566"
redshift = "http://localhost:4566"
route53 = "http://localhost:4566"
s3 = "http://s3.localhost.localstack.cloud:4566"
secretsmanager = "http://localhost:4566"
ses = "http://localhost:4566"
sns = "http://localhost:4566"
sqs = "http://localhost:4566"
ssm = "http://localhost:4566"
stepfunctions = "http://localhost:4566"
sts = "http://localhost:4566"
}
}

OpenTofu is an open-source fork of Terraform acting as a drop-in replacement for Terraform, as it’s compatible with Terraform versions 1.5.x and most of 1.6.x. You can use OpenTofu with LocalStack to create and manage your AWS resources with your pre-existing Terraform configurations. You can use the TF_CMD environment variable with tflocal to specify the tofu binary to call, or setup a manual configuration to point the individual services to LocalStack.

Terminal window
TF_CMD=tofu tflocal --help
Output
Usage: tofu [global options] <subcommand> [args]
The available commands for execution are listed below.
The primary workflow commands are given first, followed by
less common or more advanced commands.
...

Terragrunt is an open-source wrapper for Terraform that provides extra tools for keeping your configurations DRY, working with multiple Terraform modules, and managing remote state. You can use Terragrunt with LocalStack to create and manage your AWS resources with your pre-existing Terraform configurations.

A sample terragrunt.hcl configuration file to use with LocalStack is shown below:

generate "provider" {
path = "provider.tf"
if_exists = "overwrite_terragrunt"
contents = <<EOF
provider "aws" {
access_key = "test"
secret_key = "test"
region = "us-east-1"
s3_use_path_style = false
skip_credentials_validation = true
skip_metadata_api_check = true
skip_requesting_account_id = true
endpoints {
apigateway = "http://localhost:4566"
dynamodb = "http://localhost:4566"
iam = "http://localhost:4566"
kinesis = "http://localhost:4566"
lambda = "http://localhost:4566"
s3 = "http://s3.localhost.localstack.cloud:4566"
ses = "http://localhost:4566"
sns = "http://localhost:4566"
sqs = "http://localhost:4566"
sts = "http://localhost:4566"
}
}
EOF
}

You can add more service endpoints to the above configuration as needed, and point them to LocalStack (http://localhost:4566).