I sometimes fire up EC2 instances and forget about them while they’re starting up - only to realise they’ve been running happily for the last 10mns. Thankfully that’s relatively easy to achieve with SNS and minimal plumbing.

To follow along you’ll need to have the aws tools set up. The instructions are available here. Don’t forget to run aws configure to add in your credentials.

Creating an SNS topic

With the aws CLI installed, we can create a topic on the fly. We’ll call ours ec2-up-notification.

vagrant@vagrant:/tmp$ aws sns create-topic --name ec2-up-notification
{
    "TopicArn": "arn:aws:sns:us-east-1:530738210011:ec2-up-notification"
}

This returns a JSON msg with a TopicArn key which we will need later. We confirm it has been properly created:

vagrant@vagrant:/tmp$ aws sns list-topics
{
    "Topics": [
        {
            "TopicArn": "arn:aws:sns:us-east-1:530738210011:ec2-up-notification"
        }
    ]
}

Creating a subscription

Those notifications need an endpoint. For simplicity we’ll assume an email address is good enough.

vagrant@vagrant:/tmp$ aws sns subscribe --topic-arn "arn:aws:sns:us-east-1:530738210011:ec2-up-notification" --protocol email-json --notification-endpoint foo@gmail.com
{
    "SubscriptionArn": "pending confirmation"
}
vagrant@vagrant:/tmp$ aws sns list-subscriptions-by-topic --topic-arn "arn:aws:sns:us-east-1:530738210011:ec2-up-notification"
{
    "Subscriptions": [
        {
            "Owner": "530738210011",
            "Endpoint": "foo@gmail.com",
            "Protocol": "email-json",
            "TopicArn": "arn:aws:sns:us-east-1:530738210011:ec2-up-notification",
            "SubscriptionArn": "PendingConfirmation"
        }
    ]
}

Note that email subscriptions require you to validate the email address (a subscription message will be sent from AWS along with a URL). Once we do this we can confirm we’re all set:

vagrant@vagrant:/tmp$ aws sns list-subscriptions-by-topic --topic-arn "arn:aws:sns:us-east-1:530738210011:ec2-up-notification"
{
    "Subscriptions": [
        {
            "Owner": "530738210011",
            "Endpoint": "foo@gmail.com",
            "Protocol": "email-json",
            "TopicArn": "arn:aws:sns:us-east-1:530738210011:ec2-up-notification",
            "SubscriptionArn": "arn:aws:sns:us-east-1:530738210011:ec2-up-notification:af67f9dd-12be-4ce4-b937-a0d8af48be84"
        }
    ]
}

The SubscriptionArn key has been changed from “PendingConfirmation” to a proper ARN. We can check the endpoint works as expected by doing a dummy publish:

vagrant@vagrant:/tmp$ aws sns publish --topic-arn "arn:aws:sns:us-east-1:530738210011:ec2-up-notification" --message "Hello!" --subject "SNS notification coming through!"
{
    "MessageId": "ab4afabf-6b16-531f-95c5-aba905649c0d"
}

Which should end up right in your inbox and look a little like:

{
  "Type" : "Notification",
  "MessageId" : "ab4afabf-6b16-531f-95c5-aba905649c0d",
  "TopicArn" : "arn:aws:sns:us-east-1:530738210011:ec2-up-notification",
  "Subject" : "SNS notification coming through!",
  "Message" : "Hello!",
...

IAM and the startup script

We’re almost done. Before our EC2 can send messages to SNS, it’ll need to have the right permissions. To do this we’ll create a new role in IAM called ‘EC2-SNS’ and grant it the AmazonSNSFullAccess (though technically we should only need the sns:Publish but that would require us to create a custom policy - which you’d probably want to do in a production setting anyway).

A notification is well and good, but let’s make this useful by also sending the box’s public hostname which we can easily get from the meta-data url. For simplicity, we’ll output this to a file. The script will be as follows:

#!/bin/sh
curl http://169.254.169.254/latest/meta-data/public-hostname > msg.txt
aws sns publish --topic-arn "arn:aws:sns:us-east-1:530738210011:ec2-up-notification" --message file://msg.txt --subject "EC2 instance up and running" --region us-east-1

We can now kick off the instance and shortly afterwards receive something like the below in your inbox:

{
  "Type" : "Notification",
  "MessageId" : "4f222bd3-a332-58e7-a30e-7ac54ca4f9d4",
  "TopicArn" : "arn:aws:sns:us-east-1:530738210011:ec2-up-notification",
  "Subject" : "EC2 instance up and running",
  "Message" : "ec2-54-90-212-175.compute-1.amazonaws.com",

No more missing out on instances already running!

Conclusion

I was really tempted to use SMS but the cost in Singapore can be quite expensive! A much cheaper alternative would be to use their push functionality via, say, Google Cloud Notifications but this would require you to create an app with the correct API keys etc… Something to look at if you were to use SNS for alerting.