# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 AWSTemplateFormatVersion: "2010-09-09" Parameters: Ec2InstanceType: Description: Type of EC2 instance Type: String Default: m6g.8xlarge AllowedValues: - m6g.medium - m6g.large - m6g.xlarge - m6g.2xlarge - m6g.4xlarge - m6g.8xlarge - m6g.12xlarge - m6g.16xlarge Ec2KeyPair: Description: Name of SSH key pair (required) Type: String ConstraintDescription: "Must be the 'Name' of an SSH key pair from here https://console.aws.amazon.com/ec2/v2/home#KeyPairs:" AllowedPattern: ".+" Ec2VolumeSize: Description: Size of storage space in GB Type: String Default: 500 Resources: Ec2SecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Instance security group Ec2SecurityGroupSshIngress: Type: AWS::EC2::SecurityGroupIngress Properties: Description: Allow inbound SSH access GroupId: !GetAtt Ec2SecurityGroup.GroupId IpProtocol: tcp FromPort: 22 ToPort: 22 CidrIp: "0.0.0.0/0" Ec2SecurityGroupSelfIngress: Type: AWS::EC2::SecurityGroupIngress Properties: Description: Allow access in same security group GroupId: !GetAtt Ec2SecurityGroup.GroupId IpProtocol: -1 SourceSecurityGroupId: !GetAtt Ec2SecurityGroup.GroupId Ec2ServiceRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: ec2.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: !Sub ${AWS::StackName}-EC2-ServicePolicy PolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Action: "*" Resource: "*" Ec2InstanceProfile: Type: AWS::IAM::InstanceProfile Properties: Roles: - !Ref Ec2ServiceRole Ec2LaunchTemplate: Type: AWS::EC2::LaunchTemplate Properties: LaunchTemplateName: !Sub ${AWS::StackName}-EC2-LaunchTemplate LaunchTemplateData: ImageId: !FindInMap [AMIRegionMap, !Ref "AWS::Region", AMIID] KeyName: !Ref Ec2KeyPair InstanceType: !Ref Ec2InstanceType IamInstanceProfile: Name: !Ref Ec2InstanceProfile SecurityGroupIds: !Split [",", !GetAtt Ec2SecurityGroup.GroupId] TagSpecifications: - ResourceType: instance Tags: - Key: Name Value: !Sub ${AWS::StackName}-Ec2-Instance MetadataOptions: HttpEndpoint: "enabled" HttpTokens: "required" BlockDeviceMappings: - DeviceName: /dev/sda1 Ebs: VolumeSize: !Ref Ec2VolumeSize DeleteOnTermination: true Encrypted: true UserData: Fn::Base64: !Sub | #!/bin/bash set -euo pipefail # Wait for any existing package install to finish i=0 while true; do if sudo fuser /var/{lib/{dpkg,apt/lists},cache/apt/archives}/lock >/dev/null 2>&1; then i=0 else i=`expr $i + 1` if expr $i \>= 10 > /dev/null; then break fi fi sleep 1 done # Upgrade system and reboot if required apt update && apt upgrade -y if [ -f /var/run/reboot-required ]; then # Delete the UserData info file so that we run again after reboot rm -f /var/lib/cloud/instances/*/sem/config_scripts_user reboot exit fi # Install helper scripts: apt update && apt install -y python3-setuptools mkdir -p /opt/aws/bin wget https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-py3-latest.tar.gz python3 -m easy_install --script-dir /opt/aws/bin aws-cfn-bootstrap-py3-latest.tar.gz rm aws-cfn-bootstrap-py3-latest.tar.gz # On error, signal back to cfn: error_handler() { /opt/aws/bin/cfn-signal --success false --stack ${AWS::StackName} --resource Ec2Instance --region ${AWS::Region} } trap error_handler ERR # Install packages apt update && apt install -y ec2-instance-connect htop jq unzip zip # Install AWS CLI: curl "https://awscli.amazonaws.com/awscli-exe-linux-aarch64.zip" -o "awscliv2.zip" unzip -q awscliv2.zip ./aws/install rm awscliv2.zip # Signal init complete: /opt/aws/bin/cfn-signal --stack ${AWS::StackName} --resource Ec2Instance --region ${AWS::Region} Ec2Instance: Type: AWS::EC2::Instance CreationPolicy: ResourceSignal: Count: 1 Timeout: PT15M Properties: LaunchTemplate: LaunchTemplateId: !Ref Ec2LaunchTemplate Version: !GetAtt Ec2LaunchTemplate.LatestVersionNumber Mappings: # Ubuntu 20.04 arm64 AMIs AMIRegionMap: ap-northeast-1: AMIID: ami-0836b08b6e50975e0 ap-northeast-2: AMIID: ami-09a9b3cefb0428387 ap-northeast-3: AMIID: ami-0e48a9cf92bd86508 ap-south-1: AMIID: ami-0a20a058ee035d49c ap-southeast-1: AMIID: ami-04a46a6d4dbeb5fe0 ap-southeast-2: AMIID: ami-0c9be6cb7d01a9066 ca-central-1: AMIID: ami-0c4c276bcaf3911b1 eu-central-1: AMIID: ami-048c3444604e23b5c eu-north-1: AMIID: ami-04a8d27b5fe65dd51 eu-west-1: AMIID: ami-0ea366b1f105cb0aa eu-west-2: AMIID: ami-06b427ade4da0da55 eu-west-3: AMIID: ami-06cc80fe7e768f974 sa-east-1: AMIID: ami-081f3905bf0562cdd us-east-1: AMIID: ami-0620aa8714211d0af us-east-2: AMIID: ami-0bc02c3c09aaee8ea us-west-1: AMIID: ami-038e08160883bc1f9 us-west-2: AMIID: ami-0c4dfe348469b0ae5 Outputs: Ec2InstanceId: Description: "EC2 instance ID" Value: !Ref Ec2Instance Ec2InstancePublicIp: Description: "EC2 instance public IP address" Value: !GetAtt Ec2Instance.PublicIp