Skip to content

Instantly share code, notes, and snippets.

@lukemelia
Last active July 12, 2022 22:09
Show Gist options
  • Save lukemelia/bc1a0792af9653059321e8b66fd37ae7 to your computer and use it in GitHub Desktop.
Save lukemelia/bc1a0792af9653059321e8b66fd37ae7 to your computer and use it in GitHub Desktop.
WIP deploying waypoint server to EC2 with terraform
set -e
# add docker's own apt repository
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
# add hashicorp's apt repository
curl -fsSL https://apt.releases.hashicorp.com/gpg | apt-key add -
apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
# Install packages and unattended security upgrades
echo unattended-upgrades unattended-upgrades/enable_auto_updates boolean true | debconf-set-selections
DEBIAN_FRONTEND=noninteractive apt-get update
DEBIAN_FRONTEND=noninteractive apt-get install -y unattended-upgrades docker-ce unzip socat waypoint
# Take any security upgrades immediately
unattended-upgrade
# This needed to come after we installed docker-ce, which created the docker group
useradd --create-home --groups docker docker-control
# Docker remote access via SSH
cat >> /etc/ssh/sshd_config <<EOF
Match User docker-control
AllowTcpForwarding no
X11Forwarding no
PermitTunnel no
GatewayPorts no
AllowAgentForwarding no
ForceCommand socat STDIO UNIX-CONNECT:/var/run/docker.sock
EOF
service sshd reload
# install waypoint into docker
waypoint install --platform=docker -accept-tos
# Copy generated waypoint config tree to ubuntu user's home directory
mkdir -p /home/ubuntu/.config/waypoint
cp -R /.config/waypoint/context /home/ubuntu/.config/waypoint/context
rm /home/ubuntu/.config/waypoint/context/_default.hcl
sed -i -- 's/localhost/${waypoint_domain_name}/g' /home/ubuntu/.config/waypoint/context/*
ln -s /home/ubuntu/.config/waypoint/context/install-* /home/ubuntu/.config/waypoint/context/_default.hcl
chown ubuntu -R /home/ubuntu/.config
chgrp ubuntu -R /home/ubuntu/.config
variable "host_name" {
type = string
}
variable "domain" {
type = string
}
variable "subnet_id" {
type = string
}
variable "zone_id" {
type = string
}
variable "vpc_id" {
type = string
}
variable "subnet_ids" {
type = set(string)
}
locals {
waypoint_domain_name = "${var.host_name}.${var.domain}"
public_zone_name = "${var.domain}."
iam_name = "${var.host_name}-session-manager"
iam_path = "/service-role/"
}
data "aws_iam_policy" "default" {
arn = "arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM"
}
resource "aws_instance" "waypoint" {
ami = "ami-0ee02acd56a52998e" # ubuntu/images/hvm-ssd/ubuntu-xenial-16.04-amd64-server-*
lifecycle {
ignore_changes = [ ami ]
}
instance_type = "t2.small"
subnet_id = var.subnet_id
tags = {
Name = var.host_name
}
vpc_security_group_ids = [aws_security_group.waypoint.id]
associate_public_ip_address = true #TODO: false
iam_instance_profile = aws_iam_instance_profile.this.name
root_block_device {
volume_size = "64"
}
user_data = <<EOF
#!/bin/bash
${module.waypoint_keys.adder_script}
${templatefile("${path.module}/provision-waypoint.sh", { waypoint_domain_name: local.waypoint_domain_name})}
${module.docker_keys.adder_script}
EOF
}
resource "aws_route53_record" "waypoint" {
zone_id = var.zone_id
name = local.waypoint_domain_name
type = "A"
alias {
name = aws_lb.this.dns_name
zone_id = aws_lb.this.zone_id
evaluate_target_health = true
}
}
module "waypoint_keys" {
source = "../../../../modules/ssh_keys_from_s3"
user = "ubuntu"
home_dir = "/home/ubuntu"
key_set = "devs"
}
module "docker_keys" {
source = "../../../../modules/ssh_keys_from_s3"
user = "docker-control"
home_dir = "/home/docker-control"
key_set = "docker-control"
}
resource "aws_security_group" "waypoint" {
vpc_id = var.vpc_id
# gRPC API (Default 9701, TCP) - This is used for the gRPC API. This is consumed by the CLI,
# Entrypoint, and Runners. This port must be reachable by all deployments using the Entrypoint.
ingress {
from_port = 9701
to_port = 9701
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
# HTTP API (Default 9702, TCP) - This is used to serve the web UI and the web UI API client.
# If the web UI is not used, this port can be blocked or disabled.
ingress {
from_port = 9702
to_port = 9702
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
# SSH
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = -1
cidr_blocks = ["0.0.0.0/0"]
}
}
resource "aws_lb" "this" {
name = var.host_name
internal = false
load_balancer_type = "network"
subnets = var.subnet_ids
}
module "lb_cert" {
source = "../../../../modules/amazon_validated_cert"
zone_name = local.public_zone_name
cert_domain_name = local.waypoint_domain_name
}
resource "aws_lb_listener" "ui" {
load_balancer_arn = aws_lb.this.arn
port = "443"
protocol = "TLS"
ssl_policy = "ELBSecurityPolicy-2016-08"
certificate_arn = module.lb_cert.arn
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.ui.arn
}
}
resource "aws_lb_target_group" "ui" {
name = "${var.host_name}-ui"
vpc_id = var.vpc_id
protocol = "TLS"
port = 9702
}
resource "aws_lb_target_group_attachment" "ui" {
target_group_arn = aws_lb_target_group.ui.arn
target_id = aws_instance.waypoint.id
}
resource "aws_lb_listener" "grpc" {
load_balancer_arn = aws_lb.this.arn
port = "9701"
protocol = "TCP"
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.grpc.arn
}
}
resource "aws_lb_target_group" "grpc" {
name = "${var.host_name}-grpc"
vpc_id = var.vpc_id
protocol = "TCP"
port = 9701
}
resource "aws_lb_target_group_attachment" "grpc" {
target_group_arn = aws_lb_target_group.grpc.arn
target_id = aws_instance.waypoint.id
}
resource "aws_iam_instance_profile" "this" {
name = local.iam_name
role = aws_iam_role.this.name
path = local.iam_path
}
resource "aws_iam_role" "this" {
name = local.iam_name
assume_role_policy = data.aws_iam_policy_document.assume_role_policy.json
path = local.iam_path
tags = { "Name" = local.iam_name }
}
data "aws_iam_policy_document" "assume_role_policy" {
statement {
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["ec2.amazonaws.com"]
}
}
}
resource "aws_iam_policy" "this" {
name = local.iam_name
policy = data.aws_iam_policy.default.policy
path = local.iam_path
}
# https://www.terraform.io/docs/providers/aws/r/iam_role_policy_attachment.html
resource "aws_iam_role_policy_attachment" "this" {
role = aws_iam_role.this.name
policy_arn = aws_iam_policy.this.arn
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment