12 Commits

Author SHA1 Message Date
d87f7117d1 Adding latest 2020-11-19 19:39:06 +00:00
c4dd5c1463 Updating subnets 2020-07-30 02:19:48 +01:00
fcd82ae4e5 Updating subnets 2020-07-30 02:18:29 +01:00
7fb2ea43f5 Commenting out DB Subnets 2020-07-30 02:16:44 +01:00
f13baee42f Editing subnets 2020-07-30 02:13:59 +01:00
403e007d05 Adding VPC/Subnets to config files 2020-07-30 01:59:24 +01:00
b33a7001b5 Changing to security group name rather than ID 2020-07-30 01:42:29 +01:00
1f91092468 Updating eb config 2020-07-30 01:25:25 +01:00
149a5a199d Updating single instance 2020-07-30 01:20:16 +01:00
cae918f832 Single instance, external DB
eb create --single
2020-07-30 00:42:23 +01:00
e860a4557c Updating single instance configs 2020-07-29 15:39:12 +01:00
b07e4e1b18 Creating single instance with db
eb create --single --database
2020-07-29 15:33:54 +01:00
12 changed files with 284 additions and 44 deletions

View File

@@ -1,10 +1,10 @@
option_settings:
# aws:elasticbeanstalk:environment:
# EnvironmentType: SingleInstance
# aws:rds:dbinstance:
# DBEngine: postgres
# DBInstanceClass: "db.t2.micro"
# DBAllocatedStorage: 5
# DBUser: strapi
aws:rds:dbinstance:
DBEngine: postgres
DBInstanceClass: "db.t2.micro"
DBAllocatedStorage: 5
DBUser: strapi
aws:ec2:instances:
InstanceTypes: "t2.micro"

View File

@@ -5,16 +5,16 @@ option_settings:
value: true
- option_name: STRAPI_LOG_LEVEL
value: debug
- option_name: STRAPI_S3_ACCESS_KEY
value: AKIA23D4RF6OZWGDKV7W
- option_name: STRAPI_S3_SECRET_KEY
value: "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"
# - option_name: STRAPI_S3_ACCESS_KEY
# value: AKIA23D4RF6OZWGDKV7W
# - option_name: STRAPI_S3_SECRET_KEY
# value: "4sb/fxewDGjMYLocjclPCWDm7JTBCYuFBjQAbbBR"
- option_name: STRAPI_S3_REGION
value: "eu-west-1"
- option_name: STRAPI_S3_BUCKET
value: "elb-example-bucket-cf"
value: "prod-strapi-eb-strapi-uploads"
- option_name: RDS_HOSTNAME
value: prod-strapi-elb.chgwfe43ss59.eu-west-1.rds.amazonaws.com
value: prod-strapi-eb.chgwfe43ss59.eu-west-1.rds.amazonaws.com
- option_name: RDS_PORT
value: 5432
- option_name: RDS_NAME

View File

@@ -1,3 +1,4 @@
# Permanantly disabled
# container_commands:
# installpg:
# command: "npm install pg"

View File

@@ -1,12 +1,11 @@
# Not needed in a single environment
option_settings:
# aws:ec2:vpc:
# VPCId: vpc-02f98fa754899162c
# Subnets: "subnet-0b17872a2b9315fad,subnet-0342e8a0a77b30e23,subnet-0eacb84d238279a58"
# DBSubnets: "subnet-0b17872a2b9315fad,subnet-0342e8a0a77b30e23,subnet-0eacb84d238279a58"
# ELBSubnets: "subnet-0b17872a2b9315fad,subnet-0342e8a0a77b30e23,subnet-0eacb84d238279a58"
# aws:autoscaling:launchconfiguration:
# SecurityGroups: sg-07a97fc88ba143f26
aws:ec2:vpc:
VPCId: vpc-016efd8cfbcca99a8
Subnets: "subnet-00c0725542e08b1d7,subnet-039fd98ceb88c863c,subnet-0b9fab172a19d818b"
# DBSubnets: "subnet-00c0725542e08b1d7,subnet-039fd98ceb88c863c,subnet-0b9fab172a19d818b"
# ELBSubnets: "subnet-00c0725542e08b1d7,subnet-039fd98ceb88c863c,subnet-0b9fab172a19d818b"
aws:autoscaling:launchconfiguration:
SecurityGroups: sg-087f33381c535528b
# aws:elbv2:loadbalancer:
# ManagedSecurityGroup: sg-0e6f91df2ed07050a
# SecurityGroups: sg-0e6f91df2ed07050a

View File

