{ "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" ]} } } }