Creating an EC2 Instance
Make an instance in a public subnet
Open your shell again and get a new scaffold:
scaffold aws_instance
add aws_instance.web.tf to the new scaffold.
resource "aws_instance" "web" {
ami = "ami-12345678"
instance_type = "t2.micro"
tags = var.common_tags
}
Rather than hard-coding the AMI like above, a better and more maintainable way it to get the latest AMI made of that type: Adding an ami data source is a better way, like this one for ubuntu xenial data.aws_ami.xenial.tf:
data "aws_ami" "xenial" {
most_recent = true
owners = ["099720109477"]
filter {
name = "name"
values = ["ubuntu/images/*ubuntu-xenial-16.04-amd64-server-*"]
}
filter {
name = "root-device-type"
values = ["ebs"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
}
Then update the AMI reference in aws_instance to:
ami = data.aws_ami.xenial.id
If you apply now the latest xenial AMI will start, and as just about every other property isn't specified it will use the defaults for VPC, Subnet and Security Group.
+ aws_instance.web
id: <computed>
ami: "ami-01bc69b830b49f729"
arn: <computed>
associate_public_ip_address: <computed>
availability_zone: <computed>
cpu_core_count: <computed>
cpu_threads_per_core: <computed>
ebs_block_device.#: <computed>
ephemeral_block_device.#: <computed>
get_password_data: "false"
host_id: <computed>
instance_state: <computed>
instance_type: "t2.micro"
ipv6_address_count: <computed>
ipv6_addresses.#: <computed>
key_name: <computed>
network_interface.#: <computed>
network_interface_id: <computed>
password_data: <computed>
placement_group: <computed>
primary_network_interface_id: <computed>
private_dns: <computed>
private_ip: <computed>
public_dns: <computed>
public_ip: <computed>
root_block_device.#: <computed>
security_groups.#: <computed>
source_dest_check: "true"
subnet_id: <computed>
tags.%: "1"
tags.createdby: "Terraform"
tenancy: <computed>
volume_tags.%: <computed>
vpc_security_group_ids.#: <computed>
Specify an SSH key
The currently provisioned instance has no access as no SSH key was specified, you can manually upload your ssh key to AWS or automatically provision one.
Create an SSH key by adding tls_private_key.ssh.tf
resource "tls_private_key" "ssh" {
algorithm = "RSA"
rsa_bits = "2048"
}
and add a new provider for tls provider.tls.tf:
provider tls {
version="2.1.1"
}
Add the generated key to AWS with aws_key_pair.ssh.tf
resource "aws_key_pair" "ssh" {
key_name = "id_rsa"
public_key = tls_private_key.ssh.public_key_openssh
}
To SSH in you'll need the private key, get the key pair with local_file.ssh-key.tf:
resource "local_file" "pem-private" {
content = tls_private_key.ssh.private_key_pem
filename = "${path.cwd}/id_rsa"
}
resource "local_file" "ssh-public" {
content = tls_private_key.ssh.public_key_openssh
filename = "${path.cwd}/id_rsa.pub"
}
This needs a provider for file provider.local.tf:
provider local {
version="1.4"
}
Update the aws_instance resource to link to the new key:
resource aws_instance web {
ami = data.aws_ami.xenial.id
instance_type = "t2.micro"
tags = var.common_tags
key_name = aws_key_pair.ssh.key_name
}
And a Secruity group that allows access:
resource aws_security_group ssh {
name = "allow-ssh"
ingress {
cidr_blocks = [
"0.0.0.0/0"
]
from_port = 22
to_port = 22
protocol = "tcp"
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
Warning
In the ingress I use a CIDR of "0.0.0.0/0", which is wide open to the world. Id normally restrict this my own IP. You could also make the Ingress group optional and deprovision it all together at a later date.
and finally add update outputs.tf to get the public to get the Public ip to SSH into.
output public_ip {
value=aws_instance.web.public_ip
}
Apply the above changes:
See the created key files id_rsa and id_rsa.pub and test by SSHing into new instance.
$ ls -l
total 32
-rwxrwxrwx 1 jim jim 406 Oct 22 10:13 Makefile
-rwxrwxrwx 1 jim jim 2701 Oct 22 10:13 README.md
-rwxrwxrwx 1 jim jim 46 Oct 22 10:13 aws_instance.auto.tfvars
-rwxrwxrwx 1 jim jim 189 Nov 5 14:15 aws_instance.web.tf
-rwxrwxrwx 1 jim jim 114 Nov 5 14:01 aws_key_pair.ssh.tf
-rwxrwxrwx 1 jim jim 289 Nov 5 14:14 aws_security.ssh.tf
-rwxrwxrwx 1 jim jim 345 Oct 22 10:13 data.aws_ami.xenial.tf
-rwxrwxrwx 1 jim jim 1675 Nov 5 14:23 id_rsa
-rwxrwxrwx 1 jim jim 381 Nov 5 14:23 id_rsa.pub
-rwxrwxrwx 1 jim jim 260 Nov 5 14:01 local_file.ssh-key.tf
-rwxrwxrwx 1 jim jim 35 Oct 22 10:13 main.tf
-rwxrwxrwx 1 jim jim 59 Nov 5 14:21 outputs.tf
-rwxrwxrwx 1 jim jim 68 Nov 5 10:17 provider.aws.tf
-rwxrwxrwx 1 jim jim 38 Nov 5 14:13 provider.local.tf
-rwxrwxrwx 1 jim jim 38 Nov 5 13:57 provider.tls.tf
-rwxrwxrwx 1 jim jim 15355 Nov 5 14:24 terraform.tfstate
-rwxrwxrwx 1 jim jim 5920 Nov 5 14:23 terraform.tfstate.backup
-rwxrwxrwx 1 jim jim 80 Nov 5 13:44 tls_private_key.ssh.tf
-rwxrwxrwx 1 jim jim 120 Oct 22 10:13 variables.tf
Warning
Do not add keys to Git
Info
Run "Terraform destroy" to cleanup.