@@ -1,4 +1,4 @@
option_settings:
aws:elbv2:listener:443:
Protocol: HTTPS
SSLCertificateArns: arn:aws:acm:eu-west-1:745437999005:certificate/218876af-7f8d-4022-97af-ad982aa540bc
# option_settings:
# aws:elbv2:listener:443:
# Protocol: HTTPS
# SSLCertificateArns: arn:aws:acm:eu-west-1:745437999005:certificate/218876af-7f8d-4022-97af-ad982aa540bc

View File

@@ -0,0 +1,73 @@
# Security groups
## Load balanced
1 for the EC2 instances (applied to the autoscaler).
The instances can be private.
Gateway VPC needed for S3 upload.
1 for the RDS.
1 for the LB.
## Single instances
1 for the EC2 instances (applied to the autoscaler).
The instances need to be public.
No gateway VPC needed - they have internet access.
1 for the RDS.
If using `--database` you don't need to create any SG. Let EB use the default VPC. It will create everything for you.
If not using `--database`:
EC2:
- Create a SG for EC2
- Should have ingress from all (0.0.0.0:80+443)
- Should have egress to all (0.0.0.0:all)
RDS:
- Specify the `security_group_ids` with the SG of the EC2 and EB will create the SG for you with this as ingress for the SG you pass in.
- Specify `associate_security_group_ids` to attach a security group to the RDS (if you need to enable public access)
## Commands
Deploy CF
`aws --profile admin cloudformation deploy --template-file ./03-stack-rdsinstance.yaml --stack-name strapi-rds --parameter-overrides StackName=strapi-vpc --tags git=web-dev owner=home project=strapi-elb test=true deployment=cloudformation`
Destroy CF
`aws --profile admin cloudformation delete-stack --stack-name strapi-rds`
Terraform
`gmake plan`
`gmake applu`
`gmake destroy`
EB Single instance
`eb create --single`
with DB
`eb create --single --database`
Deploy code to environment
`apps-awsebcli`
Health check
`eb health`
Open the URL
`eb open`
Terminate
`eb terminate`

View File

@@ -40,3 +40,41 @@ VPC terraform will create
- You create subnets for a VPC. These subnets will be split evenly across availability zones (for redundancy) and private/local (whether they have internet access or not).
- Behind the scenes (if using TF), internet gateway, routing tables, attachments will all be created for you. If using CF you will need to create these yourself.
- A security group is a firewall that is _attached to an EC2 instance_. A security group belongs to a VPC. You can permit instances to talk to each other by setting the source and destination to be the security group itself. You can control ports/ips exactly on an instance basis using security groups.
## HTTPS
### Single instance
As it terminates on the Ec2 instance itself, you need to ammend the nginx config locally. This is specific for each application you are deploying.
<https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/https-singleinstance-nodejs.html>.
You need to generate a certificate locally.
`pip install certbot`
`sudo certbot certonly --manual --preferred-challenges=dns --email dtomlinson@panaetius.co.uk --server https://acme-v02.api.letsencrypt.org/directory --agree-tos -d "*.panaetius.co.uk"`
### Load balanced
You have two options:
1. Terminate on the load balancer (easiest).
<https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/configuring-https-elb.html>.
You can use AWS Certificate manager to generate your SSL cert, or you can upload your own.
Use a .config file as documented above and EB will handle the rest.
2. Pass through to the instance.
<https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/https-tcp-passthrough.html>.
If you do this you need to set up termination on the EC2 instances using the config for a single instance above.
You can TCP pass through without the load balancer decrypting the traffic. The traffic is encrypted all the way to the instance. The instances between themselves are HTTP.
Additionally you can configure end-to-end encryption between the EC2 instances if you have strict security requirements.
<https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/configuring-https-endtoend.html>.

View File

@@ -1,2 +1,39 @@
Connecting external DB:
Create RDS using TF @important @today
Create RDS using TF @important @today @done (7/28/2020, 11:34:12 PM)
RDS Config:
☐ Try using `associate_security_group_ids` and creating a security group to allow all incoming traffic to the RDS instance.
Email:
☐ Add `strapi-provider-email-amazon-ses` and configure.
Deployments:
One:
✔ Create S3 bucket for strapi s3. @done (7/29/2020, 2:07:55 PM)
✔ Deploy TF with additional SG for DB. @done (7/30/2020, 3:02:39 AM)
☐ Have TF produce outputs with everything needed.
✔ Redeploy single instance with the EB config file with VPCs created. @done (7/30/2020, 3:02:41 AM)
Two:
☐ Have SSL enabled for single instance.
Three:
☐ Have SSL enabled for multiple instance.
Misc:
☐ Have the EB instances on the private subnet.
☐ Create a Gateway VPC endpoint: <https://docs.aws.amazon.com/vpc/latest/userguide/vpce-gateway.html>.
Prod Steps:
☐ Plan out the posts needed for the series.
This needs to be done at the same time as writing the site pages.
☐ Create everything from scratch
Strapi:
☐ Install from new.
☐ Create TF files.
☐ Initialise EB environment.
☐ Deploy TF.
☐ Deploy EB environment for single instance to start.
Today:
☐ Redeploy with updated config.
☐ Enable HTTPs for single instance.
☐ Use S3 to read in secrets.

