---
# System prepended metadata

title: AWS using Terraform

---


[toc]

### Terraform HCL

#### Write a tf file to create an EC2 instance in us-east-1 region
````yaml=
## Create an EC2 instance in us-east-1

provider "aws" {
access_key = "<Your_Access_Key>"
secret_key = "<Your_Secret_Key>"
token = "<Your_Security_Token>"
region = "us-east-1"
}

resource "aws_instance" "terraform_demo" {
ami = "ami-02f3f602d23f1659d"
instance_type = "t2.micro"
}
````

#### Add the "Name" tag to your EC2 instance
````yaml=
## Add a user defined tag to your instance

provider "aws" {
access_key = "<Your_Access_Key>"
secret_key = "<Your_Secret_Key>"
token = "<Your_Security_Token>"
region = "us-east-1"
}

resource "aws_instance" "terraform_demo" {
ami = "ami-02f3f602d23f1659d"
instance_type = "t2.micro"
    tags = {
      Name = "terraform-node"
    }
}

Apply changes:
terraform plan
terraform apply
or 
terraform apply --auto-approve

Validate changes:
Go to AWS console --> EC2 Dashboard --> instances
Your instance name should be changed to "terraform-node"
```` 

#### Attach an existing security group to the instance
````yaml=
provider "aws" {
access_key  = "your accesskey"
secret_key  = "yoursecretkey"
token       = "yourtoken"
region      = "us-east-1"
}

resource "aws_instance" "sl-tf-web" {
  ami           = "ami-0f34c5ae932e6f0e4" 
  instance_type = "t2.micro"
  vpc_security_group_ids = ["sg-0d3359a397ff3a1f1"]
      tags = {
        Name  = "ec2-sg-web"
        env   = "dev"
      }
}
````

#### Providing User data for EC2 instances [inline]
````yaml=
provider "aws" {
access_key  = "your accesskey"
secret_key  = "yoursecretkey"
token       = "yourtoken"
region      = "us-east-1"
}

resource "aws_instance" "sl-tf-web" {
  ami           = "ami-0f34c5ae932e6f0e4" 
  instance_type = "t2.micro"
  vpc_security_group_ids = ["sg-0d3359a397ff3a1f1"]
      tags = {
        Name  = "ec2-userdata-inline"
        env   = "dev"
      }
  user_data = <<EOF
    #!/bin/bash
    yum update -y
    yum install -y httpd.x86_64
    systemctl start httpd.service
    systemctl enable httpd.service
    echo “Welcome to Simplilearn CMAT from $(hostname -f)” > /var/www/html/index.html
  EOF
}
````

#### Providing User data for EC2 instances [via script file]
````yaml=
provider "aws" {
access_key  = "your accesskey"
secret_key  = "yoursecretkey"
token       = "yourtoken"
region      = "us-east-1"
}

resource "aws_instance" "sl-tf-web" {
  ami           = "ami-0f34c5ae932e6f0e4" 
  instance_type = "t2.micro"
  vpc_security_group_ids = ["sg-0d3359a397ff3a1f1"]
      tags = {
        Name  = "ec2-userdata-script"
        env   = "dev"
      }
  user_data = "${file("myscript.sh")}" 
  
}
````
:arrow_right: *For above userdata Make sure that you have myscript.sh file created in the same Terraform directory*

##### Sample user data script
```sh=
## vi mycript.sh

#!/bin/bash
yum update -y
yum install -y httpd.x86_64
systemctl start httpd.service
systemctl enable httpd.service
echo “Welcome to Simplilearn CMAT from $(hostname -f)” > /var/www/html/index.html
```

##### Validate user data

:::success
**You can check the user data of the instance as follows:**

Select the instance --> Click on **Actions** --> go to **instance settings** --> Click on **Edit user data**

