Terraform how to do SSH in AWS EC2 instance?


This blog post will help you to understand how to do SSH into AWS EC2 instance using Terraform. It is quite often that you create your terraform script for setting up your EC2 instance but after starting your EC2 can not SSH into EC2 instance created with Terraform.

When you are working on the cloud (AWS, Google Cloud) you are not provided with a password for the root user. You have to use SSH key-pair(public key, private key) for authentication and after successful authentication, you can SSH into your EC2 machine using the private key.

In this blog post, we will go through the following steps -

  1. Generate key-pair(public key, private key) using ssh keygen
  2. Use public key to start EC2 instance
  3. Use the private key to SSH into EC2 instance
  4. Generate pem file from AWS console and use the file to SSH into EC2


(*Note - The first 3 steps in which we are going to generate the ssh key-pair manually and in the 4th step we will generate the key pair from AWS console.If you do not want to generate the SSH keys manually then you can refer to this blog post where I described on how to use terraform's tls_private_key module to generate and upload private, public key for AWS)


1. Generate key-pair(public key, private key) using ssh keygen

1.1 Generate the public key and private key

Before you start playing with AWS console and terraform script we need to first generate the key-pair(public key, private key) using ssh-keygen.

Later we are going to associate both public and private keys with AWS EC2 instances.

Let us generate the key pair using the following command

1ssh-keygen -t rsa -b 2048 

By default, the above command will generate the public as well as private key at location '/home//.ssh'

But we can override the end destination with a custom path. (I have assigned my custom path /home/rahul/Jhooq/keys/aws followed my key name .i.e. aws_key )

Here is the output along with a screenshot my terminal-

 1Generating public/private RSA key pair.
 2Enter file in which to save the key (/home/rahul/.ssh/id_rsa): /home/rahul/Jhooq/keys/aws/aws_key 
 3Enter passphrase (empty for no passphrase): 
 4Enter the same passphrase again: 
 5Your identification has been saved in /home/rahul/Jhooq/keys/aws/aws_key
 6Your public key has been saved in /home/rahul/Jhooq/keys/aws/aws_key.pub
 7The key fingerprint is:
 8SHA256:sAOjXyvJc2gnMrvxXA+qiaU9pUEvwl5ZG9Y2kZqRf5M rahul@rahul-HP-ZBook-15-G2
 9The key's randomart image is:
10+---[RSA 2048]----+
11|      . .        |
12|     o o         |
13|    o B . .      |
14|  .. O B E       |
15|....+ B S .      |
16|..o=o= o         |
17|..*=X *          |
18| *oX O o         |
19|o *++   .        |
20+----[SHA256]-----+ 

Terrafrom ssh into ec2 instance generate keys using ssh-keygen



1.2 Verify the generated public key and private key

In the previous step, we have generated the key-pair which we are going to use for provisioning the EC2 instance. But let us take a look at the keys and how it looks.

If you remember in the previous step we have generated the keys at path /home/rahul/Jhooq/keys/aws we should see two key files over there -

  1. aws_key (private key)
  2. aws_key.pub (public key)

Terrafrom ssh into ec2 instance generate keys using ssh-keygen

We are going to use public key aws_key.pub inside the terraform file to provision/start the ec2 instance.

1.2.1 public key aws_key.pub

Here is the content of the public key aws_key.pub(you can open the file in any editor of your choice) -

1ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDbvRN/gvQBhFe+dE8p3Q865T/xTKgjqTjj56p1IIKbq8SDyOybE8ia0rMPcBLAKds+wjePIYpTtRxT9UsUbZJTgF+SGSG2dC6+ohCQpi6F3xM7ryL9fy3BNCT5aPrwbR862jcOIfv7R1xVfH8OS0WZa8DpVy5kTeutsuH5FMAmEgba4KhYLTzIdhM7UKJvNoUMRBaxAqIAThqH9Vt/iR1WpXgazoPw6dyPssa7ye6tUPRipmPTZukfpxcPlsqytXWlXm7R89xAY9OXkdPPVsrQA0XFQnY8aFb9XaZP8cm7EOVRdxMsA1DyWMVZOTjhBwCHfEIGoePAS3jFMqQjGWQd rahul@rahul-HP-ZBook-15-G2
1.2.2 private key aws_key

Here is the content of the private key aws_key(you can open the file in any editor of your choice) -

 1-----BEGIN OPENSSH PRIVATE KEY-----
 2b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn
 3NhAAAAAwEAAQAAAQEA270Tf4L0AYRXvnRPKd0POuU/8UyoI6k44+eqdSCCm6vEg8jsmxPI
 4mtKzD3ASwCnbPsI3jyGKU7UcU/VLFG2SU4BfkhkhtnQuvqIQkKYuhd8TO68i/X8twTQk+W
 5j68G0fOto3DiH7+0dcVXx/DktFmWvA6VcuZE3rrbLh+RTAJhIG2uCoWC08yHYTO1CibzaF
 6DEQWsQKiAE4ah/Vbf4kdVqV4Gs6D8Oncj7LGu8nurVD0YqZj02bpH6cXD5bKsrV1pV5u0f
 7PcQGPTl5HTz1bK0ANFxUJ2PGhW/V2mT/HJuxDlUXcTLANQ8ljFWTk44QcAh3xCBqHjwEt4
 8xTKkIxlkHQAAA9CsiPUKrIj1CgAAAAdzc2gtcnNhAAABAQDbvRN/gvQBhFe+dE8p3Q865T
 9/xTKgjqTjj56p1IIKbq8SDyOybE8ia0rMPcBLAKds+wjePIYpTtRxT9UsUbZJTgF+SGSG2
10dC6+ohCQpi6F3xM7ryL9fy3BNCT5aPrwbR862jcOIfv7R1xVfH8OS0WZa8DpVy5kTeutsu
11H5FMAmEgba4KhYLTzIdhM7UKJvNoUMRBaxAqIAThqH9Vt/iR1WpXgazoPw6dyPssa7ye6t
12UPRipmPTZukfpxcPlsqytXWlXm7R89xAY9OXkdPPVsrQA0XFQnY8aFb9XaZP8cm7EOVRdx
13MsA1DyWMVZOTjhBwCHfEIGoePAS3jFMqQjGWQdAAAAAwEAAQAAAQB83JvPwSHWGtWhK4Yw
14S6Tz2oDTJLQGT4o8Ns/tbmPJAXnRSMLp+/vpvgBxrUV6XE5xAvt/IZfwqOFH9AKNwRV8zV
152BLzaw7qQBPyYai9Ozzmana4V+dl4RgwffkX/GTruIPac7KKR+zLXy/aNVBACwhUJBVYDP
16Dlf1g8hUOS5WcqpRpdzf3PWjAosC2sZUNtoU9wmMTOQMb96haWgdqQrdulzhBxMb7/hJQ5
17q11gGdTboFM2l8yKMbRsba1OG/0JR2cmSNoK2PDL8GxskolwveGjvzsYPUS0iQsvjqAWQX
18F3cW7lBq0eL23qkLFxAJxFQU4mB9yH5KCunU0K9am18hAAAAgAxkrreETLmI0snIX3uX+T
19ySTNTb0G9kya0G3TGpkjvZT8Ump/L8ysleidqK2VYVEPre6vfTECqzWhBL1BVT/howuacG
205LeEkgS/F8oQJ19iEKT4LXxTumlFJqIj7+9jjnD5Z+gxi/ttJVTWvN/L4Ho9ZbZ6SoUBIB
21hnb+tDP0+mAAAAgQDwFBx6E7dARqwOeN8byrmzsYmnr9a2jx4eXR1iDX7ZzPLjYoOCFiJP
223ahHhXSzPx5pJK4k8MRYUFNTjtl2K+cKgCZC75Dj5mfI/8l0pvmUrZ2e2GN1+ATUcQO7Dy
230j8124Bke0OkItBTfwQrsIOSyYzySOll88odoISNB2BdZsewAAAIEA6k+ljxLX1sfn8wOg
24l9zgXqoT64tiQIJ720WSHuc5xoslgHVdjeunVy1eAaZMDURn8sbedlGLaebaGdVZwidR04
25gpodkAZdkBm+tju2NRIxIhuDU02ddJFEGy/8lp+XqEm+YfbUpHrCSNOjYBDkdAp6umQFVq
26jQi2RBtpIsNFikcAAAAacmFodWxAcmFodWwtSFAtWkJvb2stMTUtRzIB
27-----END OPENSSH PRIVATE KEY-----


2. Use public key to start EC2 instance

Alright now we have the public key and the private key with us, let us create our terraform configuration file using the public key .i.e. aws_key.pub

(*Note - If this is your first time with terraform and you have not worked before then I would recommend you to go through an article on How to install terraform and How to create EC2 instance on AWS)

Here is the main.tf -

 1provider "aws" {
 2   region     = "eu-central-1"
 3   access_key = ""
 4   secret_key = ""
 5   
 6}
 7
 8resource "aws_instance" "ec2_example" {
 9
10    ami = "ami-0767046d1677be5a0"  
11    instance_type = "t2.micro" 
12    key_name= "aws_key"
13    vpc_security_group_ids = [aws_security_group.main.id]
14
15  provisioner "remote-exec" {
16    inline = [
17      "touch hello.txt",
18      "echo helloworld remote provisioner >> hello.txt",
19    ]
20  }
21  connection {
22      type        = "ssh"
23      host        = self.public_ip
24      user        = "ubuntu"
25      private_key = file("/home/rahul/Jhooq/keys/aws/aws_key")
26      timeout     = "4m"
27   }
28}
29
30resource "aws_security_group" "main" {
31  egress = [
32    {
33      cidr_blocks      = [ "0.0.0.0/0", ]
34      description      = ""
35      from_port        = 0
36      ipv6_cidr_blocks = []
37      prefix_list_ids  = []
38      protocol         = "-1"
39      security_groups  = []
40      self             = false
41      to_port          = 0
42    }
43  ]
44 ingress                = [
45   {
46     cidr_blocks      = [ "0.0.0.0/0", ]
47     description      = ""
48     from_port        = 22
49     ipv6_cidr_blocks = []
50     prefix_list_ids  = []
51     protocol         = "tcp"
52     security_groups  = []
53     self             = false
54     to_port          = 22
55  }
56  ]
57}
58
59
60resource "aws_key_pair" "deployer" {
61  key_name   = "aws_key"
62  public_key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDbvRN/gvQBhFe+dE8p3Q865T/xTKgjqTjj56p1IIKbq8SDyOybE8ia0rMPcBLAKds+wjePIYpTtRxT9UsUbZJTgF+SGSG2dC6+ohCQpi6F3xM7ryL9fy3BNCT5aPrwbR862jcOIfv7R1xVfH8OS0WZa8DpVy5kTeutsuH5suehdngba4KhYLTzIdhM7UKJvNoUMRBaxAqIAThqH9Vt/iR1WpXgazoPw6dyPssa7ye6tUPRipmPTZukfpxcPlsqytXWlXm7R89xAY9OXkdPPVsrQdkdfhnY8aFb9XaZP8cm7EOVRdxMsA1DyWMVZOTjhBwCHfEIGoePAS3jFMqQjGWQd rahul@rahul-HP-ZBook-15-G2"
63}

You can first verify the terraform configuration using the terraform plan and then finally you can apply it using terraform apply.

After applying the configuration you can verify the instance by going into the AWS console -

AWS terraform instance running after adding the public and private key



3. Use private key 'aws_key' to SSH into EC2 instance

In the previous step, we have started the EC2 instance, now we need to connect to EC2 instance using the private key.

You can find the connect command from the aws console -

ssh commend to connect with ec2 machine using private key

Here is the SSH connect command for your reference-

(By default in the command you will see .pem extension in the private key file name but since we have created private with the name aws_key so we need to remove .pem extension from the file)

1ssh -i "aws_key" ubuntu@ec2-18-185-22-181.eu-central-1.compute.amazonaws.com

after connecting to ec2 instance using the private key



4. Generate pem file from AWS console and use the file to SSH into EC2

In this step, we are going to AWS's key pair utility to generate the keys for us.

Login to your AWS console and in the search bar type is key pair

AWS key pair

Click on the Create Key pair

AWS create key pair

Now you need to supply the key name. You can choose the private key format .pem

Enter the key pair name for creating the aws key

As you will click on Create key pair you will be able to download the key and save it somewhere onto your disk.

Now you can simply use the key aws_key.pem by specifying the key name inside your terraform file.

Here is an example of terraform script -

 1provider "aws" {
 2   region     = "eu-central-1"
 3   access_key = "AKIATQ37NXB2BYDxxxxx"
 4   secret_key = "JzZKiCia2vjbq4zGGGewdbOhnacm2QIMgcBxxxxx"
 5   
 6}
 7
 8resource "aws_instance" "ec2_example" {
 9
10    ami = "ami-0767046d1677be5a0"  
11    instance_type = "t2.micro" 
12    key_name= "aws_key"
13    vpc_security_group_ids = [aws_security_group.main.id]
14
15}
16
17resource "aws_security_group" "main" {
18  egress = [
19    {
20      cidr_blocks      = [ "0.0.0.0/0", ]
21      description      = ""
22      from_port        = 0
23      ipv6_cidr_blocks = []
24      prefix_list_ids  = []
25      protocol         = "-1"
26      security_groups  = []
27      self             = false
28      to_port          = 0
29    }
30  ]
31 ingress                = [
32   {
33     cidr_blocks      = [ "0.0.0.0/0", ]
34     description      = ""
35     from_port        = 22
36     ipv6_cidr_blocks = []
37     prefix_list_ids  = []
38     protocol         = "tcp"
39     security_groups  = []
40     self             = false
41     to_port          = 22
42  }
43  ]
44}

Few points to pay attention for -

  1. You need to open port 22 for SSH
  2. For opening port 22 you need to create a security group and attach the security group to aws instance

Apply the Terraform configuration You can simply run the following commands in the same sequence one after another -

  1. terraform init
  2. terraform plan
  3. terraform apply
4.1 Verify the EC2 instance

After provisioning/starting the EC2 instance, we need to verify two things -

  1. EC2 instance running state
  2. SSH into EC2 instance using the aws_key.pem key

1. Verify EC2 instance running state

Go to your AWS console and look for the number of EC2 instances running. If you successfully started your EC2 instance then you will following under the EC2 dashboard of AWS -

Successfully running EC2 instance


2. SSH into EC2 instance using the aws_key.pem key

So till now we have created the key as well started the AWS ec2 instance which is also up and running.

Now we need to ssh into the ec2 instance so that we can verify that the keys which we have generated are working fine.

Let's first goto the AWS console and select the EC2 instance which we have created. Then click on connect.

Connect the Ec2 instance

After you click on the connection you will be prompted with different options to connect -

  1. EC2 Instance connect
  2. Session Manager
  3. SSH Client
  4. EC2 Serial Console

We are going to choose the option SSH Client

SSH Client connect option with EC2

Open your terminal and go to the location where you have saved aws_key.pem key file. Because we need that private key file to connect with the EC2 instance.

Run the following command to change the permission of the file -

1chmod 400 aws_key.pem

Now use the following command to connect with the EC2 instance -

1ssh -i "aws_key.pem" ubuntu@ec2-52-58-111-83.eu-central-1.compute.amazonaws.com

After making the successful SSH connection you should see the following on you terminal -

Connect with EC2 instance using aws_key

Hope this blog post helps you to solve the issue Can't SSH into EC2 instance created with Terraform.


Read More - Terragrunt -

  1. How to use Terragrunt?

Posts in this Series