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