{
"AWSTemplateFormatVersion" : "2010-09-09",
"Description" : "Alestic email-relay-dash-to-plus https://github.com/alestic/alestic-email-relay-dash-to-plus",
"Parameters" : {
"InstanceType" : {
"Description" : "Server EC2 instance type",
"Type" : "String",
"Default" : "t3.micro"
},
"OperatorEmail": {
"Description": "Email address to notify if there are any scaling operations",
"Type" : "String",
"Default": "your-address@example.com"
},
"SshKeyName" : {
"Description" : "The EC2 Key Pair to allow SSH access to the instances",
"Type" : "String",
"Default": "your-ssh-keypair"
},
"DnsDomain" : {
"Type" : "String",
"Description" : "The DNS domain name of an existing Amazon Route 53 hosted zone",
"Default" : "example.com"
},
"DnsHostName" : {
"Type" : "String",
"Description" : "The short DNS host name for the service endpoint (no domain)",
"Default" : "email-relay-dash-to-plus"
},
"MinInstances" : {
"Description" : "Minimum number of instances to keep running",
"Type" : "Number",
"Default" : "1"
},
"MaxInstances" : {
"Description" : "Maximum number of instances during scaling",
"Type" : "Number",
"Default" : "1"
},
"InstallScriptURL" : {
"Description" : "URL of script to install/configure new instances",
"Type" : "String",
"Default" : "https://raw.githubusercontent.com/alestic/alestic-email-relay-dash-to-plus/master/email-relay-dash-to-plus-install-2204"
}
},
"Mappings" : {
# Ubuntu 22.04 LTS jammy amd64 hvm:ebs-ssd
"AMIRegionMap" : {
"us-east-1" : { "AMIID" : "ami-051dcca84f1edfff1" }, # 20220712.1
"us-west-2" : { "AMIID" : "ami-04a32162efe87cb4c" } # 20220712.1
# # Ubuntu 18.04 LTS bionic amd64 hvm:ebs-ssd
# "us-east-1" : { "AMIID" : "ami-09499f802f26db67e" }, # 20220805
# "us-west-2" : { "AMIID" : "ami-0b9dc4709feb21c9c" } # 20220805
# # Ubuntu 16.04 LTS xenial amd64 hvm:ebs-ssd
# "us-west-2" : { "AMIID" : "ami-835b4efa" } # 20170619
}
},
"Resources" : {
"NotificationTopic": {
"Type": "AWS::SNS::Topic",
"Properties": {
"Subscription": [ {
"Endpoint": { "Ref": "OperatorEmail" },
"Protocol": "email" } ]
}
},
"ServerGroup" : {
"Type" : "AWS::AutoScaling::AutoScalingGroup",
"Properties" : {
"AvailabilityZones" : { "Fn::GetAZs" : ""},
"LaunchConfigurationName" : { "Ref" : "LaunchConfig" },
"MinSize" : {"Ref" : "MinInstances" },
"MaxSize" : {"Ref" : "MaxInstances" },
"LoadBalancerNames" : [ { "Ref" : "ElasticLoadBalancer" } ],
"NotificationConfiguration" : {
"TopicARN" : { "Ref" : "NotificationTopic" },
"NotificationTypes" : [ "autoscaling:EC2_INSTANCE_LAUNCH","autoscaling:EC2_INSTANCE_LAUNCH_ERROR","autoscaling:EC2_INSTANCE_TERMINATE", "autoscaling:EC2_INSTANCE_TERMINATE_ERROR"]
}
}
},
"LaunchConfig" : {
"Type" : "AWS::AutoScaling::LaunchConfiguration",
"Properties" : {
"KeyName" : { "Ref" : "SshKeyName" },
"ImageId" : { "Fn::FindInMap" : [ "AMIRegionMap", { "Ref" : "AWS::Region" }, "AMIID" ] },
"SecurityGroups" : [ { "Fn::GetAtt" : [ "InstanceSecurityGroup", "GroupId" ] } ],
"InstanceType" : { "Ref" : "InstanceType" },
"InstanceMonitoring": "true",
"UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
"#!/bin/bash -ex\n",
"exec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1\n",
"install=$(mktemp /tmp/install.XXXXXX)\n",
"curl --location --retry 10 -o $install ", { "Ref" : "InstallScriptURL" }, "\n",
"chmod 700 $install", "\n",
"$install ",
"'", { "Ref" : "DnsDomain" }, "' ",
"'", { "Ref" : "DnsHostName" }, "' ",
"'", { "Ref" : "WaitForInstanceWaitHandle" }, "' ",
"'", { "Ref" : "OperatorEmail" }, "' ",
"\n",
""
]]}}
}
},
"ServerScaleUpPolicy" : {
"Type" : "AWS::AutoScaling::ScalingPolicy",
"Properties" : {
"AdjustmentType" : "ChangeInCapacity",
"AutoScalingGroupName" : { "Ref" : "ServerGroup" },
"Cooldown" : "60",
"ScalingAdjustment" : "1"
}
},
"ServerScaleDownPolicy" : {
"Type" : "AWS::AutoScaling::ScalingPolicy",
"Properties" : {
"AdjustmentType" : "ChangeInCapacity",
"AutoScalingGroupName" : { "Ref" : "ServerGroup" },
"Cooldown" : "60",
"ScalingAdjustment" : "-1"
}
},
"CPUAlarmHigh": {
"Type": "AWS::CloudWatch::Alarm",
"Properties": {
"AlarmDescription": "Scale-up if CPU > 90% for 10 minutes",
"MetricName": "CPUUtilization",
"Namespace": "AWS/EC2",
"Statistic": "Average",
"Period": "300",
"EvaluationPeriods": "2",
"Threshold": "90",
"AlarmActions": [ { "Ref": "ServerScaleUpPolicy" } ],
"Dimensions": [
{
"Name": "AutoScalingGroupName",
"Value": { "Ref": "ServerGroup" }
}
],
"ComparisonOperator": "GreaterThanThreshold"
}
},
"CPUAlarmLow": {
"Type": "AWS::CloudWatch::Alarm",
"Properties": {
"AlarmDescription": "Scale-down if CPU < 40% for 10 minutes",
"MetricName": "CPUUtilization",
"Namespace": "AWS/EC2",
"Statistic": "Average",
"Period": "300",
"EvaluationPeriods": "2",
"Threshold": "40",
"AlarmActions": [ { "Ref": "ServerScaleDownPolicy" } ],
"Dimensions": [
{
"Name": "AutoScalingGroupName",
"Value": { "Ref": "ServerGroup" }
}
],
"ComparisonOperator": "LessThanThreshold"
}
},
"ElasticLoadBalancer" : {
"Type" : "AWS::ElasticLoadBalancing::LoadBalancer",
"Properties" : {
"AvailabilityZones" : { "Fn::GetAZs" : "" },
"Listeners" : [ {
"LoadBalancerPort" : "25",
"InstancePort" : "25",
"Protocol" : "TCP"
} ],
"HealthCheck" : {
"Target" : "TCP:22",
"HealthyThreshold" : "2",
"UnhealthyThreshold" : "5",
"Interval" : "20",
"Timeout" : "5"
}
}
},
"WaitForInstanceWaitHandle" : {
"Type" : "AWS::CloudFormation::WaitConditionHandle",
"Properties" : {
}
},
"WaitForInstance" : {
"Type" : "AWS::CloudFormation::WaitCondition",
"DependsOn" : "ServerGroup",
"Properties" : {
"Handle" : {"Ref" : "WaitForInstanceWaitHandle"},
"Timeout" : "1800"
}
},
"InstanceSecurityGroup" : {
"Type" : "AWS::EC2::SecurityGroup",
"Properties" : {
"GroupDescription" : "SSH access from anywhere; TCP from the load balancer",
"SecurityGroupIngress" : [ {
"IpProtocol" : "tcp",
"FromPort" : "22",
"ToPort" : "22",
"CidrIp" : "0.0.0.0/0"
},
{
"IpProtocol" : "tcp",
"FromPort" : "25",
"ToPort" : "25",
"SourceSecurityGroupOwnerId" : {"Fn::GetAtt" : ["ElasticLoadBalancer", "SourceSecurityGroup.OwnerAlias"]},
"SourceSecurityGroupName" : {"Fn::GetAtt" : ["ElasticLoadBalancer", "SourceSecurityGroup.GroupName"]}
} ]
}
},
"DnsRecord" : {
"Type" : "AWS::Route53::RecordSet",
"Properties" : {
"HostedZoneName" : { "Fn::Join" : [ "", [{ "Ref" : "DnsDomain" }, "." ]]},
"Comment" : { "Fn::Join" : [ "", [ "CNAME to ELB for ", { "Ref" : "AWS::StackName" }]]},
"Name" : { "Fn::Join" : [ "", [{ "Ref" : "DnsHostName" }, ".", { "Ref" : "DnsDomain" }, "."]]},
"Type" : "CNAME",
"TTL" : "300",
"ResourceRecords" : [{ "Fn::GetAtt" : [ "ElasticLoadBalancer", "DNSName" ]}]
}
}
},
"Outputs" : {
"EmailRoutingDestination" : {
"Value" : { "Ref" : "DnsRecord" }
},
"ELBDnsName" : {
"Value" : { "Fn::GetAtt" : [ "ElasticLoadBalancer", "DNSName" ]}
}
}
}