Terraform: AWS EC2 with SSM Agent Installed

Terraform is one of the Infrastructure as Code tools used to automate the provisioning of cloud resources. This article explains how to create an EC2 instance with systems manager (SSM) installed using Terraform.

Systems Manager is an AWS service for server management. It is useful for:

  • Automating tasks you would like to run on your ec2 instances e.g. System Upgrades.
  • Configuring multiple servers at once.
  • It also enables users to access ec2 instances without using ssh and key-pairs. This is especially helpful for security since we are not opening up ports for ssh.


  • An AWS account.
  • A user that has generated his/her AWS access key ID and secret access key and permissions to create AWS resources.
  • Have Terraform installed on your respective PC.
  • Manually generated the EC2 Key Pair on your AWS account.
  • This article assumes that the reader has already created a Terraform Module to set up the Network Infrastructure and Security Groups. We can find a guide for this on the link below.


Step 1: Create the Terraform EC2 Module

Create a folder on your PC for Terraform modules. Within the folder you can create other folders to better orgarnise templates. For our case we created the services directory within the modules directory and ec2 directory within the services directory. Then, add the below files to the folder.

  • ec2.tf
  • install-ssm.sh
  • outputs.tf
sudo mkdir modules
cd mkdir modules
sudo mkdir services
cd services
sudo mkdir ec2
cd ec2
touch ec2.tf outputs.tf install-ssm.sh 

On the install-ssm.sh file and add the user-data to install ssm agent on the instance. For example, for a linux2, RHEL and Centos Instance, add the below code to the file:

cd /tmp 
sudo yum install -y https://s3.amazonaws.com/ec2-downloads
sudo systemctl enable amazon-ssm-agent 
sudo systemctl start amazon-ssm-agent

Add the below code on, the ec2.tf file:

module "vpc" {
  source  = "/Users/maureenbarasa/modules/services/vpc"

#Instance Role
resource "aws_iam_role" "test_role" {
  name = "test-ssm-ec2"
  assume_role_policy = <<EOF
  "Version": "2012-10-17",
  "Statement": [
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "ec2.amazonaws.com"
      "Effect": "Allow",
      "Sid": ""

  tags = {
    Name = "test-ssm-ec2"
    createdBy = "MaureenBarasa"
    Owner = "DevSecOps"
    Project = "test-terraform"
    environment = "test"

#Instance Profile
resource "aws_iam_instance_profile" "test_profile" {
  name = "test-ssm-ec2"
  role = "${aws_iam_role.test_role.id}"

#Attach Policies to Instance Role
resource "aws_iam_policy_attachment" "test_attach1" {
  name       = "test-attachment"
  roles      = [aws_iam_role.test_role.id]
  policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"

resource "aws_iam_policy_attachment" "test_attach2" {
  name       = "test-attachment"
  roles      = [aws_iam_role.test_role.id]
  policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM"

#EC2 Instance
resource "aws_instance" "test-ec2" {
    ami = "ami-ID"
    instance_type = "t2.micro"
    key_name = "test-key"
    subnet_id = "${module.vpc.vpc_public_subnet1}"
    vpc_security_group_ids = [module.vpc.vpc_security_group_id]
    monitoring = "true"
    iam_instance_profile = "${aws_iam_instance_profile.test_profile.id}"
    user_data = "${file("/Users/maureenbarasa/modules/services/ec2/install-ssm.sh")}"
    tags = {
        Name = "test-ec2"
        createdBy = "MaureenBarasa"
        Owner = "DevSecOps" 
        Project = "test-terraform"
        environment = "test"

The above ec2 terraform module creates:

  • SSM Instance Role.
  • SSM Instance Profile.
  • The EC2 Instance.

The Template also attaches some AWS managed Policies to the created Instance Role.

N/B: For the EC2 Subnet and Security Group, The module imports or uses values from another module. The VPC Module created from the Template referenced earlier on the article.

The reader/user should customize the below specific items on the template to reflect the what is available on their AWs account.

  • The ami id
  • The Instance Type
  • The EC2 Key-Pair Key Name

Also, the Resources Tags should be customized to meet the user’s specific requirements. You have now successfully created the ec2 module. Next we will look at how to provision resources using the modules created.

The output.tf file is used to define the outputs variables. Add the below code to your outputs.tf file. The outputs variables are important because they can be called from other templates. For example, on our ec2.tf file we have used output variables from the VPC module to define the EC2 subnet ID.

output "ec2-instance" {
  description = "The EC2 instance"
  value       = "${aws_instance.test-ec2.id}"

output "ec2-instance-Profile" {
  description = "The EC2 Instance Profile"
  value       = "${aws_iam_instance_profile.test_profile.id}"

Step 2: Create the Terraform Root Module

Create another folder called Terraform-ec2 and within that folder add 3 files:

  • main.tf
  • version.tf
  • vars.tf

On the vars.tf file add the below code. The file contains variables that describe the users AWS credentials, ec2 key-pair name and the region that the user would like to launch his resources on.

variable "AWS_ACCESS_KEY" {
  default = "**************"

variable "AWS_SECRET_KEY" {
  default = "***************"

variable "AWS_REGION" {
  default = "eu-central-1"

variable "key_name" {
  default = "test-key"

Replace the AWS access and secret key with the user generated AWS access key ID and AWS secret access key, respectively. The user should also change the region default value to the specific AWS region they would like to provision the resources.

On the version.tf file add the below code.

terraform {
  required_version = ">= 0.12" 

Finally, on the main.tf file, Add the below code. The main.tf file calls the terraform modules that will be invoked to create the AWS resources.

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

provider "aws" {
  access_key = var.AWS_ACCESS_KEY
  secret_key = var.AWS_SECRET_KEY
  region = "eu-central-1"

module "vpc" {
  source  = "/Users/maureenbarasa/modules/services/vpc"

module "ec2" {
  source  = "/Users/maureenbarasa/modules/services/ec2"

The main.tf file calls the 2 modules required to provision the EC2 instance:

  • The VPC Module.
  • EC2 Module.

N/B: The respective module source should reflect the user’s respective module directories.

Provision the Resources

To create the infrastructure on your account, On your root module directory, run below commands:

terraform init
terraform plan
terraform apply

The terraform init command initializes our working directory. We should run this command whenever we write a new terraform configuration.

The terraform plan creates a preview of the actions that terraform will perform i.e. the resources that terraform will create.

After reviewing the actions that Terraform will perform, we can now run terraform apply to create the resources. You will be prompted to approve by typing yes.

To destroy everything created with the template, run the below command. The command will preview all resources that will be destroyed. It will also prompt the user to approve by typing yes.

terraform destroy

Important Links

You can find all the code used under:


Other Links Include:





Happy Building!!!

One thought on “Terraform: AWS EC2 with SSM Agent Installed

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s