22 Commits

Author SHA1 Message Date
1bde508461 updating documentation 2020-05-03 04:59:55 +01:00
f8f0e9a688 adding latest documentation from loadbalanced branch 2020-05-03 04:41:40 +01:00
b16b747414 updating documentation 2020-05-03 00:23:34 +01:00
bae738ad98 updating VPC config 2020-05-02 23:21:07 +01:00
331643fbf7 updating docs 2020-05-02 02:56:24 +01:00
12a967b92e adding https strapi.panaetius.co.uk 2020-05-02 02:56:18 +01:00
2281dd34fd removing default security group config 2020-05-01 19:59:58 +01:00
ab6d220f8c updating RDS CF template 2020-05-01 19:59:44 +01:00
3d58f2c5d6 updating RDS env var 2020-05-01 19:59:30 +01:00
f5a5dc4410 updating VPC config 2020-05-01 19:44:26 +01:00
16058e296d updating notes 2020-05-01 19:44:21 +01:00
aaae536003 updating VPC CF template 2020-05-01 19:44:14 +01:00
c97321790b working config 2020-05-01 02:59:59 +01:00
3fc49078ab changing minsize to 2 2020-05-01 01:48:07 +01:00
9ba7de1ad2 adding ELB subnets 2020-05-01 00:02:26 +01:00
008aa708bf commenting out ELB config 2020-05-01 00:02:19 +01:00
c1e515d28b updating notes 2020-04-30 23:55:29 +01:00
ea12dc3827 updating CF templates 2020-04-30 23:55:24 +01:00
31936a6729 commenting out single instance 2020-04-30 23:55:16 +01:00
bea77bf9fa adding VPC to ELB config 2020-04-30 23:55:10 +01:00
b60bebbddc adding custom securitygroup to deployment 2020-04-30 19:47:15 +01:00
67951f21f4 changing ip to home only 2020-04-30 19:05:40 +01:00
11 changed files with 387 additions and 139 deletions

View File

@@ -7,6 +7,77 @@ Resources:
CidrBlock: "172.31.0.0/16"
EnableDnsHostnames: true
EnableDnsSupport: true
ELBSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: !Sub "${AWS::StackName}-ELBSecurityGroup"
GroupDescription: Security group for the Elastic Load Balancer.
This permits inbound 80/443 from any IP, to 80/443 to the
Auto Scaling security group.
VpcId: !Ref PublicVPC
ELBSecurityGroupIngressHttp:
Type: AWS::EC2::SecurityGroupIngress
Properties:
Description: Ingress for ELBSecurityGroup for HTTP.
GroupId: !Ref ELBSecurityGroup
IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
ELBSecurityGroupIngressHttps:
Type: AWS::EC2::SecurityGroupIngress
Properties:
Description: Ingress for ELBSecurityGroup for HTTPS.
GroupId: !Ref ELBSecurityGroup
IpProtocol: tcp
FromPort: 443
ToPort: 443
CidrIp: 0.0.0.0/0
ELBSecurityGroupEgressHttp:
Type: AWS::EC2::SecurityGroupEgress
Properties:
Description: Egress for ELBSecurityGroup for HTTP.
GroupId: !Ref ELBSecurityGroup
IpProtocol: tcp
FromPort: 80
ToPort: 80
SourceSecurityGroupId: !Ref ASSecurityGroup
ELBSecurityGroupEgressHttps:
Type: AWS::EC2::SecurityGroupEgress
Properties:
Description: Egress for ELBSecurityGroup for HTTPS.
GroupId: !Ref ELBSecurityGroup
IpProtocol: tcp
FromPort: 443
ToPort: 443
SourceSecurityGroupId: !Ref ASSecurityGroup
ASSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: !Sub "${AWS::StackName}-ASSecurityGroup"
GroupDescription: Security group for the Auto Scaler. This security group
will be applied to any EC2 instances that the Auto Scaler creates. This
group permits inbound 80/443 from the Elastic Load Balancer security
group.
VpcId: !Ref PublicVPC
ASSecurityGroupIngressHttp:
Type: AWS::EC2::SecurityGroupIngress
Properties:
Description: Ingress for ASSecurityGroup for HTTP.
GroupId: !Ref ASSecurityGroup
IpProtocol: tcp
FromPort: 80
ToPort: 80
SourceSecurityGroupId: !Ref ELBSecurityGroup
ASSecurityGroupIngressHttps:
Type: AWS::EC2::SecurityGroupIngress
Properties:
Description: Ingress for ASSecurityGroup for HTTPS.
GroupId: !Ref ASSecurityGroup
IpProtocol: tcp
FromPort: 443
ToPort: 443
SourceSecurityGroupId: !Ref ELBSecurityGroup
PublicSubnet0:
Type: AWS::EC2::Subnet
Properties:
@@ -72,27 +143,37 @@ Resources:
RouteTableId: !Ref PublicRouteTable
Outputs:
PublicVPCID:
Description: The VPC ID.
Description: The VPC for the environment.
Value: !Ref PublicVPC
Export:
Name: !Sub "${AWS::StackName}-PublicVPC"
PublicVPCIDDefaultSecurityGroup:
Description: The VPC default security group.
Value: !GetAtt PublicVPC.DefaultSecurityGroup
ELBSecurityGroupOutput:
Description: ELB Security Group
Value: !Ref ELBSecurityGroup
Export:
Name: !Sub "${AWS::StackName}-PublicVPCIDDefaultSecurityGroup"
Name: !Sub "${AWS::StackName}-ELBSecurityGroup"
ASSecurityGroupOutput:
Description: AS Security Group
Value: !Ref ASSecurityGroup
Export:
Name: !Sub "${AWS::StackName}-ASSecurityGroup"
# PublicVPCIDDefaultSecurityGroup:
# Description: The VPC default security group.
# Value: !GetAtt PublicVPC.DefaultSecurityGroup
# Export:
# Name: !Sub "${AWS::StackName}-PublicVPCIDDefaultSecurityGroup"
PublicSubnet0ID:
Description: The ID of the subnet.
Description: The public subnet 0.
Value: !Ref PublicSubnet0
Export:
Name: !Sub "${AWS::StackName}-PublicSubnet0"
PublicSubnet1ID:
Description: The ID of the subnet.
Description: The public subnet 1.
Value: !Ref PublicSubnet1
Export:
Name: !Sub "${AWS::StackName}-PublicSubnet1"
PublicSubnet2ID:
Description: The ID of the subnet.
Description: The public subnet 2.
Value: !Ref PublicSubnet2
Export:
Name: !Sub "${AWS::StackName}-PublicSubnet2"

View File

@@ -11,15 +11,6 @@ Parameters:
to prepend the name of other resources in other templates.
Type: String
Resources:
# VPCSecurityGroupIngress:
# Type: AWS::EC2::SecurityGroupIngress
# Properties:
# GroupId:
# Fn::ImportValue: !Sub "${StackName}-PublicVPCIDDefaultSecurityGroup"
# IpProtocol: tcp
# FromPort: 5432
# ToPort: 5432
# CidrIp: 0.0.0.0/0
RDSSubnetGroup:
Type: AWS::RDS::DBSubnetGroup
Properties:
@@ -36,10 +27,15 @@ Resources:
VpcId:
Fn::ImportValue: !Sub "${StackName}-PublicVPC"
SecurityGroupIngress:
IpProtocol: tcp
FromPort: 5432
ToPort: 5432
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 5432
ToPort: 5432
CidrIp: 82.6.205.148/32
- IpProtocol: tcp
FromPort: 5432
ToPort: 5432
SourceSecurityGroupId:
Fn::ImportValue: !Sub "${StackName}-ASSecurityGroup"
RDSDBInstance:
Type: AWS::RDS::DBInstance
Properties:

View File