1
infrastructure/.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1 @@
{}

View File

@@ -8,7 +8,7 @@ provider "aws" {
# tags
locals {
tags = {
"Project" = "strapi-elb"
"Project" = "strapi-eb"
"Description" = "Terraform resources for strapi in Elastic Beanstalk"
}
}
@@ -16,18 +16,20 @@ locals {
# Network
module "vpc" {
source = "git::https://github.com/cloudposse/terraform-aws-vpc?ref=tags/0.14.0"
source = "git::https://github.com/cloudposse/terraform-aws-vpc.git?ref=tags/0.14.0"
stage = var.stage
name = var.name
tags = local.tags
cidr_block = "172.16.0.0/16"
enable_default_security_group_with_custom_rules = false
}
module "subnets" {
source = "git::https://github.com/cloudposse/terraform-aws-dynamic-subnets?ref=tags/0.23.0"
source = "git::https://github.com/cloudposse/terraform-aws-dynamic-subnets.git?ref=tags/0.23.0"
stage = var.stage
name = var.name
tags = local.tags
availability_zones = ["eu-west-1a", "eu-west-1b", "eu-west-1c"]
vpc_id = module.vpc.vpc_id
@@ -37,12 +39,59 @@ module "subnets" {
nat_instance_enabled = false
}
resource "aws_security_group" "ec2_security_group" {
name = "${var.stage}-${var.name}-ec2_sg"
description = "Security group assigned to the Elastic Scaling group that is applied to the EC2 instances."
vpc_id = module.vpc.vpc_id
tags = local.tags
ingress {
description = "HTTP"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
description = "HTTPS"
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
description = "Outbound to all"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
resource "aws_security_group" "rds_security_group_public" {
name = "${var.stage}-${var.name}-rds_public_sg"
description = "Security group for the RDS instance that allows public access from the internet."
vpc_id = module.vpc.vpc_id
tags = local.tags
ingress {
description = "Incoming Postgres"
from_port = 5432
to_port = 5432
protocol = "tcp"
cidr_blocks = ["82.6.205.148/32"]
}
}
# RDS instance
module "rds_instance" {
source = "git::https://github.com/cloudposse/terraform-aws-rds.git?ref=tags/0.20.0"
stage = var.stage
name = var.name
tags = local.tags
allocated_storage = 5
database_name = "postgres"
@@ -53,12 +102,18 @@ module "rds_instance" {
engine = "postgres"
engine_version = "12.3"
instance_class = "db.t2.micro"
security_group_ids = [aws_security_group.ec2_security_group.id]
associate_security_group_ids = [aws_security_group.rds_security_group_public.id]
subnet_ids = module.subnets.public_subnet_ids
vpc_id = module.vpc.vpc_id
publicly_accessible = true
tags = local.tags
}
# Set maintenance window
# subnet_ids and vpc_id required
# need a security group for the DB with ingress rule allowing inbound from the autoscaler/EB security group (does a single instance have an SC?) - use 0.0.0.0 for initial creation then change the TF stack with the EB security group once it's created.
# S3 bucket
resource "aws_s3_bucket" "static_assets" {
bucket = "${var.stage}-${var.name}-strapi-uploads"
acl = "private"
tags = local.tags
}

View File

@@ -0,0 +1,36 @@
# S3
output "s3_static_assets_id" {
value = aws_s3_bucket.static_assets.id
description = "Name of the static assets S3 bucket."
}
# VPC
output "vpc_id" {
value = module.vpc.vpc_id
description = "The ID of the VPC."
}
output "subnet_public_ids" {
value = module.subnets.public_subnet_ids
description = "The IDs of the public subnets."
}
# Security groups
output "aws_security_group_ec2_security_group" {
value = aws_security_group.ec2_security_group.id
description = "Security group for the EC2 instances applied by the Elastic Scaler."
}
output "aws_security_group_ec2_security_group_rds" {
value = aws_security_group.rds_security_group_public.id
description = "Security group for the RDS instance allowing public access."
}
# RDS
output "rds_instance_endpoint" {
value = module.rds_instance.instance_endpoint
description = "Endpoint of the RDS instance."
}

View File

@@ -1,5 +1,5 @@
# module
name = "strapi-elb"
name = "strapi-eb"
region = "eu-west-1"
stage = "prod"
profile = "admin"