Skip to content

Instantly share code, notes, and snippets.

@zimbatm
Created April 12, 2022 13:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zimbatm/56e7c6df6cc7902ebaed26989b1e5c69 to your computer and use it in GitHub Desktop.
Save zimbatm/56e7c6df6cc7902ebaed26989b1e5c69 to your computer and use it in GitHub Desktop.
# Fetch the latest NixOS AMI from 20.03
module "nixos_image" {
source = "git@github.com:tweag/terraform-nixos.git//aws_image_nixos?ref=43cbf822c07e705c66fb6d719ab58ed9cb05f87d"
release = "20.09"
}
data "external" "local_info" {
program = ["${path.module}/get_local_info.sh"]
}
# Generate a SSH key-pair
resource "tls_private_key" "machine" {
algorithm = "RSA"
}
# Updating key pairs is impossible if they have the same name, so we
# need to uniquify the name using the creation time.
resource "time_static" "keypair_update" {
triggers = {
# Save the time when the key pair changes
keypair = tls_private_key.machine.public_key_fingerprint_md5
}
}
# Record the SSH public key into AWS
resource "aws_key_pair" "machine" {
key_name = "${var.name}-machine-${time_static.keypair_update.unix}"
public_key = tls_private_key.machine.public_key_openssh
}
# This is the security group that will be attached to the instance
resource "aws_security_group" "machine" {
name = "${var.name}-machine"
description = "Machine SG"
tags = var.tags
vpc_id = var.vpc_id
}
# A bunch of rules for the group
resource "aws_security_group_rule" "machine_ingress_ssh" {
description = "Allow SSH from everywhere"
type = "ingress"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
security_group_id = aws_security_group.machine.id
}
# A bunch of rules for the group
resource "aws_security_group_rule" "machine_ingress_mosh" {
description = "Allow SSH from everywhere"
type = "ingress"
from_port = 60001
to_port = 60001
protocol = "udp"
cidr_blocks = ["0.0.0.0/0"]
security_group_id = aws_security_group.machine.id
}
resource "aws_security_group_rule" "machine_ingress_http" {
description = "Allow HTTP from the Load-Balancer only"
type = "ingress"
from_port = 0
to_port = 0
protocol = "-1"
source_security_group_id = aws_security_group.lb.id
security_group_id = aws_security_group.machine.id
}
resource "aws_security_group_rule" "machine_egress_all" {
description = "Allow to connect to the whole Internet"
type = "egress"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
security_group_id = aws_security_group.machine.id
}
# Permissions for the AWS instance
data "aws_iam_policy_document" "machine" {
statement {
sid = "SecretsAccess"
actions = [
"ssm:GetParameterHistory",
"ssm:ListTagsForResource",
"ssm:GetParametersByPath",
"ssm:GetParameters",
"ssm:GetParameter",
]
resources = [
aws_ssm_parameter.brossa_config.arn
]
}
statement {
sid = "CognitoIdpPermissions"
actions = [
"cognito-idp:*",
]
resources = [
"arn:aws:cognito-idp:*"
]
}
statement {
sid = "SESEmailPermissions"
actions = [
"ses:*",
]
resources = [
"arn:aws:ses:*"
]
}
}
# A bunch of IAM resources needed to give permissions to the instance
resource "aws_iam_role" "machine" {
name = "${var.name}-machine"
tags = var.tags
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
resource "aws_iam_role_policy" "machine" {
name = "${var.name}-machine"
role = aws_iam_role.machine.name
policy = data.aws_iam_policy_document.machine.json
}
resource "aws_iam_instance_profile" "machine" {
name = "${var.name}-machine"
role = aws_iam_role.machine.name
depends_on = [aws_iam_role_policy.machine]
}
# The actual AWS instance
resource "aws_instance" "machine" {
# Base image to start the instance with
ami = module.nixos_image.ami
iam_instance_profile = aws_iam_instance_profile.machine.name
instance_type = var.ec2_instance_type
key_name = aws_key_pair.machine.key_name
vpc_security_group_ids = [aws_security_group.machine.id]
# always deploy in the first subnet
subnet_id = var.vpc_subnets[1]
tags = merge(var.tags, { "Name" = "${var.name}-machine" })
root_block_device {
volume_type = "gp2"
volume_size = "50" # GiB
}
lifecycle {
create_before_destroy = true
}
}
# This deploys the NixOS configuration onto the VM
module "machine_deploy" {
source = "git@github.com:tweag/terraform-nixos.git//deploy_nixos?ref=43cbf822c07e705c66fb6d719ab58ed9cb05f87d"
NIX_PATH = data.external.local_info.result.nix_path
nixos_config = "${path.module}/configuration.nix"
ssh_agent = false
ssh_private_key = tls_private_key.machine.private_key_pem
target_host = aws_instance.machine.public_ip
target_user = "root"
keys = {
"grafana-agent-loki-url" = var.loki_url
"grafana-agent-loki-username" = var.loki_username
"grafana-agent-loki-password" = var.loki_password
"grafana-agent-prometheus-remote-write-url" = var.prometheus_remote_write_url
"grafana-agent-prometheus-remote-write-username" = var.prometheus_remote_write_username
"grafana-agent-prometheus-remote-write-password" = var.prometheus_remote_write_password
}
triggers = {
# Force a new deployment if the instance ID has changed. The ID changes if
# the instance is re-created for example.
machine_id = aws_instance.machine.id
}
}
# Attach a DNS name for accessing the machine directly. Not strictly
# necessary.
resource "aws_route53_record" "machine" {
zone_id = var.zone_id
name = "machine.${var.domain}"
type = "A"
ttl = "300"
records = [aws_instance.machine.public_ip]
}
# LB Target group that holds the machine
resource "aws_lb_target_group" "machine" {
name = "${var.name}-machine"
port = 8000
protocol = "HTTP"
vpc_id = var.vpc_id
tags = var.tags
health_check {
enabled = true
interval = 5
path = "/health"
port = 8000
protocol = "HTTP"
timeout = 2
healthy_threshold = 2
unhealthy_threshold = 3
}
}
resource "aws_lb_target_group_attachment" "machine" {
target_group_arn = aws_lb_target_group.machine.arn
target_id = aws_instance.machine.id
port = 8000
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment