Created
December 1, 2022 02:09
-
-
Save fprimex/e7e8397b0a05b406a8dd0f4f47a5e193 to your computer and use it in GitHub Desktop.
Terraform configuration to create an instance that can be SSH'd into
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# You'll need to set AWS environment variables or use a credentials file | |
# or take the usual command line approach to authenticate to AWS. If the | |
# aws-cli is working for you, then Terraform probably will too. | |
# Specify which provider plugins to get from the registry. | |
terraform { | |
required_providers { | |
aws = { | |
source = "hashicorp/aws" | |
} | |
random = { | |
source = "hashicorp/random" | |
} | |
tls = { | |
source = "hashicorp/tls" | |
} | |
} | |
} | |
# Set the region. This value can be overridden at the command line | |
# with -var region=..., or in a tfvars file, usually an automatic vars file | |
# named, e.g., whatever.auto.tfvars containing region = "..." | |
variable "region" { | |
default = "us-west-2" | |
} | |
# Declare and configure the provider. The region comes from the Terraform | |
# variable 'region', and the rest comes from the environment, via environment | |
# variables or an AWS credentials file, etc. | |
provider "aws" { | |
region = var.region | |
} | |
# Locals are expression labels. For us-west-2, this makes local.az = us-west-2a | |
locals { | |
az = "${var.region}a" | |
} | |
# Query AWS for the Ubuntu 20.04 AMI in this region | |
data "aws_ami" "ubuntu" { | |
most_recent = true | |
filter { | |
name = "name" | |
values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"] | |
} | |
filter { | |
name = "virtualization-type" | |
values = ["hvm"] | |
} | |
owners = ["099720109477"] | |
} | |
# Create a random name to give to everything | |
resource "random_pet" "p" {} | |
# Generate a key we can use for SSH | |
resource "tls_private_key" "k" { | |
algorithm = "ED25519" | |
} | |
# Start making infrastructure. All of the networking required to get | |
# from wherever you are out on the Internet to the new instance. | |
resource "aws_vpc" "v" { | |
cidr_block = "10.0.0.0/16" | |
enable_dns_hostnames = true | |
} | |
resource "aws_subnet" "s" { | |
vpc_id = aws_vpc.v.id | |
cidr_block = "10.0.0.0/24" | |
map_public_ip_on_launch = true | |
availability_zone = local.az | |
} | |
resource "aws_internet_gateway" "gw" { | |
vpc_id = aws_vpc.v.id | |
} | |
resource "aws_route_table" "r" { | |
vpc_id = aws_vpc.v.id | |
route { | |
cidr_block = "0.0.0.0/0" | |
gateway_id = aws_internet_gateway.gw.id | |
} | |
} | |
resource "aws_route_table_association" "a" { | |
subnet_id = aws_subnet.s.id | |
route_table_id = aws_route_table.r.id | |
} | |
resource "aws_security_group" "sg" { | |
name = random_pet.p.id | |
vpc_id = aws_vpc.v.id | |
ingress { | |
from_port = 0 | |
to_port = 22 | |
protocol = "tcp" | |
cidr_blocks = ["0.0.0.0/0"] | |
self = true | |
} | |
} | |
# Make an AWS key pair object containing the key created earlier | |
# so that the instance can be assigned this key from within AWS. | |
resource "aws_key_pair" "p" { | |
key_name = random_pet.p.id | |
public_key = tls_private_key.k.public_key_openssh | |
} | |
# Create the instance, using the AMI found and placing it inside | |
# the network that was made for it. Tell it to ask for a public | |
# IP address association so that it can be reached from outside | |
# of AWS. | |
resource "aws_instance" "i" { | |
ami = data.aws_ami.ubuntu.id | |
instance_type = "t2.micro" | |
availability_zone = local.az | |
subnet_id = aws_subnet.s.id | |
vpc_security_group_ids = [aws_security_group.sg.id] | |
key_name = aws_key_pair.p.key_name | |
associate_public_ip_address = true | |
# The instance doesn't have an implicit dependency on the gateway, | |
# but the gateway does have to be created first, so this creates | |
# an explicit dependency. | |
depends_on = [aws_internet_gateway.gw] | |
# The resource config is finished. The connection and provisioner | |
# blocks demonstrate how to run something on the instance once | |
# its up directly from TF. | |
# This tells Terraform how to connect to the instance. | |
connection { | |
type = "ssh" | |
user = "ubuntu" | |
host = aws_instance.i.public_ip | |
private_key = tls_private_key.k.private_key_openssh | |
} | |
# And lastly the remote-exec provisioner runs once the instance | |
# is created. Any command can be passed here. | |
provisioner "remote-exec" { | |
inline = [ | |
"uname -a", | |
] | |
} | |
} | |
# These outputs will show up once the apply is complete, and they can | |
# be retrieved with the terraform output command. The SSH private | |
# key is marked sensitive so that it doesn't get printed in plain text | |
# after the apply, but it is still available with terraform output key | |
output "key" { | |
sensitive = true | |
value = sensitive(tls_private_key.k.private_key_openssh) | |
} | |
# This output shows the commands needed to connect to the instance. First | |
# use terraform output to dump the private key to a file, then use that | |
# private key to ssh into the instance. | |
output "ssh_to_ec2_cmd" { | |
value = "terraform output -raw key > key; chmod 600 key; ssh -i ./key ubuntu@${aws_instance.i.public_ip}" | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment