Skip to content

Instantly share code, notes, and snippets.

@tatat
Last active October 25, 2017 13:10
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save tatat/8dec56a264f5cc9b39796642399c0eff to your computer and use it in GitHub Desktop.
cfn
AWSTemplateFormatVersion: 2010-09-09
Description: VPC + EB + RDS (MySQL) + Rails (Puma)
Parameters:
KeyName:
Description: Name of an existing EC2 KeyPair to enable SSH access to the bastion host and Elastic Beanstalk hosts
Type: AWS::EC2::KeyPair::KeyName
SSHLocation:
Description: Lockdown SSH access to the bastion host (default can be accessed from anywhere)
Type: String
Default: 0.0.0.0/0
BastionInstanceType:
Description: Bastion Host EC2 instance type
Type: String
Default: t2.micro
BastionImageId:
Description: Bastion Host AMI ID
Type: String
Default: ami-6b96400d
NATInstanceType:
Description: NAT Device EC2 instance type
Type: String
Default: t2.micro
NATImageId:
Description: NAT Device AMI ID
Type: String
Default: ami-17944271
RootVolumeSize:
Description: Root Volume Size
Type: Number
Default: 32
DBName:
Description: Database Name
Type: String
Default: application
DBUser:
NoEcho: true
Description: The database admin account username
Type: String
Default: application
MinLength: 1
MaxLength: 16
AllowedPattern: "[a-zA-Z][a-zA-Z0-9]*"
ConstraintDescription: must begin with a letter and contain only alphanumeric characters.
DBPassword:
NoEcho: true
Description: The database admin account password
Type: String
Default: application
MinLength: 1
MaxLength: 41
AllowedPattern: "[a-zA-Z0-9]+"
ConstraintDescription: must contain only alphanumeric characters.
DB1llocatedStorage:
Description: The size of the database (Gb)
Type: Number
Default: 5
MinValue: 5
MaxValue: 1024
ConstraintDescription: must be between 5 and 1024Gb.
DBInstanceClass:
Description: The database instance type
Type: String
Default: db.t2.micro
DBMultiAZ:
Description: Multi-AZ master database
Type: String
Default: "false"
AllowedValues:
- "true"
- "false"
ConstraintDescription: must be true or false.
DBAutoMinorVersionUpgrade:
Description: Apply minor engine upgrades automatically
Type: String
Default: "true"
AllowedValues:
- "true"
- "false"
ConstraintDescription: must be true or false.
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
Tags:
- Key: Application
Value: !Ref AWS::StackId
- Key: Network
Value: Public
PublicSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: ap-northeast-1a
CidrBlock: 10.0.0.0/24
Tags:
- Key: Application
Value: !Ref AWS::StackId
- Key: Network
Value: Public
PublicSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: ap-northeast-1c
CidrBlock: 10.0.1.0/24
Tags:
- Key: Application
Value: !Ref AWS::StackId
- Key: Network
Value: Public
InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Application
Value: !Ref AWS::StackId
- Key: Network
Value: Public
GatewayToInternet:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref InternetGateway
PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Application
Value: !Ref AWS::StackId
- Key: Network
Value: Public
PublicRoute:
Type: AWS::EC2::Route
DependsOn: GatewayToInternet
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
PublicSubnet1RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet1
RouteTableId: !Ref PublicRouteTable
PublicSubnet2RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet2
RouteTableId: !Ref PublicRouteTable
PublicNetworkAcl:
Type: AWS::EC2::NetworkAcl
Properties:
VpcId: !Ref VPC
Tags:
- Key: Application
Value: !Ref AWS::StackId
- Key: Network
Value: Public
InboundHTTPPublicNetworkAclEntry:
Type: AWS::EC2::NetworkAclEntry
Properties:
NetworkAclId: !Ref PublicNetworkAcl
RuleNumber: 100
Protocol: 6
RuleAction: allow
Egress: false
CidrBlock: 0.0.0.0/0
PortRange:
From: 80
To: 80
InboundHTTPSPublicNetworkAclEntry:
Type: AWS::EC2::NetworkAclEntry
Properties:
NetworkAclId: !Ref PublicNetworkAcl
RuleNumber: 101
Protocol: 6
RuleAction: allow
Egress: false
CidrBlock: 0.0.0.0/0
PortRange:
From: 443
To: 443
InboundSSHPublicNetworkAclEntry:
Type: AWS::EC2::NetworkAclEntry
Properties:
NetworkAclId: !Ref PublicNetworkAcl
RuleNumber: 102
Protocol: 6
RuleAction: allow
Egress: false
CidrBlock: !Ref SSHLocation
PortRange:
From: 22
To: 22
InboundNTPPublicNetworkAclEntry:
Type: AWS::EC2::NetworkAclEntry
Properties:
NetworkAclId: !Ref PublicNetworkAcl
RuleNumber: 103
Protocol: 17
RuleAction: allow
Egress: false
CidrBlock: 0.0.0.0/0
PortRange:
From: 123
To: 123
InboundEphemeralPublicNetworkAclEntry:
Type: AWS::EC2::NetworkAclEntry
Properties:
NetworkAclId: !Ref PublicNetworkAcl
RuleNumber: 104
Protocol: 6
RuleAction: allow
Egress: false
CidrBlock: 0.0.0.0/0
PortRange:
From: 1024
To: 65535
OutboundPublicNetworkAclEntry:
Type: AWS::EC2::NetworkAclEntry
Properties:
NetworkAclId: !Ref PublicNetworkAcl
RuleNumber: 100
Protocol: -1
RuleAction: allow
Egress: true
CidrBlock: 0.0.0.0/0
PublicSubnet1NetworkAclAssociation:
Type: AWS::EC2::SubnetNetworkAclAssociation
Properties:
SubnetId: !Ref PublicSubnet1
NetworkAclId: !Ref PublicNetworkAcl
PublicSubnet2NetworkAclAssociation:
Type: AWS::EC2::SubnetNetworkAclAssociation
Properties:
SubnetId: !Ref PublicSubnet2
NetworkAclId: !Ref PublicNetworkAcl
PrivateSubnetApp1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: ap-northeast-1a
CidrBlock: 10.0.10.0/24
Tags:
- Key: Application
Value: !Ref AWS::StackId
- Key: Network
Value: Private
PrivateSubnetApp2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: ap-northeast-1c
CidrBlock: 10.0.11.0/24
Tags:
- Key: Application
Value: !Ref AWS::StackId
- Key: Network
Value: Private
PrivateSubnetDB1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: ap-northeast-1a
CidrBlock: 10.0.100.0/24
Tags:
- Key: Application
Value: !Ref AWS::StackId
- Key: Network
Value: Private
PrivateSubnetDB2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: ap-northeast-1c
CidrBlock: 10.0.101.0/24
Tags:
- Key: Application
Value: !Ref AWS::StackId
- Key: Network
Value: Private
DBSubnetGroup:
Type: AWS::RDS::DBSubnetGroup
Properties:
DBSubnetGroupDescription: DB subnet group
SubnetIds:
- !Ref PrivateSubnetDB1
- !Ref PrivateSubnetDB2
Tags:
- Key: Application
Value: !Ref AWS::StackId
- Key: Network
Value: Private
PrivateRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Application
Value: !Ref AWS::StackId
- Key: Network
Value: Private
PrivateSubnetRouteTableAssociationApp1:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnetApp1
RouteTableId: !Ref PrivateRouteTable
PrivateSubnetRouteTableAssociationApp2:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnetApp2
RouteTableId: !Ref PrivateRouteTable
PrivateSubnetRouteTableAssociationDB1:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnetDB1
RouteTableId: !Ref PrivateRouteTable
PrivateSubnetRouteTableAssociationDB2:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnetDB2
RouteTableId: !Ref PrivateRouteTable
PrivateRoute:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref PrivateRouteTable
DestinationCidrBlock: 0.0.0.0/0
InstanceId: !Ref NATDevice
PrivateNetworkAcl:
Type: AWS::EC2::NetworkAcl
Properties:
VpcId: !Ref VPC
Tags:
- Key: Application
Value: !Ref AWS::StackId
- Key: Network
Value: Private
InboundPrivateNetworkAclEntry:
Type: AWS::EC2::NetworkAclEntry
Properties:
NetworkAclId: !Ref PrivateNetworkAcl
RuleNumber: 100
Protocol: -1
RuleAction: allow
Egress: false
CidrBlock: 0.0.0.0/0
OutboundPrivateNetworkAclEntry:
Type: AWS::EC2::NetworkAclEntry
Properties:
NetworkAclId: !Ref PrivateNetworkAcl
RuleNumber: 100
Protocol: -1
RuleAction: allow
Egress: true
CidrBlock: 0.0.0.0/0
PrivateSubnetNetworkAclAssociationApp1:
Type: AWS::EC2::SubnetNetworkAclAssociation
Properties:
SubnetId: !Ref PrivateSubnetApp1
NetworkAclId: !Ref PrivateNetworkAcl
PrivateSubnetNetworkAclAssociationApp2:
Type: AWS::EC2::SubnetNetworkAclAssociation
Properties:
SubnetId: !Ref PrivateSubnetApp2
NetworkAclId: !Ref PrivateNetworkAcl
PrivateSubnetNetworkAclAssociationDB1:
Type: AWS::EC2::SubnetNetworkAclAssociation
Properties:
SubnetId: !Ref PrivateSubnetDB1
NetworkAclId: !Ref PrivateNetworkAcl
PrivateSubnetNetworkAclAssociationDB2:
Type: AWS::EC2::SubnetNetworkAclAssociation
Properties:
SubnetId: !Ref PrivateSubnetDB2
NetworkAclId: !Ref PrivateNetworkAcl
NATIPAddress:
Type: AWS::EC2::EIP
DependsOn: GatewayToInternet
Properties:
Domain: vpc
InstanceId: !Ref NATDevice
NATDevice:
Type: AWS::EC2::Instance
Properties:
InstanceType: !Ref NATInstanceType
SubnetId: !Ref PublicSubnet1
SourceDestCheck: false
ImageId: !Ref NATImageId
SecurityGroupIds:
- !Ref NATSecurityGroup
Tags:
- Key: Application
Value: !Ref AWS::StackId
NATSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Enable internal access to the NAT device
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: -1
FromPort: 0
ToPort: 65535
CidrIp: 10.0.0.0/16
SecurityGroupEgress:
- IpProtocol: -1
FromPort: 0
ToPort: 65535
CidrIp: 0.0.0.0/0
BastionIPAddress:
Type: AWS::EC2::EIP
DependsOn: GatewayToInternet
Properties:
Domain: vpc
InstanceId: !Ref Bastion
Bastion:
Type: AWS::EC2::Instance
Properties:
InstanceType: !Ref BastionInstanceType
KeyName: !Ref KeyName
SubnetId: !Ref PublicSubnet1
ImageId: !Ref BastionImageId
SecurityGroupIds:
- !Ref BastionSecurityGroup
Tags:
- Key: Application
Value: !Ref AWS::StackId
BastionSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Enable access to the Bastion host
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: !Ref SSHLocation
SecurityGroupEgress:
- IpProtocol: -1
FromPort: 0
ToPort: 65535
CidrIp: 0.0.0.0/0
BeanstalkSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allow the Elastic Beanstalk instances to access the NAT device
VpcId: !Ref VPC
WebServerPolicy:
Type: AWS::IAM::ManagedPolicy
Properties:
Description: Web server policy
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
NotAction: iam:*
Resource: "*"
WebServerRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service: ec2.amazonaws.com
Action:
- sts:AssumeRole
ManagedPolicyArns:
- !Ref WebServerPolicy
WebServerInstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
Path: /
Roles:
- !Ref WebServerRole
Application:
Type: AWS::ElasticBeanstalk::Application
Properties:
Description: AWS Elastic Beanstalk Application
ApplicationEnvironment:
Type: AWS::ElasticBeanstalk::Environment
Properties:
ApplicationName: !Ref Application
Description: AWS Elastic Beanstalk Environment running Application
SolutionStackName: 64bit Amazon Linux 2017.09 v2.6.0 running Ruby 2.4 (Puma)
Tags:
- Key: Application
Value: !Ref AWS::StackId
OptionSettings:
- Namespace: aws:elasticbeanstalk:application
OptionName: Application Healthcheck URL
Value: /
- Namespace: aws:elasticbeanstalk:application:environment
OptionName: SECRET_KEY_BASE
Value: UPDATE ME
- Namespace: aws:elasticbeanstalk:application:environment
OptionName: DATABASE_USERNAME
Value: !Ref DBUser
- Namespace: aws:elasticbeanstalk:application:environment
OptionName: DATABASE_PASSWORD
Value: !Ref DBPassword
- Namespace: aws:elasticbeanstalk:application:environment
OptionName: DATABASE_HOST
Value: !GetAtt ["Database", "Endpoint.Address"]
- Namespace: aws:elasticbeanstalk:command
OptionName: DeploymentPolicy
Value: RollingWithAdditionalBatch
- Namespace: aws:elasticbeanstalk:environment
OptionName: EnvironmentType
Value: LoadBalanced
- Namespace: aws:autoscaling:asg
OptionName: MinSize
Value: 2
- Namespace: aws:autoscaling:asg
OptionName: MaxSize
Value: 4
- Namespace: aws:autoscaling:launchconfiguration
OptionName: SSHSourceRestriction
Value: !Sub tcp, 22, 22, ${BastionSecurityGroup}
- Namespace: aws:autoscaling:launchconfiguration
OptionName: SecurityGroups
Value: !Ref BeanstalkSecurityGroup
- Namespace: aws:autoscaling:launchconfiguration
OptionName: EC2KeyName
Value: !Ref KeyName
- Namespace: aws:autoscaling:launchconfiguration
OptionName: IamInstanceProfile
Value: !Ref WebServerInstanceProfile
- Namespace: aws:autoscaling:launchconfiguration
OptionName: RootVolumeSize
Value: !Ref RootVolumeSize
- Namespace: aws:autoscaling:updatepolicy:rollingupdate
OptionName: RollingUpdateEnabled
Value: true
- Namespace: aws:autoscaling:updatepolicy:rollingupdate
OptionName: RollingUpdateType
Value: Health
- Namespace: aws:ec2:vpc
OptionName: VPCId
Value: !Ref VPC
- Namespace: aws:ec2:vpc
OptionName: Subnets
Value: !Sub ${PrivateSubnetApp1}, ${PrivateSubnetApp2}
- Namespace: aws:ec2:vpc
OptionName: ELBSubnets
Value: !Sub ${PublicSubnet1}, ${PublicSubnet2}
DBSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: DB security group
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 3306
ToPort: 3306
SourceSecurityGroupId: !Ref BeanstalkSecurityGroup
SecurityGroupEgress:
- IpProtocol: -1
FromPort: 0
ToPort: 65535
CidrIp: 0.0.0.0/0
DBParameterGroup:
Type: AWS::RDS::DBParameterGroup
Properties:
Family: MySQL5.7
Description: Database Parameter Group
Parameters:
character_set_client: utf8mb4
character_set_connection: utf8mb4
character_set_database: utf8mb4
character_set_results: utf8mb4
character_set_server: utf8mb4
collation_connection: utf8mb4_bin
collation_server: utf8mb4_bin
Tags:
- Key: Application
Value: !Ref AWS::StackId
DBOptionGroup:
Type: AWS::RDS::OptionGroup
DeletionPolicy: Retain
Properties:
EngineName: mysql
MajorEngineVersion: "5.7"
OptionGroupDescription: Database Option Group
OptionConfigurations: []
Tags:
- Key: Application
Value: !Ref AWS::StackId
Database:
Type: AWS::RDS::DBInstance
DeletionPolicy: Snapshot
Properties:
DBName: !Ref DBName
AllocatedStorage: !Ref DB1llocatedStorage
DBInstanceClass: !Ref DBInstanceClass
Engine: MySQL
EngineVersion: "5.7"
MasterUsername: !Ref DBUser
MasterUserPassword: !Ref DBPassword
MultiAZ: !Ref DBMultiAZ
AutoMinorVersionUpgrade: !Ref DBAutoMinorVersionUpgrade
DBParameterGroupName: !Ref DBParameterGroup
DBSubnetGroupName: !Ref DBSubnetGroup
OptionGroupName: !Ref DBOptionGroup
VPCSecurityGroups:
- !Ref DBSecurityGroup
Tags:
- Key: Application
Value: !Ref AWS::StackId
Outputs:
Bastion:
Description: IP Address of the Bastion host
Value: !Ref BastionIPAddress
URL:
Description: The URL of the Elastic Beanstalk environment
Value: !Sub ["http://${Endpoint}", { Endpoint: { "Fn::GetAtt": ["ApplicationEnvironment", "EndpointURL"] }}]
DBEndpoint:
Description: Database endpoint
Value: !Sub ["${Address}:${Port}", { Address: { "Fn::GetAtt": ["Database", "Endpoint.Address"] }, Port: { "Fn::GetAtt": ["Database", "Endpoint.Port"] }}]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment