Creating AWS EC2 Instances and Security Rules with Terraform (5/5)

Tutorial and source code explaining how to manage AWS EC2 Instances and Security with Terraform.

EC2 Instances and Resource Security

This is the continuation of a AWS Terraform demo to create a VPC in AWS with an EC2 instance connected to MariaDB database running in RDS using a single Terraform plan.

Prerequisites and source code:

Creating AWS EC2 Instances with Terraform

EC2 instances are defined using the terraform.tfvars, some values (ami, vpc_security_group_ids, and subnet_id) are derived from modules output so the definition is in the file as terraform.tfvars doesn’t allow interpolation.

    # WP PRO

  aws_ec2_pro_pub_wp_01 = {
    name              = "ditwl-ec2-pro-pub-wp01"
    ami               = "" #Uses
    instance_type     = "t2.micro" #AWS Free Tier: 750 hours per month of Linux, RHEL, or SLES t2.micro instance usage
    availability_zone = "us-east-1a"
    key_name          = "ditwl_kp_infradmin"
    # vpc_security_group_ids = SEE TF file
    # subnet_id         = SEE TF file
    associate_public_ip_address = true

    root_block_device_size        = 8

    # See
    root_block_device_volume_type = "gp2"

    tag_private_name  = "ditwl-ec2-pro-pub-wp-01"
    tag_public_name   = "www"
    tag_app           = "wp"
    tag_app_id        = "wp-01"
    tag_os            = "ubuntu"
    tag_os_id         = "ubuntu-16"
    tags_environment  = "pro"
    tag_cost_center   = "ditwl-permanent"
    tags_volume       = "ditwl-ec2-pro-pub-wp-01-root"


  # WP PRO Security Group
  aws_sg_ec2_pro_pub_wp_01 = {
    sec_name        = "ditwl-sg-ec2-pro-pub-01"
    sec_description = "ditwl - WP server access rules - Pub, Env: PRO"
    allow_all_outbound = false

  aws_sr_ec2_pro_pub_wp_01_internet_to_80 = {
    type              = "ingress"
    from_port         = 80
    to_port           = 80
    protocol          = "tcp"
    cidr_blocks       = ""
    description       = "Access from Internet to port 80"

  aws_sr_ec2_pro_pub_wp_01_internet_to_443 = {
    type              = "ingress"
    from_port         = 443
    to_port           = 443
    protocol          = "tcp"
    cidr_blocks       = ""
    description       = "Access from Internet to port 443"

All EC2 instance names and their Security Rules and Groups follow a standardized naming pattern.

Private Key for the EC2 Instance

In order to access the created Linux instances in AWS you will need an SSH client. Authentication will use a private key, and in the case of Ubuntu a username named “ubuntu”.

The private key needs to be registered in AWS EC2 console, it can be uploaded to the console or created using a wizard.

  1. Visit the AWS console
  2. Select the region where instances will be created (as Key Pais are unique to each region),
  3. Go to EC2 AWS web console
  4. Go to Network & Security and Key Pairs.
  5. Create a new Key Pair and name it ditwl_kp_infradmin. AWS generates a PEM file that you should store in a safe place.
  6. Save the downloaded pem file in ${HOME}/keys/ditwl_kp_infradmin.pem. It will be used by Ansible in the next tutorial.

Launching AWS EC2 Instances with Terraform

Having configured most of the values for the instance in the terraform.tfvars, now the file makes use of Terraform modules to create the resources.

The Terraform module /modules/aws/ec2/instance/add is used to create the EC2 instance. Most of the variables come from the aws_ec2_pro_pub_wp_01 variable definition from terraform.tfvars and the rest are interpolations to other resources:

  • ami = “${}”. Uses the output from the data source aws_ami. See Route 53 and AMI Lookup for an explanation.
  • disable_api_termination = “${var.is_production ? true : false}”. Uses the value from is_production variable to prevent EC2 instance destruction. See Avoiding AWS instance destroy with Terraform for an explanation.
  • vpc_security_group_ids = [“${}”, “${}”] is a list of security groups that will allow access to the instance.
  • register_dns_private = true and register_dns_public = true are used for Instance registration in private and public DNS. See Registering EC2 instances in Route 53 for an explanation.
  # Create WP instance
  module "aws_ec2_pro_pub_wp_01" {
    source            = "./modules/aws/ec2/instance/add"
    name              = var.aws_ec2_pro_pub_wp_01["name"]
    ami               =
    instance_type     = var.aws_ec2_pro_pub_wp_01["instance_type"]
    availability_zone = var.aws_ec2_pro_pub_wp_01["availability_zone"]
    key_name          = var.aws_ec2_pro_pub_wp_01["key_name"]
    disable_api_termination = var.is_production ? true : false
    vpc_security_group_ids = [,]
    subnet_id         =
    associate_public_ip_address = var.aws_ec2_pro_pub_wp_01["associate_public_ip_address"]
    instance_tags     = {}
    tag_private_name  = var.aws_ec2_pro_pub_wp_01["tag_private_name"]
    tag_public_name   = var.aws_ec2_pro_pub_wp_01["tag_public_name"]
    tag_app           = var.aws_ec2_pro_pub_wp_01["tag_app"]
    tag_app_id        = var.aws_ec2_pro_pub_wp_01["tag_app_id"]
    tag_os            = var.aws_ec2_pro_pub_wp_01["tag_os"]
    tag_os_id         = var.aws_ec2_pro_pub_wp_01["tag_os_id"]
    tags_environment  = var.aws_ec2_pro_pub_wp_01["tags_environment"]
    tag_cost_center   = var.aws_ec2_pro_pub_wp_01["tag_cost_center"]

    register_dns_private = true
    route53_private_zone_id =

    register_dns_public = true
    route53_public_zone_id =

    root_block_device = {
      volume_size           = var.aws_ec2_pro_pub_wp_01["root_block_device_size"]
      volume_type           = var.aws_ec2_pro_pub_wp_01["root_block_device_volume_type"]
      delete_on_termination = var.is_production ? false : true #If production, Do not delete!

    volume_tags       = {
      Name = var.aws_ec2_pro_pub_wp_01["name"]

    ignore_changes = ["ami"]


Resource Security in AWS with Terraform

Securing AWS VPC resources with Terraform makes use of 3 modules:

  • modules/aws/security/group: creates a security group and returns the ID to be used in rules and instance association.
  • modules/aws/security/rule/cidr_blocks: creates a security rule associated with a previously created security group, the cidr_blocks module uses an IP address range as the source for the traffic.
  • modules/aws/security/rule/source_group: creates a security rule associated with a previously created security group, the source_group module uses another security group as source. See RDS creation for an example of its usage.

See AWS Security Groups’ Best Practices.

The following illustration shows the security groups and rules applied to each AWS resource.

List of security rules
AWSC Security rules applied to EC2 and RDS instances

Continue the Terraform and Ansible demo, see:

terraform-aws-ec2-rds-basic-free - ITWL_AWS_Terraform_VPC_WP_Security1.png
Table of Contents
Primary Item (H2)Sub Item 1 (H3)Sub Item 2 (H4)
Sub Item 3 (H5)
Sub Item 4 (H6)

Related Cloud Tutorials

AWS Security Groups’ Best Practices
AWS Security Groups are virtual firewalls that control inbound and outbound traffic to and from Amazon Web Services (AWS) resources, such as EC2 and RDS instances.
AWS and Terraform Naming Best Practices
Terraform and AWS resource naming should follow a company standard. Each company has different requirements and the standard should be adjusted.
How To Debug Terraform
Enable Terraform debug Terraform uses the value from the environment variable TF_LOG to define the LOG level. Available values are TRACE, DEBUG, INFO, WARN or ERROR. Additionally, you can specify a destination file for the log by setting the environment variable TF_LOG_PATH to the full path of the desired destination. Set the debug variables and […]
AWS Tagging Best Practices
Effective infrastructure resource tagging can greatly improve management, IaC, monitoring and cost visibility in AWS.
How to Deploy Applications in Kubernetes using Terraform
How to publish multiple replicas of an Application (from the Docker Registry) and create a NodePort in Kubernetes using Terraform (in 10 seconds)
Terraform logo
HashiCorp Configuration Language HCL is a domain-specific language developed by HashiCorp, a company known for its infrastructure automation tools such as Terraform, Vault, Consul, and Nomad. HCL is designed specifically for writing configuration files that define infrastructure components and their settings. It is used in HashiCorp’s suite of tools to create and manage infrastructure as […]
AWS Terraform module
Infrastructure as Code IaC is an approach to managing and provisioning computing infrastructure through machine-readable code and automation, rather than manual processes. In IaC, infrastructure is defined, configured, and managed using code, which can be version-controlled and treated like any other software application. IaC involves: IaC provides several benefits, including improved efficiency, reduced manual errors, […]
AWS S3, is a highly scalable and durable object storage used for data storage, backup, content distribution, data archiving, and as a foundation for building cloud-native applications.
Amazon Elastic Compute Cloud, is a web service offered by Amazon Web Services (AWS) that provides resizable and scalable compute capacity in the cloud. In simple terms, AWS EC2 allows you to launch and manage virtual machines, known as instances, in the AWS cloud.
AWS AMI, or Amazon Machine Image, is a pre-configured virtual machine image used to create and launch Amazon Elastic Compute Cloud (EC2) instances
1 2 3

Javier Ruiz

IT Wonder Lab tutorials are based on the rich and diverse experience of Javier Ruiz, who founded and bootstrapped a SaaS company in the energy sector. His company, which was later acquired by a NASDAQ traded company, managed over €2 billion per year of electricity for prominent energy producers across Europe and America. Javier has more than 20 years of experience in building and managing IT companies, developing cloud infrastructure, leading cross-functional teams, and transitioning his own company from on-premises, consulting, and custom software development to a successful SaaS model that scaled globally.

2 comments on “Creating AWS EC2 Instances and Security Rules with Terraform (5/5)”

Leave a Reply

Your email address will not be published. Required fields are marked *

linkedin facebook pinterest youtube rss twitter instagram facebook-blank rss-blank linkedin-blank pinterest youtube twitter instagram