Sign in
Menu
Start free trial

AWS EC2 Instance Terraform module

Terraform module which creates an EC2 instance on AWS.

SWUbanner

Usage

Single EC2 Instance

module "ec2_instance" {
  source  = "terraform-aws-modules/ec2-instance/aws"

  name = "single-instance"

  instance_type = "t3.micro"
  key_name      = "user1"
  monitoring    = true
  subnet_id     = "subnet-eddcdzz4"

  tags = {
    Terraform   = "true"
    Environment = "dev"
  }
}

Multiple EC2 Instance

module "ec2_instance" {
  source  = "terraform-aws-modules/ec2-instance/aws"

  for_each = toset(["one", "two", "three"])

  name = "instance-${each.key}"

  instance_type = "t3.micro"
  key_name      = "user1"
  monitoring    = true
  subnet_id     = "subnet-eddcdzz4"

  tags = {
    Terraform   = "true"
    Environment = "dev"
  }
}

Spot EC2 Instance

module "ec2_instance" {
  source  = "terraform-aws-modules/ec2-instance/aws"

  name = "spot-instance"

  create_spot_instance = true
  spot_price           = "0.60"
  spot_type            = "persistent"

  instance_type = "t3.micro"
  key_name      = "user1"
  monitoring    = true
  subnet_id     = "subnet-eddcdzz4"

  tags = {
    Terraform   = "true"
    Environment = "dev"
  }
}

Known limitations (Terraform/OpenTofu, not this module)

A few requests come up again and again and cannot be implemented by this module, or by any module: Terraform requires lifecycle arguments to be literal values inside the resource block. hashicorp/terraform#18367 has been open since 2018, #22544 since 2019, and opentofu/opentofu#1329 is the same request for OpenTofu.

  • Terraform wants to replace my EC2 instance because the AMI changed - Native option: pin the AMI id rather than resolving the most recent one. Otherwise fork and add ignore_changes = [ami].

Compliance.tf serves this module with these rules applied at download time, on top of whatever your organization already has enabled there. Inputs and outputs do not change; the source line does. Drop the version argument and pin the release you use by adding &version= and that release number to the URL. To get started, register a free compliance.tf account and configure an access token:

source = "https://registry.compliance.tf/terraform-aws-modules/ec2-instance/aws?add_rules=lifecycle_ignore_ami_changes"

The full workaround for each item above, and the exact diff each rule makes, are in the compliance.tf docs for this module. To preview a diff without an account, open this module in the Rules Playground.

Disclosure: written by this module's maintainer, who also builds compliance.tf.

Examples

Make an encrypted AMI for use

This module does not support encrypted AMI's out of the box however it is easy enough for you to generate one for use

This example creates an encrypted image from the latest ubuntu 20.04 base image.

provider "aws" {
  region = "us-west-2"
}

data "aws_ami" "ubuntu" {
  most_recent = true
  owners      = ["679593333241"]

  filter {
    name   = "name"
    values = ["ubuntu-minimal/images/hvm-ssd/ubuntu-focal-20.04-*"]
  }

  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }
}

resource "aws_ami_copy" "ubuntu_encrypted_ami" {
  name              = "ubuntu-encrypted-ami"
  description       = "An encrypted root ami based off ${data.aws_ami.ubuntu.id}"
  source_ami_id     = data.aws_ami.ubuntu.id
  source_ami_region = "eu-west-2"
  encrypted         = true

  tags = { Name = "ubuntu-encrypted-ami" }
}

data "aws_ami" "encrypted-ami" {
  most_recent = true

  filter {
    name   = "name"
    values = [aws_ami_copy.ubuntu_encrypted_ami.id]
  }

  owners = ["self"]
}

Conditional creation

The following combinations are supported to conditionally create resources:

module "ec2_instance" {
  source  = "terraform-aws-modules/ec2-instance/aws"

  # Disable creation of EC2 and all resources
  create = false

  # Enable creation of spot instance
  create_spot_instance = true

  # Enable creation of EC2 IAM instance profile
  create_iam_instance_profile = true

  # Disable creation of security group
  create_security_group = false

  # Enable creation of elastic IP
  create_eip = true

  # ... omitted
}

Notes

  • network_interface can't be specified together with vpc_security_group_ids, associate_public_ip_address, subnet_id. See complete example for details.
  • In regards to spot instances, you must grant the AWSServiceRoleForEC2Spot service-linked role access to any custom KMS keys, otherwise your spot request and instances will fail with bad parameters. You can see more details about why the request failed by using the awscli and aws ec2 describe-spot-instance-requests

Authors

Module is maintained by Anton Babenko with help from these awesome contributors.

License

Apache 2 Licensed. See LICENSE for full details.

Additional information for users from Russia and Belarus