Skip to content

Instantly share code, notes, and snippets.

@fprimex
Created December 1, 2022 02:09
Show Gist options
  • Save fprimex/e7e8397b0a05b406a8dd0f4f47a5e193 to your computer and use it in GitHub Desktop.
Save fprimex/e7e8397b0a05b406a8dd0f4f47a5e193 to your computer and use it in GitHub Desktop.
Terraform configuration to create an instance that can be SSH'd into
# 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