![](https://hackmd.io/_uploads/r1j7jB4o2.png)

You should now be able to see the user data of the instance:
![](https://hackmd.io/_uploads/ByENiSVj2.png)

:arrow_right: *If you want to edit the user data then you have to stop the instance first*
:::


#### Create an EC2 instance along with a new Security Group (Allow incoming ports 80/443/22 and all outgoing)
```hcl=
## Create an EC2 instance along with a new security group (80/443/22)

provider "aws" {
access_key  = "your accesskey"
secret_key  = "yoursecretkey"
token       = "yourtoken"
region      = "us-east-1"
}

resource "aws_security_group" "web-sg" {
  name = "web-sg-tf"
  description = "Allow HTTP, HTTPS and SSH traffic via Terraform"

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_instance" "sl-tf-web" {
  ami           = "ami-0f34c5ae932e6f0e4" 
  instance_type = "t2.micro"
  vpc_security_group_ids = [aws_security_group.web-sg.id]
      tags = {
        Name  = "ec2-with-sg"
        env   = "dev"
      }
  user_data = "${file("myscript.sh")}" 
  
}
```
##### Sample userdata script
```hcl=
## vi myscript.sh

#!/bin/bash
yum update -y
yum install -y httpd.x86_64
systemctl start httpd.service
systemctl enable httpd.service
echo “Welcome to Simplilearn CMAT from $(hostname -f)” > /var/www/html/index.html
```

##### Once done this is how your directory should look like:
```hcl=
sk@ec2-with-sg:$ tree
.
├── main.tf
├── myscript.sh
```

:::warning
**Apply changes**
```hcl=
terraform plan
terraform apply
or 
terraform apply --auto-approve
```

**Validate changes**
- Go to AWS console --> EC2 Dashboard --> instances.
- Capture the public IP address of the newly created instance and access it on port 80 via a web browser.
:::

#### Create similar multiple resources using "count" function
```hcl=
## Create an EC2 instance along with a new security group (80/443/22)

provider "aws" {
access_key  = "your accesskey"
secret_key  = "yoursecretkey"
token       = "yourtoken"
region      = "us-east-1"
}

resource "aws_security_group" "web-sg" {
  name = "web-sg-tf"
  description = "Allow HTTP, HTTPS and SSH traffic via Terraform"

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_instance" "sl-tf-web" {
  ami           = "ami-0f34c5ae932e6f0e4" 
  instance_type = "t2.micro"
  vpc_security_group_ids = [aws_security_group.web-sg.id]
  count = 3
      tags = {
        Name  = "ec2-count-${count.index}"
        env   = "dev"
      }
  user_data = "${file("myscript.sh")}" 
  
}

output "instance-public-ip_1" {
  value = aws_instance.sl-tf-web[0].public_ip
}

output "instance-public-ip_2" {
  value = aws_instance.sl-tf-web[1].public_ip
}

output "instance-public-ip_3" {
  value = aws_instance.sl-tf-web[2].public_ip
}

output "instance-public-ip_4" {
  value = aws_instance.sl-tf-web[3].public_ip
}
```
:arrow_right: *Apply usual terraform workflow (init/plan/apply) and validate the changes*

#### Create a proper folder structure by segragating the files:


##### provider.tf
```hcl=
provider "aws" {
access_key  = "your accesskey"
secret_key  = "yoursecretkey"
token       = "yourtoken"
region      = "us-east-1"
}
```

##### resources.tf
```hcl=
resource "aws_security_group" "web-sg" {
  name = "web-sg-tf"
  description = "Allow HTTP, HTTPS and SSH traffic via Terraform"

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_instance" "sl-tf-web" {
  ami           = "ami-0f34c5ae932e6f0e4" 
  instance_type = "t2.micro"
  vpc_security_group_ids = [aws_security_group.web-sg.id]

      tags = {
        Name  = "mywebnode1"
        env   = "dev"
      }
  user_data = "${file("myscript.sh")}" 
  
}
```
##### output.tf
```hcl=
output "instance-public-ip_4" {
  value = aws_instance.sl-tf-web.public_ip
}
```
Your directory should look like the following now:
```hcl=
sk@segretate:$ tree
.
├── myscript.sh
├── output.tf
├── provider.tf
├── resources.tf
```
:arrow_right: *Apply usual terraform workflow (init/plan/apply) and validate the changes*

#### Alternate provider definition using aws-cli
##### Steps to perform
:::warning
- Create a new IAM user
- Create new security credentials (access key and secret access key) for this newly created IAM user
- Copy the credentials in a text editor
- Install AWSCLI
- Configure AWSCLI with the security credentials of the user you created in earlier steps
:::
:arrow_right: ***Please make sure not to use credentials from Simplilearn LMS***


##### Install AWSCLI
:::warning
Use the following link to install the cli on your system depending in which OS you are on:
https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html
:::
##### Configure AWSCLI
```hcl=
$ aws configure
AWS Access Key ID [None]: AKIAIOSFODNN7EXAMPLE
AWS Secret Access Key [None]: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
Default region name [None]: us-west-2
Default output format [None]: json
``` 
:arrow_right: *Please note that you need to have your access key and secret access key handy which you acquired in [this](https://hackmd.io/@skm23/cmat/https%3A%2F%2Fhackmd.io%2F34qN0C8nQVeW4djwHtPdDA%3Fview#How-to-get-access_key-and-secret_access_key-in-your-own-AWS-accounts) step.*

##### Update your provider definition to use local awscli profile
```hcl=
provider "aws" {
  profile = "sladmin"
  region  = "us-east-1"
}
```

##### List existing AWSCLI profiles on current system:
```hcl=
$ aws configure list-profiles ## Works on MacOS and Windows
default
sladmin
sldev

For Linux, if above does not work, use the following:

$ aws configure list
```

### Variables in Terraform

#### Working with a Single variable

##### Define varibles in varibles.tf

```hcl=
variable "instance_name" {
  description   = "Instance name to be displayed on aws console"
  type          = string
  default       = "nodeviatf"
}
```
##### Call the variables in terraform block

```hcl=
resource "aws_security_group" "web-sg" {
  name = "web-sg-tf"
  description = "Allow HTTP, HTTPS and SSH traffic via Terraform"

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_instance" "sl-tf-web" {
  ami           = "ami-0f34c5ae932e6f0e4" 
  instance_type = "t2.micro"
  vpc_security_group_ids = [aws_security_group.web-sg.id]

      tags = {
        Name  = var.instance_name
        env   = "dev"
      }
  
}
```
:arrow_right: Apply the changes and verify in AWS Console

##### Override the default variables on the command line:
```yaml=
Syntax:
terraform apply -var "variable_name=variable=value"

Example:
terraform apply -var "instance_name=taggedoncli"
```

#### Terraform tfvars file

##### Create a tfvars file and initialize the variables

```hcl=
## prodvars.tfvars

instance_type = "t2.micro"
instance_name = "prodinstance"
```

```hcl=
## devvars.tfvars

instance_type = "t2.micro"
instance_name = "devinstance"
```

##### Run the following command to initialize the variables from tfvars file
```yaml=
terraform apply -var-file="prodvars.tfvars"
```
#### auto.tfvars files
:::info
If we use extension ".auto.tfvars" for the variables files, then they would be loaded automatically and -var-file flag on the command line would not be needed.
:::

:::warning
Rename one of the "tfvars" files created above to "auto.tfvars". For example:
```hcl=
mv devvars.tfvars devvars.auto.tfvars
```
Once done, run terraform apply again. You should see devvars variables getting initialized automatically without the need for -var-file flag with terraform CLI.
:::


### Terraform States

#### Local states

````yaml=
labsuser@controller:~/terra-docs/ec2-with-sg$ terraform state
Subcommands:
    list                List resources in the state
    mv                  Move an item in the state
    pull                Pull current state and output to stdout
    push                Update remote state from a local state file
    replace-provider    Replace provider in the state
    rm                  Remove instances from the state
    show                Show a resource in the state
````

#### Understanding terraform State files (Local)
##### before terraform init
````
labsuser@controller:~/terra-docs/terra-state$ ls -al
total 28
drwxrwxr-x 3 labsuser labsuser 4096 Mar 26 14:17 .
drwxrwxr-x 6 labsuser labsuser 4096 Mar 26 14:02 ..
-rw-rw-r-- 1 labsuser labsuser  708 Mar 26 14:03 main.tf
````
##### terraform init/plan
````
labsuser@controller:~/terra-docs/terra-state$ ls -al
total 28
drwxrwxr-x 3 labsuser labsuser 4096 Mar 26 14:17 .
drwxrwxr-x 6 labsuser labsuser 4096 Mar 26 14:02 ..
drwxr-xr-x 3 labsuser labsuser 4096 Mar 26 14:04 .terraform
-rw-r--r-- 1 labsuser labsuser 1377 Mar 26 14:04 .terraform.lock.hcl
-rw-rw-r-- 1 labsuser labsuser  708 Mar 26 14:03 main.tf
````

##### terraform apply (only once)
````
labsuser@controller:~/terra-docs/terra-state$ ls -al
total 28
drwxrwxr-x 3 labsuser labsuser 4096 Mar 26 14:17 .
drwxrwxr-x 6 labsuser labsuser 4096 Mar 26 14:02 ..
drwxr-xr-x 3 labsuser labsuser 4096 Mar 26 14:04 .terraform
-rw-r--r-- 1 labsuser labsuser 1377 Mar 26 14:04 .terraform.lock.hcl
-rw-rw-r-- 1 labsuser labsuser  708 Mar 26 14:03 main.tf
-rw-rw-r-- 1 labsuser labsuser 4437 Mar 26 14:17 terraform.tfstate
````
##### terraform apply (twice)
````
labsuser@controller:~/terra-docs/terra-state$ ls -al
total 36
drwxrwxr-x 3 labsuser labsuser 4096 Mar 26 14:22 .
drwxrwxr-x 6 labsuser labsuser 4096 Mar 26 14:02 ..
drwxr-xr-x 3 labsuser labsuser 4096 Mar 26 14:04 .terraform
-rw-r--r-- 1 labsuser labsuser 1377 Mar 26 14:04 .terraform.lock.hcl
-rw-rw-r-- 1 labsuser labsuser  708 Mar 26 14:20 main.tf
-rw-rw-r-- 1 labsuser labsuser 4439 Mar 26 14:22 terraform.tfstate
-rw-rw-r-- 1 labsuser labsuser 4437 Mar 26 14:22 terraform.tfstate.backup
````

##### Activity - Remove a resource from Terraform state
````yaml=!
Create an instance and security group using previously used tf files.

check terraform state:
terraform state list

Remove Security from terraform state:
terraform state rm <sg-id>

verify terraform state again:
terraform state list

Run terraform destroy:
terraform destroy -auto-approve

Validate:
Check on AWS console. EC2 instance should be terminated already however Security group should still be present and not destroyed as it was no longer managed as part of "terraform state".
````

#### Using Amazon S3 as backend for terraform "remote state"

##### Create a backend definition (backend.tf)
```hcl=
terraform {
  backend "s3" {
    bucket  = "tfstate-sk"
    key     = "dev/tfstate"
    region  = "us-east-1"
    profile = "sladmin"
  }
}
```
:arrow_right: *Profile name should match with what you have configured when configuring AWSCLI. For example if you have not mentioned any profile name then it should be "default". You can check your profile name in "~/.aws/config".*

##### Sample backend file (for simplilearn labs)
````yaml=
terraform {
  backend "s3" {
    bucket         = "<s3-bucket-name>"
    key            = "<bucket-prefix>"
    region         = "us-east-1"
    access_key     = "<Your-access-key>"
    secret_key     = "<Your-secret-key>"
    token          = "<Your-temp-token>"
    }
}
````

##### provider.tf
```hcl=
provider "aws" {
  profile = "sladmin"
  region  = "us-east-1"
}
```
:arrow_right: *Profile name should match with what you have configured when configuring AWSCLI. For example if you have not mentioned any profile name then it should be "default". You can check your profile name in "~/.aws/config".*

##### resource.tf
```hcl=
resource "aws_instance" "sl-tf-web" {
  ami                    = "ami-0f34c5ae932e6f0e4"
  instance_type          = "t2.micro"

  tags = {
    Name = "webnode-v1"
    env  = "dev"
  }
  
}
```
:arrow_right: *Apply usual terraform workflow (init/plan/apply) and validate the changes*
*You Should be able to see a new file with your terraform state in the S3 bucket/prefix you mentioned in the backend definition*

#### Terraform remote state on Terraform Cloud

##### Complete the following activity from Hashicorp official tutorials
:::warning
https://developer.hashicorp.com/terraform/tutorials/aws-get-started/aws-remote
:::

##### Additional practice for terraform cloud
:::warning
https://developer.hashicorp.com/terraform/tutorials/cloud
:::


### Working with Terraform provisioners


#### Working with Local Provisioner (Local-exec)
##### Provider.tf
```hcl=
provider "aws" {
  profile = "sladmin"
  region  = "us-east-1"
}
```

##### resources.tf
```hcl=
resource "aws_instance" "web" {
  ami           = "ami-0f34c5ae932e6f0e4" 
  instance_type = "t3.micro"
  
  tags = {
    Name = "terraform-node"
    env  = "dev"
  }
  
  provisioner "local-exec" {
    command = "touch localexec.txt"
  }
  provisioner "local-exec" {
    command = "echo ${self.private_ip} >> instance_ips.txt"
  }
  provisioner "local-exec" {
    command = "echo ${self.public_ip} >> instance_ips.txt"
  }
}
```
##### Folder structure before terraform apply
```yaml=
sk@local-exec:$ tree
.
├── provider.tf
├── resource.tf
```

:arrow_right: *Apply usual terraform workflow (init/plan/apply) and validate the changes*

##### Folder structure after terraform apply
```yaml=
sk@local-exec:$ tree
.
├── instance_ips.txt
├── localexecdemo.txt
├── provider.tf
├── resource.tf
└── terraform.tfstate
```

#### Working with Remote Provisioner (remote-exec)

##### Steps to be performed

:::info
- Create the EC2 instance
    - Make sure the Security group has incoming ports (80/443/22) open
    - make sure the public key is copied on the node (asymmetric keypair)
- copy a script file from controller to the node (nginx.sh)
- SSH into the instance
- run the nginx.sh script
- validate
    - SSH into the instance and check nginx service
    - check if nginx is accessiebl via the public-IP in a brower


#### Files needed
    - provider.tf
    - resources.tf
    - nginx.sh
    - asymmetric keypair
    - outputs (optional)
:::
:::warning
1. Create provider.tf file and add your access-key and secret-access-key for authentication to AWS account
2. Create create-ec2.tf file which will contain the resource definition
3. Create nginx.sh script file which will be copied to newly created ec2 instance and run to install and configure nginx on the newly created EC2 node.
4. Create outputs.tf to get public ip and public DNS of the ec2 instance to access nginx server.
5. Create sg.tf to create a security group which allows ports 22,80 and 443 incoming.
6. Create asymmetric key pair (locally) using ssh-keygen which will be used by Terraform to ssh into the instance.
7. Run terraform apply and Validate the changes
:::

##### Create a project folder and cd into it
````yaml=
mkdir provisioners-tf
cd provisioners-tf
````

##### providers.tf
````yaml=
## vi providers.tf

provider "aws" {
    access_key = "<Your_Access_Key>"
    secret_key = "<Your_Secret_Key>"
    token = "<Your_Security_Token>"
    region = "us-east-1"
}
````

##### create-ec2.tf
````yaml=
## vi create-ec2.tf

## Working with "remote-exec" and "file" provisioners

resource "aws_key_pair" "sk-key" {
    key_name = "sk-key"
    public_key = file("sk-key.pub")
}

resource "aws_instance" "mynginx" {
  ami           = "ami-02f3f602d23f1659d"
  instance_type = "t2.micro"
  vpc_security_group_ids = [aws_security_group.web-sg.id]
  key_name      = aws_key_pair.sk-key.key_name

  tags = {
    Name = "tf-nginx"
  }

  provisioner "file" {
      source      = "nginx.sh"
      destination = "/tmp/nginx.sh"
  }

  provisioner "remote-exec" {
    inline = [
      "chmod +x /tmp/nginx.sh",
      "sudo /tmp/nginx.sh",
    ]
  }

  connection {
    host        = self.public_ip
    type        = "ssh"
    user        = "ec2-user"
    private_key = file("sk-key")
  }
}
````
:mag: *Make sure to update the correct ***ami-id*** as per the AWS region and your account*

##### sg.tf
```hcl=
resource "aws_security_group" "web-sg" {
  name        = "web-sg-tf"
  description = "Allow HTTP, HTTPS and SSH traffic via Terraform"

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  ingress {
    from_port   = 3389
    to_port     = 3389
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}
```

##### nginx.sh
````yaml=
## vi nginx.sh

#!/bin/bash

# install nginx
sudo yum update
sudo yum install -y nginx

# make sure nginx is started
systemctl start nginx
````

##### outputs.tf
````yaml=
## vi outputs.tf

## Outputs to be displayed after "Terraform run"

output "public_ip" {
  value = aws_instance.mynginx.public_ip 
}

output "public_dns" {
  value = aws_instance.mynginx.public_dns
}
````

##### Create "remote-exec" keypair
````yaml=
root@terraform:~/provisioners-tf# ssh-keygen -t rsa -C a@b
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): sk-key
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in sk-key
Your public key has been saved in sk-key.pub
The key fingerprint is:
SHA256:2EXO2eDb8cWxpzZyCcCHrWW2xn3wS56GKx5xjlh5hxI a@b
The key's randomart image is:
+---[RSA 3072]----+
|         .+o   . |
|         =o=* ..o|
|          *E+o ++|
|       o ..o*+o=+|
|      . S .*o+@oo|
|          o B=.* |
|         . o .o  |
|           ...   |
|          ...    |
+----[SHA256]-----+
root@terraform:~/provisioners-tf# 
````

##### Final Directory / Module structure

Once all the steps are complete, your directory should look like the following:
````yaml=
root@terraform:~/provisioners-tf# tree
.
├── create-ec2.tf
├── nginx.sh
├── outputs.tf
├── provider.tf
├── sg.tf
├── sk-key
└── sk-key.pub

0 directories, 7 files
root@terraform:~/provisioners-tf# 
````
##### Run terraform apply and validate the changes
````yaml=!
Apply Terraform:
terraform apply -auto-approve

Validate:
Grab the Public IP (or Public DNS) of the instance from Terraform outputs and access it in a web browser such as chrome or firefox. You should be able to see the default nginx page.
````
:mag: If nginx is not accessible on the web browser, make sure you are accessing it on http (80) and not on https (443)


### References
:::info
- https://developer.hashicorp.com/terraform/language/meta-arguments/count
- [Variables in Terraform](https://developer.hashicorp.com/terraform/language/values/variables)
- https://developer.hashicorp.com/terraform/tutorials/configuration-language/dependencies
- https://developer.hashicorp.com/terraform/tutorials/certification-associate-tutorials-003
- https://catalog.us-east-1.prod.workshops.aws/workshops/afee4679-89af-408b-8108-44f5b1065cc7/en-US
- https://hashicorp-terraform.awsworkshop.io/
:::

