genericsuite-be-scripts
Version:
GenericSuite Scripts (backend version)
404 lines (369 loc) • 14.2 kB
YAML
AWSTemplateFormatVersion: '2010-09-09'
Description: CloudFormation template to deploy FastAPI app with EC2 and ECR, including all necessary resources (VPC, Subnets, Launch Configuration).
Parameters:
KeyName:
Description: Name for the EC2 KeyPair to enable SSH access to the instance
Type: AWS::EC2::KeyPair::KeyName
EcrRepositoryName:
Description: ECR docker images repository name
Type: String
EcrDockerImageUri:
Description: Complete URI of the ECR repository Docker image
Type: String
EcrDockerImageTag:
Description: ECR repository Docker image tag
Type: String
Default: latest
AppName:
Description: application name
Type: String
AppStage:
Description: application stage (qa, prod, staging, demo, dev)
Type: String
AwsRegion:
Description: application region
Type: String
KmsKeyAlias:
Type: String
Description: The alias of the KMS key to use for EBS encryption
S3BucketName1:
Description: App S3 Bucket name
Type: String
AsmSecretsName:
Description: Secrets Manager - Secrets set name
Type: String
AsmEnvsName:
Description: Secrets Manager - Environment variables set name
Type: String
AwsAccountId:
Description: AWS account Id
Type: String
DomainName:
Description: Domain name for the ALB
Type: String
HostedZoneId:
Description: The ID of the hosted zone where the domain is managed
Type: AWS::Route53::HostedZone::Id
DomainStackName:
Description: Name of the stack that created the domain resources
Type: String
DefaultSecurityGroupId:
Description: localstack default security group id
Type: String
Resources:
# VPC:
# Type: AWS::EC2::VPC
# Properties:
# CidrBlock: 10.0.0.0/16
# EnableDnsHostnames: true
# EnableDnsSupport: true
# InstanceTenancy: default
# Tags:
# - Key: Name
# Value: !Sub ${AppName}-${AppStage}-vpc
# - Key: App
# Value: !Ref AppName
# - Key: Stage
# Value: !Ref AppStage
# Subnet1:
# Type: AWS::EC2::Subnet
# Properties:
# VpcId: !Ref VPC
# AvailabilityZone: !Select
# - 0
# - !GetAZs ''
# CidrBlock: 10.0.1.0/24
# MapPublicIpOnLaunch: true
# Tags:
# - Key: Name
# Value: !Sub ${AppName}-${AppStage}-subnet-1
# - Key: App
# Value: !Ref AppName
# - Key: Stage
# Value: !Ref AppStage
# InstanceSecurityGroup:
# Type: AWS::EC2::SecurityGroup
# Properties:
# GroupName: !Sub ${AppName}-${AppStage}-sg-ec2
# GroupDescription: Enable SSH and HTTP access
# VpcId: !Ref VPC
# # IpPermissions:
# # - FromPort: 80,
# # IpProtocol: tcp
# # IpRanges:
# # - CidrIp: 0.0.0.0/0
# # ToPort: 80,
# # - FromPort: 22,
# # IpProtocol: tcp
# # IpRanges:
# # - CidrIp: 0.0.0.0/0
# # ToPort: 22,
# SecurityGroupIngress:
# - IpProtocol: tcp
# FromPort: 80
# ToPort: 80
# # SourceSecurityGroupId: !Ref LoadBalancerSecurityGroup
# - IpProtocol: tcp
# FromPort: 22
# ToPort: 22
# CidrIp: 0.0.0.0/0 # Consider restricting this to your IP range
# Tags:
# - Key: App
# Value: !Ref AppName
# - Key: Stage
# Value: !Ref AppStage
# Ec2InstanceRole:
# Type: AWS::IAM::Role
# Properties:
# RoleName: !Sub ${AppName}-${AppStage}-ec2-instance-role
# AssumeRolePolicyDocument:
# Version: '2012-10-17'
# Statement:
# - Effect: Allow
# Principal:
# Service:
# - ec2.amazonaws.com
# Action:
# - sts:AssumeRole
# Path: /
# ManagedPolicyArns:
# # - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
# - arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy
# # Bingo! this enabled SSM
# # - arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM
# Policies:
# - PolicyName: Ec2InstancePolicy
# PolicyDocument:
# Version: '2012-10-17'
# Statement:
# - Effect: Allow
# Action:
# - ec2:Describe*
# Resource: '*'
# - PolicyName: Ec2S3AccessPolicy1
# PolicyDocument:
# Version: '2012-10-17'
# Statement:
# - Effect: Allow
# Action:
# - s3:PutObject
# - s3:PutObjectAcl
# - s3:GetObject
# - s3:GetObjectAcl
# - s3:DeleteObject
# # Resource: arn:aws:s3:::AWS_S3_CHATBOT_ATTACHMENTS_BUCKET_placeholder/*
# # Resource: !Sub arn:aws:s3:::${S3BucketName1}/*
# Resource: '*'
# - PolicyName: Ec2LogsPolicy
# PolicyDocument:
# Version: '2012-10-17'
# Statement:
# - Effect: Allow
# Action:
# - logs:CreateLogGroup
# - logs:CreateLogStream
# - logs:PutLogEvents
# Resource: arn:*:logs:*:*:*
# - PolicyName: Ec2EcrLoginPolicy
# PolicyDocument:
# Version: '2012-10-17'
# Statement:
# - Effect: Allow
# Action:
# - ecr:GetAuthorizationToken
# Resource: '*'
# - PolicyName: Ec2EcrAccessPolicy
# PolicyDocument:
# Version: '2012-10-17'
# Statement:
# - Effect: Allow
# Action:
# - ecr:BatchCheckLayerAvailability
# - ecr:BatchGetImage
# - ecr:GetDownloadUrlForLayer
# Resource:
# # - !Sub arn:aws:ecr:${AwsRegion}:${AwsAccountId}:repository/AWS_ECR_REPOSITORY_NAME_placeholder
# - !Sub arn:aws:ecr:${AwsRegion}:${AwsAccountId}:repository/${EcrRepositoryName}
# - PolicyName: Ec2SecretsAccessPolicy
# PolicyDocument:
# Version: '2012-10-17'
# Statement:
# - Effect: Allow
# Action:
# - secretsmanager:GetSecretValue
# Resource: '*'
# # Resource:
# # # - arn:aws:secretsmanager:*:*:secret:AWS_SECRETS_MANAGER_SECRETS_NAME_placeholder
# # - !Sub arn:aws:secretsmanager:*:*:secret:${AsmSecretsName}
# # # - arn:aws:secretsmanager:*:*:secret:AWS_SECRETS_MANAGER_ENVS_NAME_placeholder
# # - !Sub arn:aws:secretsmanager:*:*:secret:${AsmEnvsName}
# - PolicyName: Ec2KmsAccessPolicy
# PolicyDocument:
# Version: '2012-10-17'
# Statement:
# - Effect: Allow
# Action:
# - kms:Decrypt
# - kms:GenerateDataKey*
# - kms:CreateGrant
# # Resource: !Sub 'arn:aws:kms:${AWS::Region}:${AWS::AccountId}:key/*'
# Resource: '*'
# # Resource: !Sub 'arn:aws:kms:${AWS::Region}:${AWS::AccountId}:alias/${KmsKeyAlias}'
# # Resource: '*'
# # Resource:
# # # - arn:aws:kms:AWS_REGION_placeholder:AWS_ACCOUNT_ID_placeholder:alias/AWS_KMS_KEY_ALIAS_placeholder
# # - !Sub arn:aws:kms:${AwsRegion}:${AwsAccountId}:alias/${KmsKeyAlias}
# - PolicyName: Ec2CloudWatchLogsPolicy
# PolicyDocument:
# Version: '2012-10-17'
# Statement:
# - Effect: Allow
# Action:
# - logs:CreateLogGroup
# - logs:CreateLogStream
# - logs:PutLogEvents
# - logs:DescribeLogStreams
# Resource:
# - !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:${AppName}-${AppStage}-ec2-logs:*
# Ec2InstanceProfile:
# Type: AWS::IAM::InstanceProfile
# Properties:
# InstanceProfileName: !Sub ${AppName}-${AppStage}-ec2-instance-profile
# Path: /
# Roles:
# - !Ref Ec2InstanceRole
AppLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub ${AppName}-${AppStage}-ec2-logs
RetentionInDays: 3 # Adjust as needed
EC2Instance:
Type: AWS::EC2::Instance
Properties:
# ImageId: ami-0c55b159cbfafe1f0
ImageId: ami-0195204d5dce06d99 # Amazon Linux 2 AMI / 64-bit (x86)
# ImageId: ami-003d53c9bb0a387f4 # Amazon Linux 2 AMI / 64-bit (Arm)
InstanceType: t2.micro
KeyName: !Ref KeyName
Count: 1
SecurityGroups:
- !Sub ${DefaultSecurityGroupId}
# - !Ref InstanceSecurityGroup
# # SubnetId: !Ref SubnetId
# SubnetId: !Ref Subnet1
# https://aws.amazon.com/blogs/security/get-the-full-benefits-of-imdsv2-and-disable-imdsv1-across-your-aws-infrastructure/
# Enable imdsv2 : --metadata-options “HttpEndpoint=enabled,HttpTokens=required”
# MetadataOptions:
# HttpTokens: required
# HttpEndpoint: enabled
BlockDeviceMappings:
- DeviceName: /dev/xvda
Ebs:
VolumeSize: 50
DeleteOnTermination: true
VolumeType: gp2
# Encrypted: true
# KmsKeyId: !Sub 'arn:aws:kms:${AWS::Region}:${AWS::AccountId}:alias/${KmsKeyAlias}'
# IamInstanceProfile:
# Name: !Ref Ec2InstanceProfile
TagSpecifications:
- ResourceType: instance
Tags:
- Key: Name
Value: !Sub ${AppName}-${AppStage}-instance
- Key: App
Value: !Ref AppName
- Key: Stage
Value: !Ref AppStage
- ResourceType: volume
Tags:
- Key: Name
Value: !Sub ${AppName}-${AppStage}-root-volume
- Key: App
Value: !Ref AppName
- Key: Stage
Value: !Ref AppStage
UserData:
Fn::Base64:
!Sub |
#!/bin/bash
exec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1
echo "Starting GS instance boot sequence..."
echo ">>--> `date` | Run | yum update -y"
yum update -y
echo ">>--> `date` | Run | yum install aws-cli jq amazon-ssm-agent amazon-cloudwatch-agent -y"
yum install aws-cli jq amazon-ssm-agent amazon-cloudwatch-agent -y
echo ">>--> `date` | Run | Create CloudWatch agent configuration file"
cat <<EOF > /opt/aws/amazon-cloudwatch-agent/bin/config.json
{
"agent": {
"metrics_collection_interval": 60,
"run_as_user": "root"
},
"logs": {
"logs_collected": {
"files": {
"collect_list": [
{
"file_path": "/var/log/user-data.log",
"log_group_name": "${AppName}-${AppStage}-ec2-logs",
"log_stream_name": "{instance_id}-user-data-logs"
},
{
"file_path": "/var/log/docker",
"log_group_name": "${AppName}-${AppStage}-ec2-logs",
"log_stream_name": "{instance_id}-docker-logs"
}
]
}
}
},
"metrics": {
"metrics_collected": {
"disk": {
"measurement": [
"used_percent"
],
"metrics_collection_interval": 60,
"resources": [
"/"
]
},
"mem": {
"measurement": [
"mem_used_percent"
],
"metrics_collection_interval": 60
}
}
}
}
EOF
/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -s -c file:/opt/aws/amazon-cloudwatch-agent/bin/config.json
echo ">>--> `date` | Run | amazon-linux-extras install docker -y"
amazon-linux-extras install docker -y
echo ">>--> `date` | Run | service amazon-ssm-agent start"
# systemctl start amazon-ssm-agent
echo ">>--> `date` | Run | service docker start"
systemctl start docker
systemctl enable docker
echo ">>--> `date` | Run | aws ecr get-login-password --region ${AWS::Region} | docker login --username AWS --password-stdin ${AwsAccountId}.dkr.ecr.${AWS::Region}.amazonaws.com"
aws ecr get-login-password --region ${AWS::Region} | docker login --username AWS --password-stdin ${AwsAccountId}.dkr.ecr.${AWS::Region}.amazonaws.com
echo ">>--> `date` | Run | docker pull ${EcrDockerImageUri}:${EcrDockerImageTag}"
docker pull ${EcrDockerImageUri}:${EcrDockerImageTag} > /dev/null 2>&1
echo ">>--> `date` | Run | docker run -d -p 80:80 --name gs_app_be -e CLOUD_PROVIDER=aws -e APP_NAME=${AppName} -e APP_STAGE=${AppStage} -e AWS_REGION=${AWS::Region} ${EcrDockerImageUri}:${EcrDockerImageTag}"
docker run -d -p 80:80 --name gs_app_be -e CLOUD_PROVIDER=aws -e APP_NAME=${AppName} -e APP_STAGE=${AppStage} -e AWS_REGION=${AWS::Region} ${EcrDockerImageUri}:${EcrDockerImageTag}
echo ">>--> `date` | Run | docker ps"
if [ "$(docker ps -q -f name=gs_app_be)" ]; then
echo "Container is running successfully."
else
echo "Container failed to start. Check docker logs."
docker logs gs_app_be
fi
echo ">>--> `date` | GS instance boot sequence finished"
Outputs:
InstancePublicIP:
Description: Public IP of our EC2 instance
Value: !GetAtt
- EC2Instance
- PublicIp