Automatically Updating Route53 with Public IP Address from EC2 Instance

So when you're trying to bootstrap a SaaS offering, and your wife has access to the credit card statements, sometimes you go to extreme lengths to shave costs. (And end up going down a very deep yak shaving hole.)

In my case, rather than paying for a hosted AuthN solution, I'm self-hosting on EC2 instances. (Because one day my product will be immensely popular and have millions of users and I don't want to pay the $.02 per MAU when I get there.) And because this is my dev environment, I'll be shutting down my instances at the end of the day so I'm not paying the $0.0168 per instance-hour that I'm not using them.

As I said: extreme lengths to shave costs.

In any case, when an EC2 instance is restarted, AWS will assign a new public IP address to the instance. Which means that any Route53 record sets for the host will need to be repopulated with the instance's new public IP address.

If you search the Internet, you'll find several solutions for doing this, but everything I found out there was too complex for my tastes. This really is a simple requirement, and it turns out that meeting this requirement really is pretty simple. (At least on Amazon Linux, where the aws CLI is preinstalled.)

The solution is to use the AWS CLI to update the DNS record. The command looks like this:

aws route53 change-resource-record-sets --hosted-zone-id <ZoneID> --change-batch file://<filename>

The command parses a JSON file with the changeset data in it. To update a single A record with a single IP address, the file looks like this:

{
    "Changes": [
        {
            "Action" : "UPSERT",
            "ResourceRecordSet": {
                "Name": "<hostname>.your.domain.com",
                "Type": "A",
                "TTL": 60,
                "ResourceRecords": [
                    {"Value": "<ip>"}
                ]
            }
        }
    ]
}

The placeholders for the hostname and the IP address should be obvious there. Save this file as route53update.template.

So to execute the aws CLI command above, we need a script to retrieve three values:

  • The DNS Zone ID
  • The hostname
  • The public IP address

There are two ways to get the Route53 Zone ID: either hardcode it into the script, or put it in a tag on the instance. If you put the Zone ID in a tag, ensure that "Allow tags in instance metadata" is enabled for the instance. To get the value of the tag from inside the instance, run curl http://169.254.169.254/latest/meta-data/tags/instance/DNSZONE.

Getting the hostname is easy: use the hostname command. (The hostname can be set with sudo hostnamectl set-hostname myhostname and rebooting.)

The public IP address can be found with curl http://169.254.169.254/latest/meta-data/public-ipv4.

Tying it all together, updating the public IP address in Route53 requires us to:

  1. Create a .json file from the template, replacing the IP address and hostname placeholders, and then
  2. Run the aws cli to update the Route53 record, feeding it the newly created .json file

Step 1:

sed 's/<hostname>/'"$(hostname)"/ route53update.template | sed 's/<ip>/'"$(curl http://169.254.169.254/latest/meta-data/public-ipv4)"/ > route53update.json

Step 2:

aws route53 change-resource-record-sets --hosted-zone-id $(curl http://169.254.169.254/latest/meta-data/tags/instance/DNSZONE) --change-batch file://route53update.json

So create a shell script with those two lines in it, updateroute53.sh:

#!/bin/bash
cd "$(dirname "$0")"
sed 's/<hostname>/'"$(hostname)"/ /full/path/to/route53update.template | sed 's/<ip>/'"$(curl http://169.254.169.254/latest/meta-data/public-ipv4)"/ > route53update.json
aws route53 change-resource-record-sets --hosted-zone-id $(curl http://169.254.169.254/latest/meta-data/tags/instance/DNSZONE) --change-batch file://route53update.json

Run chmod +x updateroute53.sh to make the script executable.

The final piece of the puzzle is giving your EC2 instance permissions to update records in the Route53 hosted zone. Create an IAM role for EC2, and in the inline policy, grant the route53:ChangeResourceRecordSets permission on your hosted zone. This can be done in the visual editor, or use this JSON:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "route53:ChangeResourceRecordSets",
            "Resource": "arn:aws:route53:::hostedzone/<YourZoneID>"
        }
    ]
}

Note that this does give your instance permissions to update any record in the zone, so be aware of this security issue. Use conditionals on the Allow grant to limit the scope of what the role can do if you'd like.

Attach the new IAM role to your instance and run your script to ensure it works.

Lastly, to make this script run every time the instance boots. Cloud-init will automatically run any scripts in /var/lib/cloud/scripts/per-boot/ on every boot. So either put your script in that directory, or create a symlink there.

The STM32F429I-DISCO Tutorial Series, Part 5: GPIO: Lighting an LED when the Button is Pressed Using Polling

All right, now that we have our build environment set up and have tested our ability to download code to the target STM32F429 Discovery board, let's write a program that will actually do something.

In this case, we're going to write a program that will light the LED when the button is pressed, and extinguish the LED when the button is released. (Oooh! Exciting!) We're going to build the project a few different ways throughout this tutorial series to understand some of the capabilities of the STM32F429. The first method we're going to use is simple, straightforward, and horribly inefficient. It's called polling.

Basically, our code is going to have a main loop that will poll the button every time through. Kind of like kids in the back seat on a long car trip, our code will be constantly asking, "Is the button pressed now? Is the button pressed now? Is the button pressed now? Is the button pressed now?"

Polling is effective, but as we'll see in a later installment, it's not the most efficient use of the CPU and there are often better solutions. For now, though, it's quick and easy, so let's go! Continue reading The STM32F429I-DISCO Tutorial Series, Part 5: GPIO: Lighting an LED when the Button is Pressed Using Polling

The STM32F429I-DISCO Tutorial Series, Part 4: Building a Skeleton Project

