CloudFormation
01 / 02

Templates, Resources & Parameters

CloudFormation: Templates, Resources & Parameters

AWS CloudFormation lets you model and provision AWS infrastructure using YAML or JSON templates. A template defines the desired state; CloudFormation handles create/update/delete in the right order based on dependencies.

Template Structure

AWSTemplateFormatVersion: '2010-09-09'
Description: 'My Application Stack'

# Metadata (optional — controls console display)
Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label: { default: "Network Configuration" }
        Parameters: [VpcId, SubnetId]

# Parameters — inputs (override at deploy time)
Parameters:
  Environment:
    Type: String
    Default: dev
    AllowedValues: [dev, staging, prod]
    Description: Deployment environment

  InstanceType:
    Type: String
    Default: t3.micro
    AllowedValues: [t3.micro, t3.small, t3.medium]

  DbPassword:
    Type: String
    NoEcho: true     # hides value in console/CLI output
    MinLength: 8

# Mappings — lookup table by key
Mappings:
  RegionAMI:
    us-east-1:
      AMI: ami-0c02fb55956c7d316
    eu-west-1:
      AMI: ami-0d71ea30463e0ff49

# Conditions
Conditions:
  IsProduction: !Equals [!Ref Environment, prod]
  CreateProdResources: !And
    - !Condition IsProduction
    - !Not [!Equals [!Ref InstanceType, t3.micro]]

# Resources — required, the actual infrastructure
Resources:
  MyBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Sub 'my-app-${Environment}-${AWS::AccountId}'
      VersioningConfiguration:
        Status: Enabled
      Tags:
        - Key: Environment
          Value: !Ref Environment

# Outputs — values to expose after stack creation
Outputs:
  BucketName:
    Description: Name of the S3 bucket
    Value: !Ref MyBucket
    Export:
      Name: !Sub '${AWS::StackName}-BucketName'   # for cross-stack references

Common Resource Types

Resources:

  # EC2 Instance
  WebServer:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: !Ref InstanceType
      ImageId: !FindInMap [RegionAMI, !Ref AWS::Region, AMI]
      KeyName: my-keypair
      SecurityGroupIds: [!Ref WebSG]
      SubnetId: !Ref PublicSubnet
      UserData:
        Fn::Base64: |
          #!/bin/bash
          yum update -y
          yum install -y httpd
          systemctl start httpd
      Tags:
        - Key: Name
          Value: !Sub '${AWS::StackName}-WebServer'

  # Security Group
  WebSG:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Web server security group
      VpcId: !Ref VPC
      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

  # RDS
  Database:
    Type: AWS::RDS::DBInstance
    DeletionPolicy: Snapshot          # take snapshot on stack delete
    Properties:
      DBInstanceClass: db.t3.micro
      Engine: postgres
      EngineVersion: '15.4'
      MasterUsername: admin
      MasterUserPassword: !Ref DbPassword
      AllocatedStorage: 20
      StorageType: gp3
      MultiAZ: !If [IsProduction, true, false]
      DeletionProtection: !If [IsProduction, true, false]

  # Lambda
  ProcessorFunction:
    Type: AWS::Lambda::Function
    Properties:
      FunctionName: !Sub '${AWS::StackName}-processor'
      Runtime: python3.12
      Handler: index.handler
      Role: !GetAtt LambdaRole.Arn
      Code:
        ZipFile: |
          def handler(event, context):
              return {'statusCode': 200}
      Environment:
        Variables:
          ENV: !Ref Environment
          TABLE_NAME: !Ref DynamoTable

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free