@@ -0,0 +1,5 @@
# Resources:
# ElasticLoadBalancer:
# Type: AWS::ElasticLoadBalancingV2::TargetGroup
# Properties:
# VpcId: vpc-029d232726cbf591d

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:elasticbeanstalk:environment:
# EnvironmentType: SingleInstance
# aws:rds:dbinstance:
# DBEngine: postgres
# DBInstanceClass: "db.t2.micro"
# DBAllocatedStorage: 5
# DBUser: strapi
aws:ec2:instances:
InstanceTypes: "t2.micro"

View File

@@ -14,7 +14,7 @@ option_settings:
- option_name: STRAPI_S3_BUCKET
value: "elb-example-bucket-cf"
- option_name: RDS_HOSTNAME
value: srdtnvn77v7rqd.chgwfe43ss59.eu-west-1.rds.amazonaws.com
value: src2ziuj8oxjct.chgwfe43ss59.eu-west-1.rds.amazonaws.com
- option_name: RDS_PORT
value: 5432
- option_name: RDS_NAME

View File

@@ -1,9 +1,9 @@
Resources:
sslSecurityGroupIngress:
Type: AWS::EC2::SecurityGroupIngress
Properties:
GroupId: { "Fn::GetAtt": ["AWSEBSecurityGroup", "GroupId"] }
IpProtocol: tcp
ToPort: 443
FromPort: 443
CidrIp: 0.0.0.0/0
# Resources:
# sslSecurityGroupIngress:
# Type: AWS::EC2::SecurityGroupIngress
# Properties:
# GroupId: { "Fn::GetAtt": ["AWSEBSecurityGroup", "GroupId"] }
# IpProtocol: tcp
# ToPort: 443
# FromPort: 443
# CidrIp: 0.0.0.0/0

View File

@@ -1,5 +1,14 @@
option_settings:
aws:ec2:vpc:
VPCId: vpc-029d232726cbf591d
Subnets: "subnet-051fe56dc37d8396d,subnet-0ea9f2f165a57be27,subnet-09b28d722f41b2dde"
DBSubnets: "subnet-051fe56dc37d8396d,subnet-0ea9f2f165a57be27,subnet-09b28d722f41b2dde"
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:elbv2:loadbalancer:
ManagedSecurityGroup: sg-0e6f91df2ed07050a
SecurityGroups: sg-0e6f91df2ed07050a
aws:autoscaling:asg:
MinSize: 1
MaxSize: 4

View File

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

View File

