Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.DS_Store
*.tfvars
*.tfstate*
*.ovpn
1 change: 1 addition & 0 deletions VERSION
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1.0.0
769 changes: 769 additions & 0 deletions post.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions terraform/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This repo contains [Terraform](https://terraform.io) configuration files and related source code used in [Guide to automating a multi-tiered application securely on AWS with Docker and Terraform](https://www.airpair.com/aws/posts/ntiered-aws-docker-terraform-guide) examples.
28 changes: 28 additions & 0 deletions terraform/app-servers.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/* App servers */
resource "aws_instance" "app" {
count = 2
ami = "${lookup(var.amis, var.region)}"
instance_type = "t2.micro"
subnet_id = "${aws_subnet.private.id}"
security_groups = ["${aws_security_group.default.id}"]
key_name = "${aws_key_pair.deployer.key_name}"
source_dest_check = false
user_data = "${file(\"cloud-config/app.yml\")}"
tags = {
Name = "airpair-example-app-${count.index}"
}
}

/* Load balancer */
resource "aws_elb" "app" {
name = "airpair-example-elb"
subnets = ["${aws_subnet.public.id}"]
security_groups = ["${aws_security_group.default.id}", "${aws_security_group.web.id}"]
listener {
instance_port = 80
instance_protocol = "http"
lb_port = 80
lb_protocol = "http"
}
instances = ["${aws_instance.app.*.id}"]
}
Binary file added terraform/assets/header.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions terraform/aws-vpc.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/* Setup our aws provider */
provider "aws" {
access_key = "${var.access_key}"
secret_key = "${var.secret_key}"
region = "${var.region}"
}

/* Define our vpc */
resource "aws_vpc" "default" {
cidr_block = "${var.vpc_cidr}"
enable_dns_hostnames = true
tags {
Name = "airpair-example"
}
}
1 change: 1 addition & 0 deletions terraform/bin/ovpn-client-config
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ssh -t -i ssh/insecure-deployer "ubuntu@$(terraform output nat.ip)" sudo docker run --volumes-from ovpn-data --rm gosuri/openvpn ovpn_getclient "${1}" > "${1}-airpair-example.ovpn"
1 change: 1 addition & 0 deletions terraform/bin/ovpn-init
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ssh -t -i ssh/insecure-deployer [email protected] sudo docker run --volumes-from ovpn-data --rm -it gosuri/openvpn ovpn_initpki
1 change: 1 addition & 0 deletions terraform/bin/ovpn-new-client
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ssh -t -i ssh/insecure-deployer "ubuntu@$(terraform output nat.ip)" sudo docker run --volumes-from ovpn-data --rm -it gosuri/openvpn easyrsa build-client-full "${1}" nopass
1 change: 1 addition & 0 deletions terraform/bin/ovpn-start
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ssh -t -i ssh/insecure-deployer "ubuntu@$(terraform output nat.ip)" sudo docker run --volumes-from ovpn-data -d -p 1194:1194/udp --cap-add=NET_ADMIN gosuri/openvpn
8 changes: 8 additions & 0 deletions terraform/cloud-config/app.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#cloud-config
# Cloud config for application servers

runcmd:
# Install docker
- curl -sSL https://get.docker.com/ubuntu/ | sudo sh
# Run nginx
- docker run -d -p 80:80 dockerfile/nginx
5 changes: 5 additions & 0 deletions terraform/key-pairs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
resource "aws_key_pair" "deployer" {
key_name = "deployer-airpair-example"
public_key = "${file(\"ssh/insecure-deployer.pub\")}"
}

29 changes: 29 additions & 0 deletions terraform/nat-server.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/* NAT/VPN server */
resource "aws_instance" "nat" {
ami = "${lookup(var.amis, var.region)}"
instance_type = "t2.micro"
subnet_id = "${aws_subnet.public.id}"
security_groups = ["${aws_security_group.default.id}", "${aws_security_group.nat.id}"]
key_name = "${aws_key_pair.deployer.key_name}"
source_dest_check = false
tags = {
Name = "nat"
}
connection {
user = "ubuntu"
key_file = "ssh/insecure-deployer"
}
provisioner "remote-exec" {
inline = [
"sudo iptables -t nat -A POSTROUTING -j MASQUERADE",
"echo 1 > /proc/sys/net/ipv4/conf/all/forwarding",
/* Install docker */
"curl -sSL https://get.docker.com | sudo sh",
/* Initialize open vpn data container */
"sudo mkdir -p /etc/openvpn",
"sudo docker run --name ovpn-data -v /etc/openvpn busybox",
/* Generate OpenVPN server config */
"sudo docker run --volumes-from ovpn-data --rm gosuri/openvpn ovpn_genconfig -p ${var.vpc_cidr} -u udp://${aws_instance.nat.public_ip}"
]
}
}
15 changes: 15 additions & 0 deletions terraform/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
output "app.0.ip" {
value = "${aws_instance.app.0.private_ip}"
}

output "app.1.ip" {
value = "${aws_instance.app.1.private_ip}"
}

output "nat.ip" {
value = "${aws_instance.nat.public_ip}"
}

output "elb.hostname" {
value = "${aws_elb.app.dns_name}"
}
26 changes: 26 additions & 0 deletions terraform/private-subnet.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/* Private subnet */
resource "aws_subnet" "private" {
vpc_id = "${aws_vpc.default.id}"
cidr_block = "${var.private_subnet_cidr}"
availability_zone = "us-west-1a"
map_public_ip_on_launch = false
depends_on = ["aws_instance.nat"]
tags {
Name = "private"
}
}

/* Routing table for private subnet */
resource "aws_route_table" "private" {
vpc_id = "${aws_vpc.default.id}"
route {
cidr_block = "0.0.0.0/0"
instance_id = "${aws_instance.nat.id}"
}
}

/* Associate the routing table to public subnet */
resource "aws_route_table_association" "private" {
subnet_id = "${aws_subnet.private.id}"
route_table_id = "${aws_route_table.private.id}"
}
31 changes: 31 additions & 0 deletions terraform/public-subnet.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/* Internet gateway for the public subnet */
resource "aws_internet_gateway" "default" {
vpc_id = "${aws_vpc.default.id}"
}

/* Public subnet */
resource "aws_subnet" "public" {
vpc_id = "${aws_vpc.default.id}"
cidr_block = "${var.public_subnet_cidr}"
availability_zone = "us-west-1a"
map_public_ip_on_launch = true
depends_on = ["aws_internet_gateway.default"]
tags {
Name = "public"
}
}

/* Routing table for public subnet */
resource "aws_route_table" "public" {
vpc_id = "${aws_vpc.default.id}"
route {
cidr_block = "0.0.0.0/0"
gateway_id = "${aws_internet_gateway.default.id}"
}
}

/* Associate the routing table to public subnet */
resource "aws_route_table_association" "public" {
subnet_id = "${aws_subnet.public.id}"
route_table_id = "${aws_route_table.public.id}"
}
68 changes: 68 additions & 0 deletions terraform/security-groups.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/* Default security group */
resource "aws_security_group" "default" {
name = "default-airpair-example"
description = "Default security group that allows inbound and outbound traffic from all instances in the VPC"
vpc_id = "${aws_vpc.default.id}"

ingress {
from_port = "0"
to_port = "0"
protocol = "-1"
self = true
}

tags {
Name = "airpair-example-default-vpc"
}
}


/* Security group for the nat server */
resource "aws_security_group" "nat" {
name = "nat-airpair-example"
description = "Security group for nat instances that allows SSH and VPN traffic from internet"
vpc_id = "${aws_vpc.default.id}"

ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}

ingress {
from_port = 1194
to_port = 1194
protocol = "udp"
cidr_blocks = ["0.0.0.0/0"]
}

tags {
Name = "nat-airpair-example"
}
}

