Bootstrapping

Real AWS accounts come pre-provisioned with default VPCs, KMS keys, and service-linked roles. The SIMFRA_BOOTSTRAP environment variable replicates this setup in Simfra.

Standard Bootstrap

export SIMFRA_BOOTSTRAP=standard

This runs a native bootstrap that creates the following resources in 16 AWS regions (us-east-1, us-east-2, us-west-1, us-west-2, eu-west-1, eu-west-2, eu-west-3, eu-central-1, eu-north-1, ap-southeast-1, ap-southeast-2, ap-northeast-1, ap-northeast-2, ap-south-1, sa-east-1, ca-central-1):

Per Region

Default VPC (172.31.0.0/16) and associated resources:

  • 6 subnets (one per AZ, /20 CIDR blocks)
  • Internet gateway attached to the VPC
  • Main route table with a route to the IGW
  • Default security group
  • Default network ACL
  • DHCP options set

AWS-managed KMS keys (alias/aws/*) for:

  • DynamoDB, EBS, S3, SNS, SQS, Lambda, RDS, CloudWatch Logs, SSM, CloudWatch

Global (Once)

IAM service-linked roles:

  • AWSServiceRoleForSupport (support.amazonaws.com)
  • AWSServiceRoleForTrustedAdvisor (trustedadvisor.amazonaws.com)

Idempotency

When persistence is enabled (SIMFRA_DATA_DIR), standard bootstrap is skipped on restart if any persisted state was found. This prevents duplicate resource creation.

Terraform Bootstrap

Point SIMFRA_BOOTSTRAP at a directory containing .tf files:

export SIMFRA_BOOTSTRAP=/path/to/my/terraform

Simfra runs terraform init and terraform apply against itself using the default account credentials. The Terraform provider is configured automatically via AWS_ENDPOINT_URL.

How It Works

  1. Simfra copies all files from the blueprint directory to a working directory
  2. Sets AWS_ENDPOINT_URL to http://localhost:<port>, plus AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY from the root account
  3. Runs terraform init followed by terraform apply -auto-approve
  4. Collects Terraform outputs and logs the result

Simfra looks for terraform or tofu (OpenTofu) in PATH. The Docker image bundles Terraform.

Terraform State Persistence

When SIMFRA_DATA_DIR is set, the Terraform working directory is $SIMFRA_DATA_DIR/bootstrap/, so the state file survives restarts. Terraform handles its own idempotency - terraform apply on subsequent starts only creates/updates resources that changed.

When SIMFRA_DATA_DIR is not set, a temporary directory is used and state is lost on exit.

Example Blueprint

A minimal bootstrap that creates an S3 bucket and a DynamoDB table:

terraform {
  required_providers {
    aws = {
      source = "hashicorp/aws"
    }
  }
}

provider "aws" {
  region = "us-east-1"
}

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

resource "aws_dynamodb_table" "locks" {
  name         = "terraform-locks"
  billing_mode = "PAY_PER_REQUEST"
  hash_key     = "LockID"

  attribute {
    name = "LockID"
    type = "S"
  }
}

output "bucket_name" {
  value = aws_s3_bucket.data.id
}

Timeout

Terraform bootstrap has a 5-minute timeout. If terraform apply does not complete within this window, bootstrap fails and Simfra exits.

Bootstrap vs Implicit Resource Creation

Bootstrap creates account-level default resources that AWS pre-provisions. This is separate from implicit resource creation, where individual API calls create dependent resources as side effects.

For example:

  • Bootstrap creates the default VPC with its subnets, IGW, route table, security group, and NACL
  • CreateVpc (EC2 API) implicitly creates a main route table, default security group, and default NACL for the new VPC

Both behaviors are simulated. Bootstrap runs once at startup; implicit creation happens on every relevant API call.

No Bootstrap

When SIMFRA_BOOTSTRAP is empty (the default), Simfra starts with no pre-existing resources. Every resource must be created explicitly via API calls, Terraform, or the admin API. This is useful for testing from a clean slate.