How to Create an AWS EC2 Instance in CloudFormation

Create an EC2 Instance in CloudFormation

If you need to create an EC2 instance in CloudFormation, then you can do the following:

AWSTemplateFormatVersion: "2010-09-09"
Resources:
  WebInstance:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: t2.nano
      ImageId: ami-80861296
      KeyName: my-key
      SecurityGroupIds:
        - sg-abc01234
      SubnetId: subnet-abc01234

You can set the Instance Name as follows:

AWSTemplateFormatVersion: "2010-09-09"
Resources:
  WebInstance:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: t2.nano
      ImageId: ami-80861296
      KeyName: my-key
      SecurityGroupIds:
        - sg-abc01234
      SubnetId: subnet-abc01234
      Tags:
        -
          Key: Name
          Value: webserver

You can Enable Monitoring as follows:

AWSTemplateFormatVersion: "2010-09-09"
Resources:
  WebInstance:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: t2.nano
      ImageId: ami-80861296
      KeyName: my-key
      Monitoring: true
      SecurityGroupIds:
        - sg-abc01234
      SubnetId: subnet-abc01234
      Tags:
        -
          Key: Name
          Value: webserver

You can add Termination Protection as follows:

AWSTemplateFormatVersion: "2010-09-09"
Resources:
  WebInstance:
    Type: AWS::EC2::Instance
    Properties:
      DisableApiTermination: true
      InstanceType: t2.nano
      ImageId: ami-80861296
      KeyName: my-key
      Monitoring: true
      SecurityGroupIds:
        - sg-abc01234
      SubnetId: subnet-abc01234
      Tags:
        -
          Key: Name
          Value: webserver

How to Increase the Root Volume Size

You can Increase the Root Volume Size as follows:

AWSTemplateFormatVersion: "2010-09-09"
Resources:
  WebInstance:
    Type: AWS::EC2::Instance
    Properties:
      BlockDeviceMappings:
        -
          DeviceName: "/dev/sda1"
          Ebs:
            VolumeSize: 24
            VolumeType: gp2
      InstanceType: t2.nano
      ImageId: ami-80861296
      KeyName: my-key
      SecurityGroupIds:
        - sg-abc01234
      SubnetId: subnet-abc01234

Storage in CloudFormation EC2 Instances

You can Add Additional Instance Storage as follows:

AWSTemplateFormatVersion: "2010-09-09"
Resources:
  WebInstance:
    Type: AWS::EC2::Instance
    Properties:
      BlockDeviceMappings:
        -
          DeviceName: "/dev/sda1"
          Ebs:
            VolumeSize: 24
            VolumeType: gp2
        -
          DeviceName: "/dev/sdf"
          Ebs:
            VolumeSize: 64
            VolumeType: gp2
      InstanceType: t2.nano
      ImageId: ami-80861296
      KeyName: my-key
      SecurityGroupIds:
        - sg-abc01234
      SubnetId: subnet-abc01234

You can Attach an Instance Volume as follows:

AWSTemplateFormatVersion: "2010-09-09"
Resources:
  WebInstance:
    Type: AWS::EC2::Instance
    Properties:      
      InstanceType: t2.nano
      ImageId: ami-80861296
      KeyName: my-key
      SecurityGroupIds:
        - sg-abc01234
      SubnetId: subnet-abc01234
      Volumes:
        -
          Device: "/dev/sdf"
          VolumeId: !Ref LogVolume

  LogVolume:
    Type: AWS::EC2::Volume
    DeletionPolicy: Snapshot
    Properties:
      AvailabilityZone: us-east-1a
      Size: 24
      Tags:
        -
          Key: Name
          Value: web-log-volume
      VolumeType: gp2

Security Groups in EC2 Instances with CloudFormation

You can Setup a Security Group as follows:

AWSTemplateFormatVersion: "2010-09-09"
Resources:
  WebSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Web server
      GroupName: web     
      VpcId: vpc-abc01234

Another example:

AWSTemplateFormatVersion: "2010-09-09"
Resources:
  WebSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Web server
      GroupName: web     
      VpcId: vpc-abc01234
      SecurityGroupIngress:
        -
          IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 0.0.0.0/0
        -
          IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: 0.0.0.0/0

Another example:

AWSTemplateFormatVersion: "2010-09-09"
Resources:  
  DatabaseSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Database server
      GroupName: database     
      VpcId: vpc-abc01234
      SecurityGroupIngress:
        -
          IpProtocol: tcp
          FromPort: 3306
          ToPort: 3306
          SourceSecurityGroupId: sg-abc01234

Another example using referencing:

AWSTemplateFormatVersion: "2010-09-09"
Resources:  
  WebSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Web server
      GroupName: web     
      VpcId: vpc-abc01234
      SecurityGroupIngress:
        -
          IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 0.0.0.0/0

  DatabaseSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Database server
      GroupName: database     
      VpcId: vpc-abc01234
      SecurityGroupIngress:
        -
          IpProtocol: tcp
          FromPort: 3306
          ToPort: 3306
          SourceSecurityGroupId: !Ref WebSecurityGroup

Self referencing a Security Group:

AWSTemplateFormatVersion: "2010-09-09"
Resources: 
  SwarmSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Swarm server
      GroupName: swarm
      VpcId: vpc-abc01234

  SwarmIngress1:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !Ref SwarmSecurityGroup
      IpProtocol: tcp
      FromPort: 2377
      ToPort: 2377
      SourceSecurityGroupId: !Ref SwarmSecurityGroup

  SwarmIngress2:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !Ref SwarmSecurityGroup
      IpProtocol: tcp
      FromPort: 7946
      ToPort: 7946
      SourceSecurityGroupId: !Ref SwarmSecurityGroup

  SwarmIngress3:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !Ref SwarmSecurityGroup
      IpProtocol: udp
      FromPort: 7946
      ToPort: 7946
      SourceSecurityGroupId: !Ref SwarmSecurityGroup
  
  SwarmIngress4:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !Ref SwarmSecurityGroup
      IpProtocol: udp
      FromPort: 4789
      ToPort: 4789
      SourceSecurityGroupId: !Ref SwarmSecurityGroup

Attaching a Security group to an Instance

AWSTemplateFormatVersion: "2010-09-09"
Resources:
  WebSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Web server
      GroupName: web     
      VpcId: vpc-abc01234
      SecurityGroupIngress:
        -
          IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 0.0.0.0/0

  WebInstance:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: t2.nano
      ImageId: ami-80861296
      KeyName: my-key
      SecurityGroupIds:
        - !Ref WebSecurityGroup
      SubnetId: subnet-abc01234

Using an Elastic IP

AWSTemplateFormatVersion: "2010-09-09"
Resources:
  WebInstance:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: t2.nano
      ImageId: ami-80861296
      KeyName: my-key
      SecurityGroupIds:
        - sg-abc01234
      SubnetId: subnet-abc01234
  
  WebElasticIp:
    Type: AWS::EC2::EIP
    Properties:
      InstanceId: !Ref WebInstance
      Domain: vpc

Using it all together in a single template

AWSTemplateFormatVersion: "2010-09-09"
Resources:
  
  ## Security group for WebInstance enabling port 80
  ## from all IP addresses
  WebSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Web server
      GroupName: web     
      VpcId: vpc-abc01234
      SecurityGroupIngress:
        -
          IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 0.0.0.0/0
 
  ## EC2 Instance with a custom security group
  ## and a larger root instance device
  ## and an externally created EBS volume attached
  WebInstance:
    Type: AWS::EC2::Instance
    Properties:
      BlockDeviceMappings:
        -
          DeviceName: "/dev/sda1"
          Ebs:
            VolumeSize: 24
            VolumeType: gp2
      InstanceType: t2.nano
      ImageId: ami-80861296
      KeyName: my-key
      Monitoring: true
      SecurityGroupIds:
        - !Ref WebSecurityGroup
      SubnetId: subnet-abc01234
      Tags:
        -
          Key: Name
          Value: webserver
      Volumes:
        -
          Device: "/dev/sdf"
          VolumeId: !Ref LogVolume
  
  ## EBS Volume for storing web logs
  LogVolume:
    Type: AWS::EC2::Volume
    DeletionPolicy: Snapshot
    Properties:
      AvailabilityZone: us-east-1a
      Size: 64
      Tags:
        -
          Key: Name
          Value: web-log-volume
      VolumeType: gp2

  ## Attach EIP to the instance
  WebElasticIp:
    Type: AWS::EC2::EIP
    Properties:
      InstanceId: !Ref WebInstance
      Domain: vpc