/* Security group for the web */
resource "aws_security_group" "web" {
name = "web-airpair-example"
description = "Security group for web that allows web traffic from internet"
vpc_id = "${aws_vpc.default.id}"

ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}

ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}

tags {
Name = "web-airpair-example"
}
}
27 changes: 27 additions & 0 deletions terraform/ssh/insecure-deployer
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA4nE0/9qcJ0MP7GB0lBxWpXnRhKfY1xnykwV6zNxb84ulkL0F
SSt0UIps9aiR/irO7pj2ZIy+aqWGTzv4uIMD3zAYrpQneten8jDUvs5yA8DuQM74
QiggfM54ErWDfxTGb6IB/tvQoQit+0NyyOXPo9XHkHlkO0oIpXUKHqt278yzaUpo
1+eh0x3YgE8KmxIsB3jKw8ohlkxbKyNYdOVXyOdr0gS2Zk/hGS/p3hpguSa/4hsP
mPQi5YJzEY+ogSvqurJP7YULxNfEZH50JZE9Ooa8jAL5I8GdwUHa4RJS2P7ilYuf
Y475MLOyLdDfJQQpaT1arkRxRCyX38XJ+8aKcQIDAQABAoIBAEecsbwwcK3iAYkp
v/SPOb+/VMl1I5hzNknUs89R6SqOgV/Sx3cqbPCDto3CL9mHxEWkzldiQ14K1vz7
5F7F4FWXKlcbt5ib1xs64i0tsNULEM4iJlUVx6Bw03xnNxzbfx4SyDrHXaVvz0Xl
QMnUE+SmWSSRn2c4tJ9O8lJcu5J+O/0a1xkJe6hE6p4R+lzCvjMaVOc6e7IceOvk
OXuItY2zhLOUCrCaQuSeC9WVf0Y3zxyfiG8m8Dy/io4DIcOdgrgKMQlh6E/OxLC7
DR2tKnwElbRdHFwufeq1+kObcfcG3EbWZS2dkJL6YaVXrTtBevqBoolcpcKXRBua
HC26K3kCgYEA8dFNLaoPh4DTbJz8e0/eCAfD+Pm68Q8sK/FuIdgZPzlnB+NiD+Y1
y5RdwhDJ558pkBsfZ8wNj/2Ld0Jkr/lezQ5DI0aIIsTx96fglL//4/8uhaRCnesr
mvMfFsUS8tXbTL534UNDTeoAQf0oqn1M5Wfy+4SATkiHpkPUTK64npMCgYEA77kO
fwpc8sydPZT01IclFZ+aokpTiDeUQJyuAfkJcgfeCRWumnyVECwM60JElIaSOtB2
DBAApLJDOf4umt8DQuguJGHIS8RMzmXpUX3+7ic5ESvychSO3tjbu2s/znRrAtWv
eM8DPJlL/3jyeziK2KUQzNuqHDlELCUq1BXpkWsCgYAcWUAmAVDOvuCKVCEZR7Ss
1lQ4JPaweengwO37U70p903H0/VUDdXyptMTBCrXV4Zk2XkmDvrsDXpDIepx4tcl
TO27/fHJubLwKKMgbR3PmcPXcPlKUB6NjMDxR2tAQqfx6EZfhyYlxTAAjHAvBH92
SWhn6hGsm74jVMJXtwf3twKBgQCn8vP4B2+lX7tOOLzq5SATLTWuO/qX9bB1MBAt
K6f1bxOdM8aXT28z3FjUviHEGR/7+q6pttBsksPMrotCT7o+NuKU9LjadFYHSJkV
Ufu4KFyv7iU2zbZm5HHVtccHQsLyQnlkX0x6OUBoZPklYTDNpZ/GlqNwkKJ1dzix
TATOrwKBgG3JFEG1Bxlpn7wJzrRtcbrERXpzul04KLEuokZYfQD+hcy4G2dJWpoT
arwtA7tEvcSI+YIWDKgjlVe6SqWrFStYdPo4BtVyafUusypmfdtjKUqp63SlnPmz
ARIVPJZg6wC9FsoZguPlO3avsLpxf2N252UbRJ2jhFUjUUjM63wy
-----END RSA PRIVATE KEY-----
1 change: 1 addition & 0 deletions terraform/ssh/insecure-deployer.pub
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDicTT/2pwnQw/sYHSUHFaledGEp9jXGfKTBXrM3Fvzi6WQvQVJK3RQimz1qJH+Ks7umPZkjL5qpYZPO/i4gwPfMBiulCd616fyMNS+znIDwO5AzvhCKCB8zngStYN/FMZvogH+29ChCK37Q3LI5c+j1ceQeWQ7SgildQoeq3bvzLNpSmjX56HTHdiATwqbEiwHeMrDyiGWTFsrI1h05VfI52vSBLZmT+EZL+neGmC5Jr/iGw+Y9CLlgnMRj6iBK+q6sk/thQvE18RkfnQlkT06hryMAvkjwZ3BQdrhElLY/uKVi59jjvkws7It0N8lBClpPVquRHFELJffxcn7xopx insecure-deployer
36 changes: 36 additions & 0 deletions terraform/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
variable "access_key" {
description = "AWS access key"
}

variable "secret_key" {
description = "AWS secert access key"
}

variable "region" {
description = "AWS region"
default = "us-west-1"
}

variable "vpc_cidr" {
description = "CIDR for VPC"
default = "10.128.0.0/16"
}

variable "public_subnet_cidr" {
description = "CIDR for public subnet"
default = "10.128.0.0/24"
}

variable "private_subnet_cidr" {
description = "CIDR for private subnet"
default = "10.128.1.0/24"
}

/* Ubuntu 14.04 amis by region */
variable "amis" {
description = "Base AMI to launch the instances with"
default = {
us-west-1 = "ami-049d8641"
us-east-1 = "ami-a6b8e7ce"
}
}