Terraform
Introduction
Section titled “Introduction”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
lstk terraform(aliaslstk tf) 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 lstk terraform and a manual configuration example.
lstk terraform
Section titled “lstk terraform”lstk terraform (alias lstk tf) runs Terraform against LocalStack. It uses the Terraform Override mechanism and creates a temporary file localstack_providers_override.tf to configure the endpoints for the AWS provider section, then forwards your arguments to the real terraform binary.
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 Terraform configuration
Section titled “Create a Terraform configuration”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"}Install lstk
Section titled “Install lstk”To use lstk terraform, install lstk by following the lstk installation instructions.
You’ll also need the terraform CLI itself installed and on your PATH.
Once installed, you can use lstk terraform, which has the same interface as the terraform command line.
lstk terraform --helpUsage: terraform [global options] <subcommand> [args]...Deploy the Terraform configuration
Section titled “Deploy the Terraform configuration”Start your LocalStack container using your preferred method. Initialize Terraform using the following command:
lstk terraform initYou can now provision the S3 bucket specified in the configuration:
lstk terraform applyConfiguration
Section titled “Configuration”The lstk terraform command supports several options and environment variables beyond what is available with standard terraform. Flags that are specific to lstk terraform must appear before the Terraform action:
| Option | Description |
|---|---|
--region <region> |
Deployment region |
--account <id> |
Target AWS account id (12 digits) |
| Environment Variable | Default value | Description |
|---|---|---|
AWS_ENDPOINT_URL |
- | Override the auto-resolved LocalStack endpoint |
LSTK_TF_CMD |
terraform |
Binary to invoke, e.g. tofu |
LSTK_TF_OVERRIDE_FILE_NAME |
localstack_providers_override.tf |
Override file name |
LSTK_TF_DRY_RUN |
- | When set, generate the override file but do not run Terraform |
AWS_REGION |
- | Fallback for --region |
AWS_ACCESS_KEY_ID |
- | Fallback for --account |
Manual Configuration
Section titled “Manual Configuration”Instead of using lstk terraform, you have the option to manually configure the local service endpoints and credentials.
The following sections will provide detailed steps for this manual configuration.
General Configuration
Section titled “General 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"}Request Management
Section titled “Request Management”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}Services
Section titled “Services”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"}Final Configuration
Section titled “Final Configuration”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
endpoints { s3 = "http://s3.localhost.localstack.cloud:4566" }}
resource "aws_s3_bucket" "test-bucket" { bucket = "my-bucket"}Endpoint Configuration
Section titled “Endpoint Configuration”Here’s a configuration example with additional service endpoints.
Please note that these provider configurations may not be necessary if you use lstk terraform (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 = true skip_credentials_validation = true skip_metadata_api_check = 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
Section titled “OpenTofu”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 LSTK_TF_CMD environment variable with lstk terraform to specify the tofu binary to call, or setup a manual configuration to point the individual services to LocalStack.
LSTK_TF_CMD=tofu lstk terraform --helpUsage: tofu [global options] <subcommand> [args]
The available commands for execution are listed below.The primary workflow commands are given first, followed byless common or more advanced commands....Terragrunt
Section titled “Terragrunt”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.
Configuration
Section titled “Configuration”A sample terragrunt.hcl configuration file to use with LocalStack is shown below:
generate "provider" { path = "provider.tf" if_exists = "overwrite_terragrunt" contents = <<EOFprovider "aws" { access_key = "test" secret_key = "test" region = "us-east-1" s3_use_path_style = true skip_credentials_validation = true skip_metadata_api_check = 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).