@@ -11,6 +11,7 @@
* [Fix Version Numbers](#FixVersionNumbers)
* [Strapi in git](#Strapiingit)
* [Cloudformation](#Cloudformation)
* [Output naming convention](#Outputnamingconvention)
* [Creating templates](#Creatingtemplates)
* [Adding resources](#Addingresources)
* [Using parameters](#Usingparameters)
@@ -225,6 +226,23 @@ You can then run Strapi with `npm run develop` or `NODE_ENV=production npm run s
<https://adamtheautomator.com/aws-cli-cloudformation/> (example of deploying an S3 bucket with static site `index.html`.)
### <a name='Outputnamingconvention'></a>Output naming convention
You should follow a standard naming convention for your CF outputs.
For example:
```yaml
Outputs:
PublicVPCOutput:
Description: The VPC ID.
Value: !Ref PublicVPC
Export:
Name: !Sub "${AWS::StackName}-EBStrapiPublicVPC"
```
Defines a VPC. We can then pass in the stackname to another CF template and it can reference this VPC. The VPC names are static between projects (they don't have to be but here they are).
### <a name='Creatingtemplates'></a>Creating templates
To create a cloudformation template you should create a `template.yaml`. This yaml file should have at the top:

View File

@@ -11,9 +11,23 @@
_ [AWS::EC2::RouteTable](#AWS::EC2::RouteTable)
_ [AWS::EC2::Route](#AWS::EC2::Route)
_ [AWS::EC2::SubnetRouteTableAssociation](#AWS::EC2::SubnetRouteTableAssociation)
- [Running notes](#Runningnotes)
- [Reference an input parameter, or a resource ID from inside current template](#ReferenceaninputparameteroraresourceIDfrominsidecurrenttemplate) \* [Using `Fn::Sub`](#UsingFn::Sub)
- [Dynamically referencing resources from another stack.](#Dynamicallyreferencingresourcesfromanotherstack.)
- [Running notes](#Runningnotes) \* [Database](#Database)
- [Work Commands](#WorkCommands)
_ [tags](#tags)
_ [deploy](#deploy)
_ [delete](#delete)
_ [describe-stack-resources](#describe-stack-resources)
- [Adding SSL to ELB](#AddingSSLtoELB) \* [With load balancer](#Withloadbalancer)
- [EB Templates/Resources](#EBTemplatesResources)
- [Configuring security groups](#Configuringsecuritygroups)
- [Elastic Load Balancer](#ElasticLoadBalancer)
_ [Elastic Scaler](#ElasticScaler)
_ [RDS](#RDS) \* [Security group to allow EC2 instances to talk to each other](#SecuritygrouptoallowEC2instancestotalktoeachother)
- [Custom VPC + Subnets in EB](#CustomVPCSubnetsinEB)
- [Using cloudformation functions in EB config files](#UsingcloudformationfunctionsinEBconfigfiles)
- [Creating a read replica RDS](#CreatingareadreplicaRDS)
- [Multiple security groups on the same resource](#Multiplesecuritygroupsonthesameresource)
- [Private subnets](#Privatesubnets)
<!-- vscode-markdown-toc-config
numbering=false
@@ -25,7 +39,7 @@
## <a name='Decoupling'></a>Decoupling
When creating an ELB instance with `--single` and `--database` the following is created as part of the ELB deployment:
When creating an EB instance with `--single` and `--database` the following is created as part of the EB deployment:
- security group
- EIP
@@ -41,15 +55,15 @@ Export these in the CF template with stackname (<https://docs.aws.amazon.com/AWS
A security group is a resource that defines what IPs/Ports are allowed on inbound/outbound for an AWS resource. You can have one for EC2 instance, or RDS among others.
ELB will create a VPC for your EC2 instances.
EB will create a VPC for your EC2 instances.
You should use this VPC for you RDS instance.
Creating a VPC for ELB (with RDS) <https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/vpc-rds.html>
Creating a VPC for EB (with RDS) <https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/vpc-rds.html>
## <a name='Singleinstancenoloadbalancer'></a>Single instance (no load balancer)
Example cloudformation template that ELB uses: <https://raw.githubusercontent.com/awslabs/elastic-beanstalk-samples/master/cfn-templates/vpc-public.yaml>.
Example cloudformation template that EB uses: <https://raw.githubusercontent.com/awslabs/elastic-beanstalk-samples/master/cfn-templates/vpc-public.yaml>.
Create a VPC - this is an object that spans all availability zones in a region. You assign a VPC a CIDR block. This is a set of IP addresses that this VPC has access to.
@@ -125,7 +139,7 @@ Database needs a security group creating
EC2 security groups automatically created and associated with the VPC.
Use aws:ec2:vpc (https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/command-options-general.html#command-options-general-ec2vpc)
### Database
### <a name='Database'></a>Database
Needs:
@@ -143,30 +157,190 @@ Default ports:
| SQL Server | 1433 |
| DynamoDB | 8000 |
## <a name='WorkCommands'></a>Work Commands
### <a name='tags'></a>tags
## Work Commands
`--tags git=web-dev owner=home project=strapi-eb test=true deployment=cloudformation`
### deploy
### <a name='deploy'></a>deploy
`aws --profile admin cloudformation deploy --template-file ./02-stack-vpc.yaml --stack-name strapi-vpc --tags git=web-dev owner=home project=strapi-elb test=true deployment=cloudformation`
`aws --profile admin cloudformation deploy --template-file ./02-stack-vpc.yaml --stack-name strapi-vpc --tags git=web-dev owner=home project=strapi-eb test=true deployment=cloudformation`
`aws --profile admin cloudformation deploy --template-file ./02-stack-vpc.yaml --stack-name new-temp-vpc --tags git=web-dev owner=home project=strapi-elb test=true deployment=cloudformation`
`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-eb test=true deployment=cloudformation`
`aws --profile admin cloudformation deploy --template-file ./03-stack-rdsinstance.yaml --stack-name strapi-rds --parameter-overrides StackName=strapi-vpc`
### <a name='delete'></a>delete
### delete
`aws --profile admin cloudformation delete-stack --stack-name strapi-vpc`
`aws --profile admin cloudformation delete-stack --stack-name temp-vpc`
`aws --profile admin cloudformation delete-stack --stack-name new-temp-vpc`
`aws --profile admin cloudformation delete-stack --stack-name strapi-rds`
`aws --profile admin cloudformation delete-stack --stack-name temp`
List of all RDS Engines available under "Engine" header: <https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_CreateDBInstance.html>.
### descrive-stack-resources
### <a name='describe-stack-resources'></a>describe-stack-resources
Will print a json list of all resources in the stack
`aws --profile admin cloudformation describe-stack-resources --stack-name strapi-vpc`
Using `jq` for formatting:
`aws --profile admin cloudformation describe-stack-resources --stack-name strapi-vpc | jq -r '.StackResources[] | .ResourceType + ": " + .PhysicalResourceId'`
## <a name='AddingSSLtoELB'></a>Adding SSL to ELB
You should generate an SSL Certificate in Certificate Manager for your domain. To do this you will need to create a CNAME record to verify you have access to the DNS settings.
At the same time you should create a CNAME record that maps your subdomain (<strapi.panaetius.co.uk>) to the DNS name AWS has given your load balancer (<awseb-AWSEB-68CXGV0UTROU-1492520139.eu-west-1.elb.amazonaws.com>).
### <a name='Withloadbalancer'></a>With load balancer
A load balancer is not free! It costs ~£15 a month.
- Configure the load balancer listener in a EB `.config` file:
```yaml
option_settings:
aws:elbv2:listener:443:
Protocol: HTTPS
SSLCertificateArns: arn:aws:acm:eu-west-1:745437999005:certificate/218876af-7f8d-4022-97af-ad982aa540bc
```
## <a name='EBTemplatesResources'></a>EB Templates/Resources
Good repo for examples: <https://github.com/awsdocs/elastic-beanstalk-samples>
Creating a VPC for RDS in EB: <https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/vpc-rds.html>
CF RDS EB template: <https://github.com/garystafford/aws-rds-postgres/blob/master/cfn-templates/rds.template>
Decouple an exisitng RDS instance from ELB to RDS: <https://aws.amazon.com/premiumsupport/knowledge-center/decouple-rds-from-beanstalk/>
## <a name='Configuringsecuritygroups'></a>Configuring security groups
## <a name='ElasticLoadBalancer'></a>Elastic Load Balancer
Should set: inbound/outbound 80/443 on 0.0.0.0/0
The option_settings: aws:elbv2:loadbalancer has two options for security groups.
| Option | Description |
| -------------------- | --------------------------------------------------------------------- |
| ManagedSecurityGroup | Defines the security group that is used for the load balancer itself. |
| SecurityGroups | Is a list of additional security groups you want to attach. |
If you define a ManagedSecurityGroup you should set SecurityGroups as well to the same one.
Load balancer needs a security group that allows incoming 80 + 443 from anywhere
It should also set the same for outbound as well
This security group should be set in `aws:elbv2:loadbalancer` under
`ManagedSecurityGroup` and `SecurityGroups`
### <a name='ElasticScaler'></a>Elastic Scaler
Should set inbound 80/443 from LBSG.
EB will create a security group for the EC2 instances. In addition to this, you can create a new security group that will be applied to EC2 instances the elastic scaler creates.
This is set under `aws:autoscaling:launchconfiguration`.
### <a name='RDS'></a>RDS
Should set: inbound 5432 from Scaling SG + home ip (change port and home ip).
The database should have a security group creating that allows incoming connections from the EC2 instances only.
### <a name='SecuritygrouptoallowEC2instancestotalktoeachother'></a>Security group to allow EC2 instances to talk to each other
Security group rule to allow instances in the same security group to talk to one another: <https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/security-group-rules-reference.html#sg-rules-other-instances>.
## <a name='CustomVPCSubnetsinEB'></a>Custom VPC + Subnets in EB
In a `.config` file specify the subnets for each tier of your app:
```yaml
option_settings:
aws:ec2:vpc:
VPCId: "vpc-003597eb63a0a3efe"
Subnets: "subnet-02cd8f7981ddfe345,subnet-02d9e1338e8d92d09,subnet-0e07d4d35394db524"
DBSubnets: "subnet-02cd8f7981ddfe345,subnet-02d9e1338e8d92d09,subnet-0e07d4d35394db524"
```
## <a name='UsingcloudformationfunctionsinEBconfigfiles'></a>Using cloudformation functions in EB config files
Only certain CF functions can be used in EB config files. For anything more advanced you should use Terraform to deploy additional resources alongside an EB template.
Reddit discussion on the topic: <https://www.reddit.com/r/aws/comments/a2uoae/is_there_a_way_to_reference_an_elastic_beanstalk/>.
EB documentaion on what functions are supported: <https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/ebextensions-functions.html#ebextensions-functions-getatt>.
You cannot use `FN::ImportValue` to reference a resource in another Cloudformation stack.
You can use join for resources that EB creates itself: `!Join [ ":", [ !Ref "AWS::StackName", AccountVPC ] ]`.
## <a name='CreatingareadreplicaRDS'></a>Creating a read replica RDS
To have a replica database you should create a new DB instance with same AllocatedStorage size and DBInstanceClass. You should set the SourceDBInstanceIdentifier to be a `!Ref` of your primary DB. You should also set the SourceRegion.
Read replica CF docs: <https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-database-instance.html#cfn-rds-dbinstance-sourcedbinstanceidentifier>
## <a name='Multiplesecuritygroupsonthesameresource'></a>Multiple security groups on the same resource
Multiple security groups get squashed to determine what is and isn't allowed: <https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-security-groups.html>.
## <a name='Privatesubnets'></a>Private subnets
You can create private subnets that do not have an internet gateway attached to them. An example of CF template is <https://github.com/awsdocs/elastic-beanstalk-samples/blob/master/cfn-templates/vpc-privatepublic.yaml>.
You need a nat gateway to allow private subnets to go out to the internet.
If you use private subnets, the nat gateway is not cheap - £30 a month.
You dont need the nat gateway, you can achieve the same thing with security groups (block all incoming) (explained <https://www.reddit.com/r/aws/comments/75bjei/private_subnets_nats_vs_simply_only_allowing/>).
An advantage to NAT is all outgoing requests to the internet come from a single IP.
## Using certbot CLI to generate SSL
### Wildcard certificate
In a new virtualenv install certbot:
```bash
pip install certbot
```
Run the `certbot` command:
```bash
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"
```
Follow the instructions to add a `TXT` record to your DNS server for validation.
When finished you should see:
```markdown
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/panaetius.co.uk/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/panaetius.co.uk/privkey.pem
Your cert will expire on 2020-08-01. To obtain a new or tweaked
version of this certificate in the future, simply run certbot
again. To non-interactively renew _all_ of your certificates, run
"certbot renew"
- Your account credentials have been saved in your Certbot
configuration directory at /etc/letsencrypt. You should make a
secure backup of this folder now. This configuration directory will
also contain certificates and private keys obtained by Certbot so
making regular backups of this folder is ideal.
```
## Terraform
### Elastic Beanstalk
Editing the EB default resources in Terraform: <https://github.com/cloudposse/terraform-aws-elastic-beanstalk-environment/issues/98#issuecomment-620677233>.

121
todo.md
View File

@@ -1,111 +1,72 @@
# To Do
~~Finish S3 config for env vars~~
~~Deploy to AWS and ensure vars are working~~
## Immediate
~~Use cloudformation to deploy bucket instead of tieing it to the RDS instance.~~
Use <https://strapi.io/documentation/3.0.0-beta.x/deployment/amazon-aws.html#_2-create-the-bucket> for bucket options for the template.
Merge the CF templates into one, make sure all the importing and other snippets are documented.
~~Strapi documentation - build and host~~
- Create single instance deployment + https (document)
- For https: use letsencrypt to generate ssl, configure the eb config to use this.
- Final git branch for each version of the app (load balanced https/http, single http/https).
- Terraform it all up (excluding single + https).
## RDS Cloudformation
Use <http://blog.blackninjadojo.com/aws/elastic-beanstalk/2019/01/28/adding-a-database-to-your-rails-application-on-elastic-beanstalk-using-rds.html> to create an RDS for ELB.
- RDS cloudformation template
- Use the GUI to go through options and create cloudformation template
- Create an RDS db before deployment
- Configure Strapi to use this RDS db
- VPC + Security Group needs creating in template
Compare the `--database option` to without and make sure you create everything in the Cloudformation template.
Look at how to have multiple environments in the same elb app
Deploy strapi as load balanced rather than single instance
Deploy strapi with a custom domain with HTTPS as a single instance + load balanced.
Combine ELB Documentations (strapi, ELB etc)
## Long term
Use codebuild to update strapi
Use circle CI instead
Finish the backgrounds for the demo website
Cloudformation template to deploy an S3 bucket
## Links
## Documentation
Decouple an exisitng RDS instance from ELB to RDS: <https://aws.amazon.com/premiumsupport/knowledge-center/decouple-rds-from-beanstalk/>
Summarise the flow -> VPC, internet gateway, attachment + route tables, subnets etc. Mention the nat gateway but show how it can be replaced with security groups. Document each individual resource needed bullet point and link to the git repo for the TF/CF templates.
Deploy the ELB environment referencing the VPC + Subnets created with Cloudformation. Use https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/vpc-rds.html as a reference.
## Running Notes
This works! Create all the VPC + Subnet resources using Cloudformation and specify them in option settings:
Various deployments:
```yaml
option_settings:
aws:ec2:vpc:
VPCId: "vpc-003597eb63a0a3efe"
Subnets: "subnet-02cd8f7981ddfe345,subnet-02d9e1338e8d92d09,subnet-0e07d4d35394db524"
DBSubnets: "subnet-02cd8f7981ddfe345,subnet-02d9e1338e8d92d09,subnet-0e07d4d35394db524"
```
- Single instance with EBCLI
- Load balanced with EBCLI
Recreate env with database, check the DB subnets - are they the same as the EC2 subnets? If so we can reference them in https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/command-options-general.html#command-options-general-ec2vpc with ELBSubnets
- Single instance with terraform
- Load balanced with terraform
Can we use cloudformation functions (imports) in .config files under option_settings? (reference a VPC that already exists?) (https://www.reddit.com/r/aws/comments/a2uoae/is_there_a_way_to_reference_an_elastic_beanstalk/) Yes?
Yes but only certain functions: <https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/ebextensions-functions.html#ebextensions-functions-getatt>. You cannot use FN::ImportValue to reference a resource in another Cloudformation stack.
HTTP + HTTPS
Use join for subnets Name: !Join [ ":", [ !Ref "AWS::StackName", AccountVPC ] ]
Single instance with terraform isn't possible with HTTPS - this is because you can't edit `Resources` or `Files` (and the other advanced EB configs). A workaround would be to create a docker image.
Updating 07 config to accept a parameter
Single instance with EBCLI isn't possible with HTTPS if you're using Certificate Manager to generate the certificates - this is because you need to edit the nginx proxy config locally on the instance to allow https. You don't have access to the private certificate with Cerficiate Manager.
One solution would be to generate your SSL using letsencrypt - then configure the instance with this.
For DB
Another solution would be to use Docker and build a custom image. In this image you could install and configure nginx, (using lets encrypt as multistage build to get your certificate).
Follow <https://github.com/garystafford/aws-rds-postgres/blob/master/cfn-templates/rds.template>
HTTPS for load balanced environment just requires pointing a domain to the EB endpoint. You can tell the load balancer to forward 443 in the security group without using it.
Create a subnet group (add each subnet to this group)
Create a security Group for DB
Create a SecurityGroupIngress
Use existing public VPC and subnet
For final deployment - use an EC2 instance (deploy with TF).
What is the RDS hostname inside the container?
### Other
Follow a naming convention for likewise cloudformation templates
Work:
Can we use APIGateway + Fargate to run an API containerised?
E.g.
Fargate documentation: <https://aws.amazon.com/fargate/>.
Fargate option in ECS terraform: <https://www.terraform.io/docs/providers/aws/r/ecs_service.html#launch_type>.
Lambda vs Fargate differences: <https://www.learnaws.org/2019/09/14/deep-dive-aws-fargate/>.
Fargate vs EC2 pricing: <https://www.reddit.com/r/aws/comments/8reem9/fargate_t2small_cost_comparison_dollar_to_dollar/>.
Reddit thread on using API Gateway + Fargate: <https://www.reddit.com/r/aws/comments/bgqz4g/can_api_gateway_route_to_a_container_in_fargate/>.
Using API Gateway + Private endpoints (in a VPC): <https://aws.amazon.com/blogs/compute/introducing-amazon-api-gateway-private-endpoints/>.
```yaml
Outputs:
PublicVPCID:
Description: The VPC ID.
Value: !Ref PublicVPC
Export:
Name: !Sub "${AWS::StackName}-ELBStrapiPublicVPC"
```
Fargate is just running containers serverless - but it isn't a direct replacement to lambda. The spin up times can be long, but if you need to run a task on a schedule and this doesn't matter, you can save money and time as you don't need to manage and run an EC2 instance for docker containers. It's not ideal for tasks that need to be running 24/7.
Defines a VPC. We can then pass in the stackname to another CF template and it can reference this VPC. The VPC names are static between projects (they don't have to be but here they are).
Have a seperate repos for Terraform + Ansible. Split them inside by project. One central place for all TF and Ansible will make things easier to reference from later.
Do we need a seperate security group for the database? - The answer should be that there is a seperate security group for RDS, and one for EC2. EC2 one should be created by ELB automatically. - This is true. The RDS one is created in CF.
Generate SSH keys for EC2.
Provision EC2 using TF - set SG to allow SSH from your IP.
Configure EC2 with an Ansible playbook.
Does the db and the ec2 instances share the same VPC? - Yes. They have different security groups.
## Single options
To Do
- Dockerise it + run on EC2/ECS/Fargate
- Use EBCLI + Config options for https. Generate SSL using lets encrypt.
Using certbot with docker: <https://certbot.eff.org/docs/install.html#running-with-docker>
To have a replica database you should create a new DB instance with same AllocatedStorage size and DBInstanceClass. You should set the SourceDBInstanceIdentifier to be a `!Ref` of your primary DB. You should also set the SourceRegion.
CF RDS ELB template:
https://github.com/garystafford/aws-rds-postgres/blob/master/cfn-templates/rds.template
Read replica CF docs:
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-database-instance.html#cfn-rds-dbinstance-sourcedbinstanceidentifier
Doc the CF changes for both
Combine them into a single CF stack
Deploy
Deploy strapi with LB + scaling
Enable HTTPS
Codebuild
Forcing http > https redirection: <https://github.com/awsdocs/elastic-beanstalk-samples/tree/master/configuration-files/aws-provided/security-configuration/https-redirect/nodejs>.