In part 3 of the tutorial series, we installed System Workbench for STM32, which is an Eclipse-based IDE, onto our computer. We then installed both the standalone and Eclipse plug-in versions of STM32CubeMX, which is ST's code generation tool.

Today, we're going to use those tools to build a skeleton program, and download that program to our STM32F429I-DISCO board. Now, our program isn't going to actually do anything (we'll leave that to our next tutorial installment), but we will effectively ensure that our build environment and our debugger interface are working.

So let's get started! Continue reading The STM32F429I-DISCO Tutorial Series, Part 4: Building a Skeleton Project

The STM32F429I-DISCO Tutorial Series, Part 3: The Build Environment

Before we can program the STM32F429, we need a development environment.

To ensure that what worked for me will also work for you, I'm going to start with a brand-new virtual machine and do all my work in the VM. This ensures that I don't have any pre-existing dependencies installed on my machine that you don't have on yours.

In many ways, this series of posts will be the reviews of STM32CubeMX and System Workbench for STM32 that I promised to write a few years ago but never did.

Note: Since I started working with STM32 series microcontrollers, ST Micro has purchased Atollic, the vendor behind the TrueStudio development environment. ST has publicly commented that they intend to support both TrueStudio and System Workbench going forward. While this may be true at the current time, I am highly skeptical that ST will continue their relationship with AC6 to support System Workbench over the long haul when they own a competing product. However, since I've grown to be somewhat familiar with System Workbench, I've decided to write my tutorials with this tool despite my reservations about the long term viability of the product. The good news is, should ST abandon System Workbench in favor of TrueStudio, the migration should be reasonably straightforward.

So... let's get started!

Continue reading The STM32F429I-DISCO Tutorial Series, Part 3: The Build Environment

The STM32F429I-DISCO Tutorial Series, Part 2: Exploring the STM32F429-DISCOVERY: the Stuff you Need to Know

With our last update, we looked at some of the features of the STM32F429ZTI chip on the STM32F429-DISCO board. Today, let's look at some of the features of the Discovery board on which the chip is mounted.

A dev board, of course, is more than just the processor on the board. A manufacturer will (hopefully) include a smattering of other devices on the board to help demonstrate the features of the microcontroller. In the case of the F429 Discovery board, the following features are included: Continue reading The STM32F429I-DISCO Tutorial Series, Part 2: Exploring the STM32F429-DISCOVERY: the Stuff you Need to Know

The STM32F429I-DISCO Tutorial Series, Part 1: Exploring the STM32F429; the Stuff you Need to Know

We're going to be working with the STM32F429 Discovery board. There are two variants of this board and it's spelled different ways in different places, but for our purposes they're all the same. (The differences between the two are solely in the ST-LINK debugger portion of the board.)  In case you haven't seen it, the board looks like this (as always, click on the thumbnail for a full-size image):

STM32F429-DISCOVERYboard

Let's kick off our tutorial of the STM32F429-DISCOVERY board by talking about the microcontroller that's soldered to it: the STM32F429ZIT6. Continue reading The STM32F429I-DISCO Tutorial Series, Part 1: Exploring the STM32F429; the Stuff you Need to Know

The STM32F429I-DISCO Tutorial Series: Introduction

I recently had an embedded project idea that requires a graphical user interface (GUI) on an LCD screen and the use of a computer mouse. The STM32F429I-DISCO board, with its onboard STM32F429ZIT6 microcontroller, is perfect for this application. With the free (as in beer) tools that ST has released, and the STemWin and/or TouchGFX graphics libraries that have been made available, I figured that it would be trivial to get a simple GUI up and running on this board.

Of course, reality came crashing down around me.

So, after putting the pieces of the puzzle together, I thought I'd share with you my attempt at creating a GUI program from scratch for the STM32F429 discovery board. Like I did in my series on building a toolchain for the STM32 processors (which, by the way, you shouldn't use any more now that ST and AC6 have released System Workbench for STM32), we'll do this the long way, so that we learn what each step along the way does. We'll visit many of the STM32F429's integrated peripherals along the way. By the end of this series of blog posts, you should have a solid understanding of how to build a GUI program (and, by extension, just about any program) from scratch for the ST series of processors.

Note that I'm not done writing this stuff yet, and I don't know for sure where I'll end up, but I have some Big Plans ahead! Continue reading The STM32F429I-DISCO Tutorial Series: Introduction

Two and a Half Years Later…

So I see that it's been quite a while since I posted.

In that time, I got divorced, got remarried, and earned a master's degree.

I'd like to get back into electronics, and I'd like to keep sharing my experiences here.

The truth, though, is that life is busy. I have a job. I have three kids. And a wife. And oh, my wife is in school, so a lot of the housework is going to fall to my shoulders.

So... I guess we'll just have to see. Hope to see y'all soon with something interesting.

The Super Kickass Temperature Logger Thingamabob

It all started with an email. (Don't they always?)

In this case, the email was from the Dallas Coding Workshops and Hackathons group at meetup.com. Now, I've been a member of meetup.com for a long time, and I've signed up for many more meetup groups than I probably should have, and for the most part, I've found that emails from meetup.com are for events that I'm either not interested in, or that I'm not available to attend. In this case, however, the planets aligned: this was an event that both interested me, and for which I had the time to attend! The email came on August 10 and announced a Hackaton the weekend of August 19-20. I checked my calendar and found that I don't have the kids that week (yes, that's foreshadowing; stay tuned), and there was nothing pressing on my calendar.

For the first time in a long time, I clicked "YES" on the "Are you going?" link that meetup.com provided me. Continue reading The Super Kickass Temperature Logger Thingamabob